Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F144588549
D15342.1775583621.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D15342.1775583621.diff
View Options
Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_vfsops.h
===================================================================
--- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_vfsops.h
+++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_vfsops.h
@@ -85,6 +85,7 @@
sa_attr_type_t *z_attr_table; /* SA attr mapping->id */
#define ZFS_OBJ_MTX_SZ 64
kmutex_t z_hold_mtx[ZFS_OBJ_MTX_SZ]; /* znode hold locks */
+ struct task z_unlinked_drain_task;
};
/*
Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_dir.c
===================================================================
--- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_dir.c
+++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_dir.c
@@ -281,6 +281,7 @@
zap_attribute_t zap;
dmu_object_info_t doi;
znode_t *zp;
+ dmu_tx_t *tx;
int error;
/*
@@ -318,6 +319,19 @@
vn_lock(ZTOV(zp), LK_EXCLUSIVE | LK_RETRY);
zp->z_unlinked = B_TRUE;
+#if defined(__FreeBSD__)
+ /*
+ * Due to changes in zfs_rmnode we need to make sure the
+ * link count is set to zero here.
+ */
+ zp->z_links = 0;
+ tx = dmu_tx_create(zfsvfs->z_os);
+ dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE);
+ VERIFY(0 == dmu_tx_assign(tx, TXG_WAIT));
+ VERIFY(0 == sa_update(zp->z_sa_hdl, SA_ZPL_LINKS(zfsvfs),
+ &zp->z_links, sizeof (zp->z_links), tx));
+ dmu_tx_commit(tx);
+#endif
vput(ZTOV(zp));
}
zap_cursor_fini(&zc);
@@ -393,7 +407,6 @@
{
zfsvfs_t *zfsvfs = zp->z_zfsvfs;
objset_t *os = zfsvfs->z_os;
- znode_t *xzp = NULL;
dmu_tx_t *tx;
uint64_t acl_obj;
uint64_t xattr_obj;
@@ -443,11 +456,8 @@
*/
error = sa_lookup(zp->z_sa_hdl, SA_ZPL_XATTR(zfsvfs),
&xattr_obj, sizeof (xattr_obj));
- if (error == 0 && xattr_obj) {
- error = zfs_zget(zfsvfs, xattr_obj, &xzp);
- ASSERT3S(error, ==, 0);
- vn_lock(ZTOV(xzp), LK_EXCLUSIVE | LK_RETRY);
- }
+ if (error)
+ xattr_obj = 0;
acl_obj = zfs_external_acl(zp);
@@ -457,10 +467,8 @@
tx = dmu_tx_create(os);
dmu_tx_hold_free(tx, zp->z_id, 0, DMU_OBJECT_END);
dmu_tx_hold_zap(tx, zfsvfs->z_unlinkedobj, FALSE, NULL);
- if (xzp) {
+ if (xattr_obj)
dmu_tx_hold_zap(tx, zfsvfs->z_unlinkedobj, TRUE, NULL);
- dmu_tx_hold_sa(tx, xzp->z_sa_hdl, B_FALSE);
- }
if (acl_obj)
dmu_tx_hold_free(tx, acl_obj, 0, DMU_OBJECT_END);
@@ -475,9 +483,25 @@
dmu_tx_abort(tx);
zfs_znode_dmu_fini(zp);
zfs_znode_free(zp);
- goto out;
+ return;
}
+#if defined(__FreeBSD__)
+ /*
+ * FreeBSD's implemention of zfs_zget requires a vnode to back it.
+ * This means that we could end up calling into getnewvnode while
+ * calling zfs_rmnode as a result of a prior call to getnewvnode
+ * trying to clear vnodes out of the cache. If this repeats we can
+ * recurse enough that we overflow our stack. To avoid this, we
+ * avoid calling zfs_zget on the xattr znode and instead simply add
+ * it to the unlinked set and schedule a call to zfs_unlinked_drain.
+ */
+ if (xattr_obj) {
+ /* Add extended attribute directory to the unlinked set. */
+ VERIFY3U(0, ==,
+ zap_add_int(os, zfsvfs->z_unlinkedobj, xattr_obj, tx));
+ }
+#else
if (xzp) {
ASSERT(error == 0);
xzp->z_unlinked = B_TRUE; /* mark xzp for deletion */
@@ -486,6 +510,7 @@
&xzp->z_links, sizeof (xzp->z_links), tx));
zfs_unlinked_add(xzp, tx);
}
+#endif
/* Remove this znode from the unlinked set */
VERIFY3U(0, ==,
@@ -494,9 +519,16 @@
zfs_znode_delete(zp, tx);
dmu_tx_commit(tx);
-out:
- if (xzp)
- vput(ZTOV(xzp));
+
+ if (xattr_obj) {
+ /*
+ * We're using the FreeBSD taskqueue API here instead of
+ * the Solaris taskq API since the FreeBSD API allows for a
+ * task to be enqueued multiple times but executed once.
+ */
+ taskqueue_enqueue(system_taskq->tq_queue,
+ &zfsvfs->z_unlinked_drain_task);
+ }
}
static uint64_t
Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
===================================================================
--- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
+++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
@@ -972,6 +972,8 @@
return (0);
}
+static task_fn_t zfsvfs_task_unlinked_drain;
+
int
zfsvfs_create(const char *osname, zfsvfs_t **zfvp)
{
@@ -1023,6 +1025,8 @@
mutex_init(&zfsvfs->z_lock, NULL, MUTEX_DEFAULT, NULL);
list_create(&zfsvfs->z_all_znodes, sizeof (znode_t),
offsetof(znode_t, z_link_node));
+ TASK_INIT(&zfsvfs->z_unlinked_drain_task, 0,
+ zfsvfs_task_unlinked_drain, zfsvfs);
#ifdef DIAGNOSTIC
rrm_init(&zfsvfs->z_teardown_lock, B_TRUE);
#else
@@ -2015,6 +2019,11 @@
}
#endif
+ while (taskqueue_cancel(system_taskq->tq_queue,
+ &zfsvfs->z_unlinked_drain_task, NULL) != 0)
+ taskqueue_drain(system_taskq->tq_queue,
+ &zfsvfs->z_unlinked_drain_task);
+
VERIFY(zfsvfs_teardown(zfsvfs, B_TRUE) == 0);
os = zfsvfs->z_os;
@@ -2559,3 +2568,10 @@
mtx_unlock(&mountlist_mtx);
}
#endif
+
+static void
+zfsvfs_task_unlinked_drain(void *context, int pending __unused)
+{
+
+ zfs_unlinked_drain((zfsvfs_t *)context);
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Apr 7, 5:40 PM (13 h, 17 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28296139
Default Alt Text
D15342.1775583621.diff (4 KB)
Attached To
Mode
D15342: Break recursion involving getnewvnode and zfs_rmnode
Attached
Detach File
Event Timeline
Log In to Comment