xfs: fix type confusion in xfs_ioc_swapext
[cascardo/linux.git] / fs / xfs / xfs_ioctl.c
index bcb6c19..408f3ad 100644 (file)
@@ -277,7 +277,6 @@ xfs_readlink_by_handle(
 {
        struct dentry           *dentry;
        __u32                   olen;
-       void                    *link;
        int                     error;
 
        if (!capable(CAP_SYS_ADMIN))
@@ -288,7 +287,7 @@ xfs_readlink_by_handle(
                return PTR_ERR(dentry);
 
        /* Restrict this handle operation to symlinks only. */
-       if (!d_is_symlink(dentry)) {
+       if (!d_inode(dentry)->i_op->readlink) {
                error = -EINVAL;
                goto out_dput;
        }
@@ -298,21 +297,8 @@ xfs_readlink_by_handle(
                goto out_dput;
        }
 
-       link = kmalloc(MAXPATHLEN+1, GFP_KERNEL);
-       if (!link) {
-               error = -ENOMEM;
-               goto out_dput;
-       }
-
-       error = xfs_readlink(XFS_I(d_inode(dentry)), link);
-       if (error)
-               goto out_kfree;
-       error = readlink_copy(hreq->ohandle, olen, link);
-       if (error)
-               goto out_kfree;
+       error = d_inode(dentry)->i_op->readlink(dentry, hreq->ohandle, olen);
 
- out_kfree:
-       kfree(link);
  out_dput:
        dput(dentry);
        return error;
@@ -334,12 +320,10 @@ xfs_set_dmattrs(
        if (XFS_FORCED_SHUTDOWN(mp))
                return -EIO;
 
-       tp = xfs_trans_alloc(mp, XFS_TRANS_SET_DMATTRS);
-       error = xfs_trans_reserve(tp, &M_RES(mp)->tr_ichange, 0, 0);
-       if (error) {
-               xfs_trans_cancel(tp);
+       error = xfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 0, 0, 0, &tp);
+       if (error)
                return error;
-       }
+
        xfs_ilock(ip, XFS_ILOCK_EXCL);
        xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
 
@@ -1141,10 +1125,9 @@ xfs_ioctl_setattr_get_trans(
        if (XFS_FORCED_SHUTDOWN(mp))
                goto out_unlock;
 
-       tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_NOT_SIZE);
-       error = xfs_trans_reserve(tp, &M_RES(mp)->tr_ichange, 0, 0);
+       error = xfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 0, 0, 0, &tp);
        if (error)
-               goto out_cancel;
+               return ERR_PTR(error);
 
        xfs_ilock(ip, XFS_ILOCK_EXCL);
        xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL | join_flags);
@@ -1592,6 +1575,17 @@ xfs_ioc_swapext(
                goto out_put_tmp_file;
        }
 
+       /*
+        * We need to ensure that the fds passed in point to XFS inodes
+        * before we cast and access them as XFS structures as we have no
+        * control over what the user passes us here.
+        */
+       if (f.file->f_op != &xfs_file_operations ||
+           tmp.file->f_op != &xfs_file_operations) {
+               error = -EINVAL;
+               goto out_put_tmp_file;
+       }
+
        ip = XFS_I(file_inode(f.file));
        tip = XFS_I(file_inode(tmp.file));