]> err.no Git - linux-2.6/blobdiff - fs/xfs/linux-2.6/xfs_ioctl.c
Merge branch 'master' of /pub/scm/linux/kernel/git/torvalds/linux-2.6
[linux-2.6] / fs / xfs / linux-2.6 / xfs_ioctl.c
index 9bba9f8be1eb886e4d9f335a4927e8118724cf4b..a9952e490ac9c7458cc5110e7d84b09fc45c867b 100644 (file)
@@ -75,7 +75,6 @@ xfs_find_handle(
        xfs_handle_t            handle;
        xfs_fsop_handlereq_t    hreq;
        struct inode            *inode;
-       bhv_vnode_t             *vp;
 
        if (copy_from_user(&hreq, arg, sizeof(hreq)))
                return -XFS_ERROR(EFAULT);
@@ -92,10 +91,10 @@ xfs_find_handle(
                if (error)
                        return error;
 
-               ASSERT(nd.dentry);
-               ASSERT(nd.dentry->d_inode);
-               inode = igrab(nd.dentry->d_inode);
-               path_release(&nd);
+               ASSERT(nd.path.dentry);
+               ASSERT(nd.path.dentry->d_inode);
+               inode = igrab(nd.path.dentry->d_inode);
+               path_put(&nd.path);
                break;
        }
 
@@ -134,28 +133,24 @@ xfs_find_handle(
                return -XFS_ERROR(EBADF);
        }
 
-       /* we need the vnode */
-       vp = vn_from_inode(inode);
-
        /* now we can grab the fsid */
-       memcpy(&handle.ha_fsid, vp->v_vfsp->vfs_altfsid, sizeof(xfs_fsid_t));
+       memcpy(&handle.ha_fsid, XFS_I(inode)->i_mount->m_fixedfsid,
+                       sizeof(xfs_fsid_t));
        hsize = sizeof(xfs_fsid_t);
 
        if (cmd != XFS_IOC_PATH_TO_FSHANDLE) {
-               xfs_inode_t     *ip;
+               xfs_inode_t     *ip = XFS_I(inode);
                int             lock_mode;
 
                /* need to get access to the xfs_inode to read the generation */
-               ip = xfs_vtoi(vp);
-               ASSERT(ip);
                lock_mode = xfs_ilock_map_shared(ip);
 
                /* fill in fid section of handle from inode */
-               handle.ha_fid.xfs_fid_len = sizeof(xfs_fid_t) -
-                                           sizeof(handle.ha_fid.xfs_fid_len);
-               handle.ha_fid.xfs_fid_pad = 0;
-               handle.ha_fid.xfs_fid_gen = ip->i_d.di_gen;
-               handle.ha_fid.xfs_fid_ino = ip->i_ino;
+               handle.ha_fid.fid_len = sizeof(xfs_fid_t) -
+                                       sizeof(handle.ha_fid.fid_len);
+               handle.ha_fid.fid_pad = 0;
+               handle.ha_fid.fid_gen = ip->i_d.di_gen;
+               handle.ha_fid.fid_ino = ip->i_ino;
 
                xfs_iunlock_map_shared(ip, lock_mode);
 
@@ -175,21 +170,19 @@ xfs_find_handle(
 
 
 /*
- * Convert userspace handle data into vnode (and inode).
- * We [ab]use the fact that all the fsop_handlereq ioctl calls
- * have a data structure argument whose first component is always
- * a xfs_fsop_handlereq_t, so we can cast to and from this type.
- * This allows us to optimise the copy_from_user calls and gives
- * a handy, shared routine.
+ * Convert userspace handle data into inode.
+ *
+ * We use the fact that all the fsop_handlereq ioctl calls have a data
+ * structure argument whose first component is always a xfs_fsop_handlereq_t,
+ * so we can pass that sub structure into this handy, shared routine.
  *
- * If no error, caller must always VN_RELE the returned vp.
+ * If no error, caller must always iput the returned inode.
  */
 STATIC int
 xfs_vget_fsop_handlereq(
        xfs_mount_t             *mp,
        struct inode            *parinode,      /* parent inode pointer    */
        xfs_fsop_handlereq_t    *hreq,
-       bhv_vnode_t             **vp,
        struct inode            **inode)
 {
        void                    __user *hanp;
@@ -198,8 +191,6 @@ xfs_vget_fsop_handlereq(
        xfs_handle_t            *handlep;
        xfs_handle_t            handle;
        xfs_inode_t             *ip;
-       struct inode            *inodep;
-       bhv_vnode_t             *vpp;
        xfs_ino_t               ino;
        __u32                   igen;
        int                     error;
@@ -221,10 +212,10 @@ xfs_vget_fsop_handlereq(
        if (hlen < sizeof(*handlep))
                memset(((char *)handlep) + hlen, 0, sizeof(*handlep) - hlen);
        if (hlen > sizeof(handlep->ha_fsid)) {
-               if (handlep->ha_fid.xfs_fid_len !=
-                               (hlen - sizeof(handlep->ha_fsid)
-                                       - sizeof(handlep->ha_fid.xfs_fid_len))
-                   || handlep->ha_fid.xfs_fid_pad)
+               if (handlep->ha_fid.fid_len !=
+                   (hlen - sizeof(handlep->ha_fsid) -
+                           sizeof(handlep->ha_fid.fid_len)) ||
+                   handlep->ha_fid.fid_pad)
                        return XFS_ERROR(EINVAL);
        }
 
@@ -232,15 +223,15 @@ xfs_vget_fsop_handlereq(
         * Crack the handle, obtain the inode # & generation #
         */
        xfid = (struct xfs_fid *)&handlep->ha_fid;
-       if (xfid->xfs_fid_len == sizeof(*xfid) - sizeof(xfid->xfs_fid_len)) {
-               ino  = xfid->xfs_fid_ino;
-               igen = xfid->xfs_fid_gen;
+       if (xfid->fid_len == sizeof(*xfid) - sizeof(xfid->fid_len)) {
+               ino  = xfid->fid_ino;
+               igen = xfid->fid_gen;
        } else {
                return XFS_ERROR(EINVAL);
        }
 
        /*
-        * Get the XFS inode, building a vnode to go with it.
+        * Get the XFS inode, building a Linux inode to go with it.
         */
        error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_SHARED, &ip, 0);
        if (error)
@@ -252,12 +243,9 @@ xfs_vget_fsop_handlereq(
                return XFS_ERROR(ENOENT);
        }
 
-       vpp = XFS_ITOV(ip);
-       inodep = vn_to_inode(vpp);
        xfs_iunlock(ip, XFS_ILOCK_SHARED);
 
-       *vp = vpp;
-       *inode = inodep;
+       *inode = XFS_ITOV(ip);
        return 0;
 }
 
@@ -274,7 +262,6 @@ xfs_open_by_handle(
        struct file             *filp;
        struct inode            *inode;
        struct dentry           *dentry;
-       bhv_vnode_t             *vp;
        xfs_fsop_handlereq_t    hreq;
 
        if (!capable(CAP_SYS_ADMIN))
@@ -282,7 +269,7 @@ xfs_open_by_handle(
        if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t)))
                return -XFS_ERROR(EFAULT);
 
-       error = xfs_vget_fsop_handlereq(mp, parinode, &hreq, &vp, &inode);
+       error = xfs_vget_fsop_handlereq(mp, parinode, &hreq, &inode);
        if (error)
                return -error;
 
@@ -384,7 +371,6 @@ xfs_readlink_by_handle(
 {
        struct inode            *inode;
        xfs_fsop_handlereq_t    hreq;
-       bhv_vnode_t             *vp;
        __u32                   olen;
        void                    *link;
        int                     error;
@@ -394,7 +380,7 @@ xfs_readlink_by_handle(
        if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t)))
                return -XFS_ERROR(EFAULT);
 
-       error = xfs_vget_fsop_handlereq(mp, parinode, &hreq, &vp, &inode);
+       error = xfs_vget_fsop_handlereq(mp, parinode, &hreq, &inode);
        if (error)
                return -error;
 
@@ -437,34 +423,32 @@ xfs_fssetdm_by_handle(
        struct fsdmidata        fsd;
        xfs_fsop_setdm_handlereq_t dmhreq;
        struct inode            *inode;
-       bhv_vnode_t             *vp;
 
        if (!capable(CAP_MKNOD))
                return -XFS_ERROR(EPERM);
        if (copy_from_user(&dmhreq, arg, sizeof(xfs_fsop_setdm_handlereq_t)))
                return -XFS_ERROR(EFAULT);
 
-       error = xfs_vget_fsop_handlereq(mp, parinode, &dmhreq.hreq, &vp, &inode);
+       error = xfs_vget_fsop_handlereq(mp, parinode, &dmhreq.hreq, &inode);
        if (error)
                return -error;
 
        if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
-               VN_RELE(vp);
-               return -XFS_ERROR(EPERM);
+               error = -XFS_ERROR(EPERM);
+               goto out;
        }
 
        if (copy_from_user(&fsd, dmhreq.data, sizeof(fsd))) {
-               VN_RELE(vp);
-               return -XFS_ERROR(EFAULT);
+               error = -XFS_ERROR(EFAULT);
+               goto out;
        }
 
-       error = xfs_set_dmattrs(xfs_vtoi(vp),
-                       fsd.fsd_dmevmask, fsd.fsd_dmstate);
+       error = -xfs_set_dmattrs(XFS_I(inode), fsd.fsd_dmevmask,
+                                fsd.fsd_dmstate);
 
-       VN_RELE(vp);
-       if (error)
-               return -error;
-       return 0;
+ out:
+       iput(inode);
+       return error;
 }
 
 STATIC int
@@ -477,7 +461,6 @@ xfs_attrlist_by_handle(
        attrlist_cursor_kern_t  *cursor;
        xfs_fsop_attrlist_handlereq_t al_hreq;
        struct inode            *inode;
-       bhv_vnode_t             *vp;
        char                    *kbuf;
 
        if (!capable(CAP_SYS_ADMIN))
@@ -487,8 +470,7 @@ xfs_attrlist_by_handle(
        if (al_hreq.buflen > XATTR_LIST_MAX)
                return -XFS_ERROR(EINVAL);
 
-       error = xfs_vget_fsop_handlereq(mp, parinode, &al_hreq.hreq,
-                       &vp, &inode);
+       error = xfs_vget_fsop_handlereq(mp, parinode, &al_hreq.hreq, &inode);
        if (error)
                goto out;
 
@@ -508,7 +490,7 @@ xfs_attrlist_by_handle(
  out_kfree:
        kfree(kbuf);
  out_vn_rele:
-       VN_RELE(vp);
+       iput(inode);
  out:
        return -error;
 }
@@ -530,7 +512,7 @@ xfs_attrmulti_attr_get(
        if (!kbuf)
                return ENOMEM;
 
-       error = xfs_attr_get(XFS_I(inode), name, kbuf, len, flags, NULL);
+       error = xfs_attr_get(XFS_I(inode), name, kbuf, (int *)len, flags, NULL);
        if (error)
                goto out_kfree;
 
@@ -597,7 +579,6 @@ xfs_attrmulti_by_handle(
        xfs_attr_multiop_t      *ops;
        xfs_fsop_attrmulti_handlereq_t am_hreq;
        struct inode            *inode;
-       bhv_vnode_t             *vp;
        unsigned int            i, size;
        char                    *attr_name;
 
@@ -606,7 +587,7 @@ xfs_attrmulti_by_handle(
        if (copy_from_user(&am_hreq, arg, sizeof(xfs_fsop_attrmulti_handlereq_t)))
                return -XFS_ERROR(EFAULT);
 
-       error = xfs_vget_fsop_handlereq(mp, parinode, &am_hreq.hreq, &vp, &inode);
+       error = xfs_vget_fsop_handlereq(mp, parinode, &am_hreq.hreq, &inode);
        if (error)
                goto out;
 
@@ -665,7 +646,7 @@ xfs_attrmulti_by_handle(
  out_kfree_ops:
        kfree(ops);
  out_vn_rele:
-       VN_RELE(vp);
+       iput(inode);
  out:
        return -error;
 }
@@ -701,12 +682,17 @@ xfs_ioc_fsgeometry(
 
 STATIC int
 xfs_ioc_xattr(
-       bhv_vnode_t             *vp,
        xfs_inode_t             *ip,
        struct file             *filp,
        unsigned int            cmd,
        void                    __user *arg);
 
+STATIC int
+xfs_ioc_fsgetxattr(
+       xfs_inode_t             *ip,
+       int                     attr,
+       void                    __user *arg);
+
 STATIC int
 xfs_ioc_getbmap(
        struct xfs_inode        *ip,
@@ -728,12 +714,10 @@ xfs_ioctl(
        void                    __user *arg)
 {
        struct inode            *inode = filp->f_path.dentry->d_inode;
-       bhv_vnode_t             *vp = vn_from_inode(inode);
        xfs_mount_t             *mp = ip->i_mount;
        int                     error;
 
-       vn_trace_entry(vp, "xfs_ioctl", (inst_t *)__return_address);
-
+       xfs_itrace_entry(XFS_I(inode));
        switch (cmd) {
 
        case XFS_IOC_ALLOCSP:
@@ -757,7 +741,7 @@ xfs_ioctl(
        case XFS_IOC_DIOINFO: {
                struct dioattr  da;
                xfs_buftarg_t   *target =
-                       (ip->i_d.di_flags & XFS_DIFLAG_REALTIME) ?
+                       XFS_IS_REALTIME_INODE(ip) ?
                        mp->m_rtdev_targp : mp->m_ddev_targp;
 
                da.d_mem = da.d_miniosz = 1 << target->bt_sshift;
@@ -782,12 +766,14 @@ xfs_ioctl(
        case XFS_IOC_GETVERSION:
                return put_user(inode->i_generation, (int __user *)arg);
 
+       case XFS_IOC_FSGETXATTR:
+               return xfs_ioc_fsgetxattr(ip, 0, arg);
+       case XFS_IOC_FSGETXATTRA:
+               return xfs_ioc_fsgetxattr(ip, 1, arg);
        case XFS_IOC_GETXFLAGS:
        case XFS_IOC_SETXFLAGS:
-       case XFS_IOC_FSGETXATTR:
        case XFS_IOC_FSSETXATTR:
-       case XFS_IOC_FSGETXATTRA:
-               return xfs_ioc_xattr(vp, ip, filp, cmd, arg);
+               return xfs_ioc_xattr(ip, filp, cmd, arg);
 
        case XFS_IOC_FSSETDM: {
                struct fsdmidata        dmi;
@@ -965,7 +951,7 @@ xfs_ioctl(
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
 
-               error = xfs_errortag_clearall(mp);
+               error = xfs_errortag_clearall(mp, 1);
                return -error;
 
        default:
@@ -1038,24 +1024,20 @@ xfs_ioc_bulkstat(
        if ((count = bulkreq.icount) <= 0)
                return -XFS_ERROR(EINVAL);
 
+       if (bulkreq.ubuffer == NULL)
+               return -XFS_ERROR(EINVAL);
+
        if (cmd == XFS_IOC_FSINUMBERS)
                error = xfs_inumbers(mp, &inlast, &count,
                                        bulkreq.ubuffer, xfs_inumbers_fmt);
        else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE)
                error = xfs_bulkstat_single(mp, &inlast,
                                                bulkreq.ubuffer, &done);
-       else {  /* XFS_IOC_FSBULKSTAT */
-               if (count == 1 && inlast != 0) {
-                       inlast++;
-                       error = xfs_bulkstat_single(mp, &inlast,
-                                       bulkreq.ubuffer, &done);
-               } else {
-                       error = xfs_bulkstat(mp, &inlast, &count,
-                               (bulkstat_one_pf)xfs_bulkstat_one, NULL,
-                               sizeof(xfs_bstat_t), bulkreq.ubuffer,
-                               BULKSTAT_FG_QUICK, &done);
-               }
-       }
+       else    /* XFS_IOC_FSBULKSTAT */
+               error = xfs_bulkstat(mp, &inlast, &count,
+                       (bulkstat_one_pf)xfs_bulkstat_one, NULL,
+                       sizeof(xfs_bstat_t), bulkreq.ubuffer,
+                       BULKSTAT_FG_QUICK, &done);
 
        if (error)
                return -error;
@@ -1160,9 +1142,44 @@ xfs_di2lxflags(
        return flags;
 }
 
+STATIC int
+xfs_ioc_fsgetxattr(
+       xfs_inode_t             *ip,
+       int                     attr,
+       void                    __user *arg)
+{
+       struct fsxattr          fa;
+
+       xfs_ilock(ip, XFS_ILOCK_SHARED);
+       fa.fsx_xflags = xfs_ip2xflags(ip);
+       fa.fsx_extsize = ip->i_d.di_extsize << ip->i_mount->m_sb.sb_blocklog;
+       fa.fsx_projid = ip->i_d.di_projid;
+
+       if (attr) {
+               if (ip->i_afp) {
+                       if (ip->i_afp->if_flags & XFS_IFEXTENTS)
+                               fa.fsx_nextents = ip->i_afp->if_bytes /
+                                                       sizeof(xfs_bmbt_rec_t);
+                       else
+                               fa.fsx_nextents = ip->i_d.di_anextents;
+               } else
+                       fa.fsx_nextents = 0;
+       } else {
+               if (ip->i_df.if_flags & XFS_IFEXTENTS)
+                       fa.fsx_nextents = ip->i_df.if_bytes /
+                                               sizeof(xfs_bmbt_rec_t);
+               else
+                       fa.fsx_nextents = ip->i_d.di_nextents;
+       }
+       xfs_iunlock(ip, XFS_ILOCK_SHARED);
+
+       if (copy_to_user(arg, &fa, sizeof(fa)))
+               return -EFAULT;
+       return 0;
+}
+
 STATIC int
 xfs_ioc_xattr(
-       bhv_vnode_t             *vp,
        xfs_inode_t             *ip,
        struct file             *filp,
        unsigned int            cmd,
@@ -1179,27 +1196,6 @@ xfs_ioc_xattr(
                return -ENOMEM;
 
        switch (cmd) {
-       case XFS_IOC_FSGETXATTR: {
-               vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \
-                                XFS_AT_NEXTENTS | XFS_AT_PROJID;
-               error = xfs_getattr(ip, vattr, 0);
-               if (unlikely(error)) {
-                       error = -error;
-                       break;
-               }
-
-               fa.fsx_xflags   = vattr->va_xflags;
-               fa.fsx_extsize  = vattr->va_extsize;
-               fa.fsx_nextents = vattr->va_nextents;
-               fa.fsx_projid   = vattr->va_projid;
-
-               if (copy_to_user(arg, &fa, sizeof(fa))) {
-                       error = -EFAULT;
-                       break;
-               }
-               break;
-       }
-
        case XFS_IOC_FSSETXATTR: {
                if (copy_from_user(&fa, arg, sizeof(fa))) {
                        error = -EFAULT;
@@ -1217,32 +1213,11 @@ xfs_ioc_xattr(
 
                error = xfs_setattr(ip, vattr, attr_flags, NULL);
                if (likely(!error))
-                       __vn_revalidate(vp, vattr);     /* update flags */
+                       vn_revalidate(XFS_ITOV(ip));    /* update flags */
                error = -error;
                break;
        }
 
-       case XFS_IOC_FSGETXATTRA: {
-               vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \
-                                XFS_AT_ANEXTENTS | XFS_AT_PROJID;
-               error = xfs_getattr(ip, vattr, 0);
-               if (unlikely(error)) {
-                       error = -error;
-                       break;
-               }
-
-               fa.fsx_xflags   = vattr->va_xflags;
-               fa.fsx_extsize  = vattr->va_extsize;
-               fa.fsx_nextents = vattr->va_anextents;
-               fa.fsx_projid   = vattr->va_projid;
-
-               if (copy_to_user(arg, &fa, sizeof(fa))) {
-                       error = -EFAULT;
-                       break;
-               }
-               break;
-       }
-
        case XFS_IOC_GETXFLAGS: {
                flags = xfs_di2lxflags(ip->i_d.di_flags);
                if (copy_to_user(arg, &flags, sizeof(flags)))
@@ -1273,7 +1248,7 @@ xfs_ioc_xattr(
 
                error = xfs_setattr(ip, vattr, attr_flags, NULL);
                if (likely(!error))
-                       __vn_revalidate(vp, vattr);     /* update flags */
+                       vn_revalidate(XFS_ITOV(ip));    /* update flags */
                error = -error;
                break;
        }