vserver 2.0-rc4
[linux-2.6.git] / fs / xfs / xfs_vfsops.c
index be11881..dd003ee 100644 (file)
@@ -118,7 +118,7 @@ xfs_init(void)
        xfs_ili_zone = kmem_zone_init(sizeof(xfs_inode_log_item_t), "xfs_ili");
        xfs_chashlist_zone = kmem_zone_init(sizeof(xfs_chashlist_t),
                                            "xfs_chashlist");
-       _ACL_ZONE_INIT(xfs_acl_zone, "xfs_acl");
+       xfs_acl_zone_init(xfs_acl_zone, "xfs_acl");
 
        /*
         * Allocate global trace buffers.
@@ -170,6 +170,7 @@ xfs_cleanup(void)
        xfs_cleanup_procfs();
        xfs_sysctl_unregister();
        xfs_refcache_destroy();
+       xfs_acl_zone_destroy(xfs_acl_zone);
 
 #ifdef XFS_DIR2_TRACE
        ktrace_free(xfs_dir2_trace_buf);
@@ -202,7 +203,6 @@ xfs_cleanup(void)
        kmem_cache_destroy(xfs_ifork_zone);
        kmem_cache_destroy(xfs_ili_zone);
        kmem_cache_destroy(xfs_chashlist_zone);
-       _ACL_ZONE_DESTROY(xfs_acl_zone);
 }
 
 /*
@@ -252,6 +252,7 @@ xfs_start_flags(
                        ap->logbufsize);
                return XFS_ERROR(EINVAL);
        }
+       mp->m_ihsize = ap->ihashsize;
        mp->m_logbsize = ap->logbufsize;
        mp->m_fsname_len = strlen(ap->fsname) + 1;
        mp->m_fsname = kmem_alloc(mp->m_fsname_len, KM_SLEEP);
@@ -318,6 +319,8 @@ xfs_start_flags(
 
        if (ap->flags & XFSMNT_NOUUID)
                mp->m_flags |= XFS_MOUNT_NOUUID;
+       if (ap->flags & XFSMNT_TAGXID)
+               mp->m_flags |= XFS_MOUNT_TAGXID;
        if (ap->flags & XFSMNT_NOLOGFLUSH)
                mp->m_flags |= XFS_MOUNT_NOLOGFLUSH;
 
@@ -400,6 +403,8 @@ xfs_finish_flags(
                        return XFS_ERROR(EINVAL);
        }
 
+       if (ap->flags & XFSMNT_TAGXID)
+               vfs->vfs_super->s_flags |= MS_TAGXID;
        return 0;
 }
 
@@ -430,6 +435,16 @@ xfs_mount(
        ddev = vfsp->vfs_super->s_bdev;
        logdev = rtdev = NULL;
 
+       /*
+        * Setup xfs_mount function vectors from available behaviors
+        */
+       p = vfs_bhv_lookup(vfsp, VFS_POSITION_DM);
+       mp->m_dm_ops = p ? *(xfs_dmops_t *) vfs_bhv_custom(p) : xfs_dmcore_stub;
+       p = vfs_bhv_lookup(vfsp, VFS_POSITION_QM);
+       mp->m_qm_ops = p ? *(xfs_qmops_t *) vfs_bhv_custom(p) : xfs_qmcore_stub;
+       p = vfs_bhv_lookup(vfsp, VFS_POSITION_IO);
+       mp->m_io_ops = p ? *(xfs_ioops_t *) vfs_bhv_custom(p) : xfs_iocore_xfs;
+
        /*
         * Open real time and log devices - order is important.
         */
@@ -454,69 +469,74 @@ xfs_mount(
                }
        }
 
-       /*
-        * Setup xfs_mount function vectors from available behaviors
-        */
-       p = vfs_bhv_lookup(vfsp, VFS_POSITION_DM);
-       mp->m_dm_ops = p ? *(xfs_dmops_t *) vfs_bhv_custom(p) : xfs_dmcore_stub;
-       p = vfs_bhv_lookup(vfsp, VFS_POSITION_QM);
-       mp->m_qm_ops = p ? *(xfs_qmops_t *) vfs_bhv_custom(p) : xfs_qmcore_stub;
-       p = vfs_bhv_lookup(vfsp, VFS_POSITION_IO);
-       mp->m_io_ops = p ? *(xfs_ioops_t *) vfs_bhv_custom(p) : xfs_iocore_xfs;
-
        /*
         * Setup xfs_mount buffer target pointers
         */
-       mp->m_ddev_targp = xfs_alloc_buftarg(ddev);
-       if (rtdev)
-               mp->m_rtdev_targp = xfs_alloc_buftarg(rtdev);
+       error = ENOMEM;
+       mp->m_ddev_targp = xfs_alloc_buftarg(ddev, 0);
+       if (!mp->m_ddev_targp) {
+               xfs_blkdev_put(logdev);
+               xfs_blkdev_put(rtdev);
+               return error;
+       }
+       if (rtdev) {
+               mp->m_rtdev_targp = xfs_alloc_buftarg(rtdev, 1);
+               if (!mp->m_rtdev_targp)
+                       goto error0;
+       }
        mp->m_logdev_targp = (logdev && logdev != ddev) ?
-                               xfs_alloc_buftarg(logdev) : mp->m_ddev_targp;
+                               xfs_alloc_buftarg(logdev, 1) : mp->m_ddev_targp;
+       if (!mp->m_logdev_targp)
+               goto error0;
 
        /*
         * Setup flags based on mount(2) options and then the superblock
         */
        error = xfs_start_flags(vfsp, args, mp);
        if (error)
-               goto error;
+               goto error1;
        error = xfs_readsb(mp);
        if (error)
-               goto error;
+               goto error1;
        error = xfs_finish_flags(vfsp, args, mp);
-       if (error) {
-               xfs_freesb(mp);
-               goto error;
-       }
+       if (error)
+               goto error2;
 
        /*
         * Setup xfs_mount buffer target pointers based on superblock
         */
-       xfs_setsize_buftarg(mp->m_ddev_targp, mp->m_sb.sb_blocksize,
-                           mp->m_sb.sb_sectsize);
-       if (logdev && logdev != ddev) {
+       error = xfs_setsize_buftarg(mp->m_ddev_targp, mp->m_sb.sb_blocksize,
+                                   mp->m_sb.sb_sectsize);
+       if (!error && logdev && logdev != ddev) {
                unsigned int    log_sector_size = BBSIZE;
 
                if (XFS_SB_VERSION_HASSECTOR(&mp->m_sb))
                        log_sector_size = mp->m_sb.sb_logsectsize;
-               xfs_setsize_buftarg(mp->m_logdev_targp, mp->m_sb.sb_blocksize,
-                                   log_sector_size);
+               error = xfs_setsize_buftarg(mp->m_logdev_targp,
+                                           mp->m_sb.sb_blocksize,
+                                           log_sector_size);
        }
-       if (rtdev)
-               xfs_setsize_buftarg(mp->m_rtdev_targp, mp->m_sb.sb_blocksize,
-                                   mp->m_sb.sb_blocksize);
+       if (!error && rtdev)
+               error = xfs_setsize_buftarg(mp->m_rtdev_targp,
+                                           mp->m_sb.sb_blocksize,
+                                           mp->m_sb.sb_sectsize);
+       if (error)
+               goto error2;
 
-       if (!(error = XFS_IOINIT(vfsp, args, flags)))
+       error = XFS_IOINIT(vfsp, args, flags);
+       if (!error)
                return 0;
-
- error:
+error2:
+       if (mp->m_sb_bp)
+               xfs_freesb(mp);
+error1:
        xfs_binval(mp->m_ddev_targp);
-       if (logdev != NULL && logdev != ddev) {
+       if (logdev && logdev != ddev)
                xfs_binval(mp->m_logdev_targp);
-       }
-       if (rtdev != NULL) {
+       if (rtdev)
                xfs_binval(mp->m_rtdev_targp);
-       }
-       xfs_unmountfs_close(mp, NULL);
+error0:
+       xfs_unmountfs_close(mp, credp);
        return error;
 }
 
@@ -1040,6 +1060,11 @@ xfs_sync_inodes(
                        continue;
                }
 
+               if (VN_BAD(vp)) {
+                       ip = ip->i_mnext;
+                       continue;
+               }
+
                if (XFS_FORCED_SHUTDOWN(mp) && !(flags & SYNC_CLOSE)) {
                        XFS_MOUNT_IUNLOCK(mp);
                        kmem_free(ipointer, sizeof(xfs_iptr_t));
@@ -1559,7 +1584,7 @@ xfs_syncsub(
 }
 
 /*
- * xfs_vget - called by DMAPI to get vnode from file handle
+ * xfs_vget - called by DMAPI and NFSD to get vnode from file handle
  */
 STATIC int
 xfs_vget(
@@ -1567,37 +1592,41 @@ xfs_vget(
        vnode_t         **vpp,
        fid_t           *fidp)
 {
-       xfs_fid_t       *xfid;
+       xfs_mount_t     *mp = XFS_BHVTOM(bdp);
+       xfs_fid_t       *xfid = (struct xfs_fid *)fidp;
        xfs_inode_t     *ip;
        int             error;
        xfs_ino_t       ino;
        unsigned int    igen;
-       xfs_mount_t     *mp;
 
-       xfid  = (struct xfs_fid *)fidp;
-       if (xfid->xfs_fid_len == sizeof(*xfid) - sizeof(xfid->xfs_fid_len)) {
-               ino  = xfid->xfs_fid_ino;
-               igen = xfid->xfs_fid_gen;
-       } else {
-               /*
-                * Invalid.  Since handles can be created in user space
-                * and passed in via gethandle(), this is not cause for
-                * a panic.
-                */
+       /*
+        * Invalid.  Since handles can be created in user space and passed in
+        * via gethandle(), this is not cause for a panic.
+        */
+       if (xfid->xfs_fid_len != sizeof(*xfid) - sizeof(xfid->xfs_fid_len))
                return XFS_ERROR(EINVAL);
-       }
-       mp = XFS_BHVTOM(bdp);
-       error = xfs_iget(mp, NULL, ino, XFS_ILOCK_SHARED, &ip, 0);
+
+       ino  = xfid->xfs_fid_ino;
+       igen = xfid->xfs_fid_gen;
+
+       /*
+        * NFS can sometimes send requests for ino 0.  Fail them gracefully.
+        */
+       if (ino == 0)
+               return XFS_ERROR(ESTALE);
+
+       error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_SHARED, &ip, 0);
        if (error) {
                *vpp = NULL;
                return error;
        }
+
        if (ip == NULL) {
                *vpp = NULL;
                return XFS_ERROR(EIO);
        }
 
-       if (ip->i_d.di_mode == 0 || (igen && (ip->i_d.di_gen != igen))) {
+       if (ip->i_d.di_mode == 0 || ip->i_d.di_gen != igen) {
                xfs_iput_new(ip, XFS_ILOCK_SHARED);
                *vpp = NULL;
                return XFS_ERROR(ENOENT);
@@ -1622,12 +1651,14 @@ xfs_vget(
 #define MNTOPT_SWIDTH  "swidth"        /* data volume stripe width */
 #define MNTOPT_NOUUID  "nouuid"        /* ignore filesystem UUID */
 #define MNTOPT_MTPT    "mtpt"          /* filesystem mount point */
+#define MNTOPT_IHASHSIZE    "ihashsize"    /* size of inode hash table */
 #define MNTOPT_NORECOVERY   "norecovery"   /* don't run XFS recovery */
 #define MNTOPT_NOLOGFLUSH   "nologflush"   /* don't hard flush on log writes */
 #define MNTOPT_OSYNCISOSYNC "osyncisosync" /* o_sync is REALLY o_sync */
 #define MNTOPT_64BITINODE   "inode64"  /* inodes can be allocated anywhere */
 #define MNTOPT_IKEEP   "ikeep"         /* do not free empty inode clusters */
 #define MNTOPT_NOIKEEP "noikeep"       /* free empty inode clusters */
+#define MNTOPT_TAGXID  "tagxid"        /* context xid tagging for inodes */
 
 
 int
@@ -1710,6 +1741,13 @@ xfs_parseargs(
                        iosize = simple_strtoul(value, &eov, 10);
                        args->flags |= XFSMNT_IOSIZE;
                        args->iosizelog = (uint8_t) iosize;
+               } else if (!strcmp(this_char, MNTOPT_IHASHSIZE)) {
+                       if (!value || !*value) {
+                               printk("XFS: %s option requires an argument\n",
+                                       this_char); 
+                               return EINVAL;
+                       }
+                       args->ihashsize = simple_strtoul(value, &eov, 10);
                } else if (!strcmp(this_char, MNTOPT_WSYNC)) {
                        args->flags |= XFSMNT_WSYNC;
                } else if (!strcmp(this_char, MNTOPT_OSYNCISOSYNC)) {
@@ -1756,6 +1794,8 @@ xfs_parseargs(
                        args->flags &= ~XFSMNT_IDELETE;
                } else if (!strcmp(this_char, MNTOPT_NOIKEEP)) {
                        args->flags |= XFSMNT_IDELETE;
+               } else if (!strcmp(this_char, MNTOPT_TAGXID)) {
+                       args->flags |= XFSMNT_TAGXID;
                } else if (!strcmp(this_char, "osyncisdsync")) {
                        /* no-op, this is now the default */
 printk("XFS: osyncisdsync is now the default, option is deprecated.\n");