]> git.proxmox.com Git - mirror_zfs-debian.git/blobdiff - module/zfs/zfs_dir.c
Imported Upstream version 0.6.4.2
[mirror_zfs-debian.git] / module / zfs / zfs_dir.c
index 448a8727ebbbd02edc21db70f9adbe64c39c376e..712cb4656430292eedbc4653502e20e6e218b24c 100644 (file)
@@ -46,6 +46,7 @@
 #include <sys/policy.h>
 #include <sys/zfs_dir.h>
 #include <sys/zfs_acl.h>
+#include <sys/zfs_vnops.h>
 #include <sys/fs/zfs.h>
 #include "fs/fs_subr.h"
 #include <sys/zap.h>
@@ -483,6 +484,57 @@ zfs_unlinked_add(znode_t *zp, dmu_tx_t *tx)
            zap_add_int(zsb->z_os, zsb->z_unlinkedobj, zp->z_id, tx));
 }
 
+/*
+ * Clean up any znodes that had no links when we either crashed or
+ * (force) umounted the file system.
+ */
+void
+zfs_unlinked_drain(zfs_sb_t *zsb)
+{
+       zap_cursor_t    zc;
+       zap_attribute_t zap;
+       dmu_object_info_t doi;
+       znode_t         *zp;
+       int             error;
+
+       /*
+        * Iterate over the contents of the unlinked set.
+        */
+       for (zap_cursor_init(&zc, zsb->z_os, zsb->z_unlinkedobj);
+           zap_cursor_retrieve(&zc, &zap) == 0;
+           zap_cursor_advance(&zc)) {
+
+               /*
+                * See what kind of object we have in list
+                */
+
+               error = dmu_object_info(zsb->z_os, zap.za_first_integer, &doi);
+               if (error != 0)
+                       continue;
+
+               ASSERT((doi.doi_type == DMU_OT_PLAIN_FILE_CONTENTS) ||
+                   (doi.doi_type == DMU_OT_DIRECTORY_CONTENTS));
+               /*
+                * We need to re-mark these list entries for deletion,
+                * so we pull them back into core and set zp->z_unlinked.
+                */
+               error = zfs_zget(zsb, zap.za_first_integer, &zp);
+
+               /*
+                * We may pick up znodes that are already marked for deletion.
+                * This could happen during the purge of an extended attribute
+                * directory.  All we need to do is skip over them, since they
+                * are already in the system marked z_unlinked.
+                */
+               if (error != 0)
+                       continue;
+
+               zp->z_unlinked = B_TRUE;
+               iput(ZTOI(zp));
+       }
+       zap_cursor_fini(&zc);
+}
+
 /*
  * Delete the entire contents of a directory.  Return a count
  * of the number of entries that could not be deleted. If we encounter
@@ -516,7 +568,8 @@ zfs_purgedir(znode_t *dzp)
                        continue;
                }
 
-               ASSERT(S_ISREG(ZTOI(xzp)->i_mode)||S_ISLNK(ZTOI(xzp)->i_mode));
+               ASSERT(S_ISREG(ZTOI(xzp)->i_mode) ||
+                   S_ISLNK(ZTOI(xzp)->i_mode));
 
                tx = dmu_tx_create(zsb->z_os);
                dmu_tx_hold_sa(tx, dzp->z_sa_hdl, B_FALSE);
@@ -528,7 +581,7 @@ zfs_purgedir(znode_t *dzp)
                error = dmu_tx_assign(tx, TXG_WAIT);
                if (error) {
                        dmu_tx_abort(tx);
-                       iput(ZTOI(xzp));
+                       zfs_iput_async(ZTOI(xzp));
                        skipped += 1;
                        continue;
                }
@@ -541,7 +594,7 @@ zfs_purgedir(znode_t *dzp)
                        skipped += 1;
                dmu_tx_commit(tx);
 
-               iput(ZTOI(xzp));
+               zfs_iput_async(ZTOI(xzp));
        }
        zap_cursor_fini(&zc);
        if (error != ENOENT)
@@ -549,71 +602,6 @@ zfs_purgedir(znode_t *dzp)
        return (skipped);
 }
 
-/*
- * Clean up any znodes that had no links when we either crashed or
- * (force) umounted the file system.
- */
-void
-zfs_unlinked_drain(zfs_sb_t *zsb)
-{
-       zap_cursor_t    zc;
-       zap_attribute_t zap;
-       dmu_object_info_t doi;
-       znode_t         *zp;
-       int             error;
-
-       /*
-        * Iterate over the contents of the unlinked set.
-        */
-       for (zap_cursor_init(&zc, zsb->z_os, zsb->z_unlinkedobj);
-           zap_cursor_retrieve(&zc, &zap) == 0;
-           zap_cursor_advance(&zc)) {
-
-               /*
-                * See what kind of object we have in list
-                */
-
-               error = dmu_object_info(zsb->z_os, zap.za_first_integer, &doi);
-               if (error != 0)
-                       continue;
-
-               ASSERT((doi.doi_type == DMU_OT_PLAIN_FILE_CONTENTS) ||
-                   (doi.doi_type == DMU_OT_DIRECTORY_CONTENTS));
-               /*
-                * We need to re-mark these list entries for deletion,
-                * so we pull them back into core and set zp->z_unlinked.
-                */
-               error = zfs_zget(zsb, zap.za_first_integer, &zp);
-
-               /*
-                * We may pick up znodes that are already marked for deletion.
-                * This could happen during the purge of an extended attribute
-                * directory.  All we need to do is skip over them, since they
-                * are already in the system marked z_unlinked.
-                */
-               if (error != 0)
-                       continue;
-
-               zp->z_unlinked = B_TRUE;
-
-               /*
-                * If this is an attribute directory, purge its contents.
-                */
-               if (S_ISDIR(ZTOI(zp)->i_mode) && (zp->z_pflags & ZFS_XATTR)) {
-                       /*
-                        * We don't need to check the return value of
-                        * zfs_purgedir here, because zfs_rmnode will just
-                        * return this xattr directory to the unlinked set
-                        * until all of its xattrs are gone.
-                        */
-                       (void) zfs_purgedir(zp);
-               }
-
-               iput(ZTOI(zp));
-       }
-       zap_cursor_fini(&zc);
-}
-
 void
 zfs_rmnode(znode_t *zp)
 {
@@ -623,7 +611,6 @@ zfs_rmnode(znode_t *zp)
        dmu_tx_t        *tx;
        uint64_t        acl_obj;
        uint64_t        xattr_obj;
-       uint64_t        count;
        int             error;
 
        ASSERT(zp->z_links == 0);
@@ -633,27 +620,13 @@ zfs_rmnode(znode_t *zp)
         * If this is an attribute directory, purge its contents.
         */
        if (S_ISDIR(ZTOI(zp)->i_mode) && (zp->z_pflags & ZFS_XATTR)) {
-               error = zap_count(os, zp->z_id, &count);
-               if (error) {
-                       zfs_znode_dmu_fini(zp);
-                       return;
-               }
-
-               if (count > 0) {
-                       taskq_t *taskq;
-
+               if (zfs_purgedir(zp) != 0) {
                        /*
-                        * There are still directory entries in this xattr
-                        * directory.  Let zfs_unlinked_drain() deal with
-                        * them to avoid deadlocking this process in the
-                        * zfs_purgedir()->zfs_zget()->ilookup() callpath
-                        * on the xattr inode's I_FREEING bit.
+                        * Not enough space to delete some xattrs.
+                        * Leave it in the unlinked set.
                         */
-                       taskq = dsl_pool_iput_taskq(dmu_objset_pool(os));
-                       taskq_dispatch(taskq, (task_func_t *)
-                           zfs_unlinked_drain, zsb, TQ_SLEEP);
-
                        zfs_znode_dmu_fini(zp);
+
                        return;
                }
        }
@@ -729,7 +702,7 @@ zfs_rmnode(znode_t *zp)
        dmu_tx_commit(tx);
 out:
        if (xzp)
-               iput(ZTOI(xzp));
+               zfs_iput_async(ZTOI(xzp));
 }
 
 static uint64_t