Merge branch 'for-linus' of git://oss.sgi.com/xfs/xfs
[cascardo/linux.git] / fs / xfs / xfs_super.c
index 912442c..dab9a5f 100644 (file)
@@ -950,6 +950,22 @@ xfs_fs_evict_inode(
        xfs_inactive(ip);
 }
 
+/*
+ * We do an unlocked check for XFS_IDONTCACHE here because we are already
+ * serialised against cache hits here via the inode->i_lock and igrab() in
+ * xfs_iget_cache_hit(). Hence a lookup that might clear this flag will not be
+ * racing with us, and it avoids needing to grab a spinlock here for every inode
+ * we drop the final reference on.
+ */
+STATIC int
+xfs_fs_drop_inode(
+       struct inode            *inode)
+{
+       struct xfs_inode        *ip = XFS_I(inode);
+
+       return generic_drop_inode(inode) || (ip->i_flags & XFS_IDONTCACHE);
+}
+
 STATIC void
 xfs_free_fsname(
        struct xfs_mount        *mp)
@@ -1433,6 +1449,7 @@ static const struct super_operations xfs_super_operations = {
        .destroy_inode          = xfs_fs_destroy_inode,
        .dirty_inode            = xfs_fs_dirty_inode,
        .evict_inode            = xfs_fs_evict_inode,
+       .drop_inode             = xfs_fs_drop_inode,
        .put_super              = xfs_fs_put_super,
        .sync_fs                = xfs_fs_sync_fs,
        .freeze_fs              = xfs_fs_freeze,
@@ -1606,12 +1623,28 @@ xfs_init_workqueues(void)
        xfs_syncd_wq = alloc_workqueue("xfssyncd", WQ_NON_REENTRANT, 0);
        if (!xfs_syncd_wq)
                return -ENOMEM;
+
+       /*
+        * The allocation workqueue can be used in memory reclaim situations
+        * (writepage path), and parallelism is only limited by the number of
+        * AGs in all the filesystems mounted. Hence use the default large
+        * max_active value for this workqueue.
+        */
+       xfs_alloc_wq = alloc_workqueue("xfsalloc", WQ_MEM_RECLAIM, 0);
+       if (!xfs_alloc_wq)
+               goto out_destroy_syncd;
+
        return 0;
+
+out_destroy_syncd:
+       destroy_workqueue(xfs_syncd_wq);
+       return -ENOMEM;
 }
 
 STATIC void
 xfs_destroy_workqueues(void)
 {
+       destroy_workqueue(xfs_alloc_wq);
        destroy_workqueue(xfs_syncd_wq);
 }