diff options
author | Chunwei Chen <[email protected]> | 2015-12-21 11:57:18 -0800 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2015-12-28 09:48:26 -0800 |
commit | f5f087eb8800a9b3c7a8d7e5a96c095eff68b097 (patch) | |
tree | e10bf7f4669949bb8675bcd24b0f937729df4739 /module/zfs | |
parent | 29572ccdeff7ddb1211b0f26dea69e0a2f262faf (diff) |
Make xattr dir truncate and remove in one tx
We need truncate and remove be in the same tx when doing zfs_rmnode on xattr
dir. Otherwise, if we truncate and crash, we'll end up with inconsistent zap
object on the delete queue. We do this by skipping dmu_free_long_range and let
zfs_znode_delete to do the work.
Signed-off-by: Chunwei Chen <[email protected]>
Signed-off-by: Brian Behlendorf <[email protected]>
Issue #4114
Issue #4052
Issue #4006
Issue #3018
Issue #2861
Diffstat (limited to 'module/zfs')
-rw-r--r-- | module/zfs/zfs_dir.c | 23 |
1 files changed, 15 insertions, 8 deletions
diff --git a/module/zfs/zfs_dir.c b/module/zfs/zfs_dir.c index 712cb4656..c1eadd0dc 100644 --- a/module/zfs/zfs_dir.c +++ b/module/zfs/zfs_dir.c @@ -632,15 +632,22 @@ zfs_rmnode(znode_t *zp) } /* - * Free up all the data in the file. + * Free up all the data in the file. We don't do this for directories + * because we need truncate and remove to be in the same tx, like in + * zfs_znode_delete(). Otherwise, if we crash here we'll end up with + * an inconsistent truncated zap object in the delete queue. Note a + * truncated file is harmless since it only contains user data. */ - error = dmu_free_long_range(os, zp->z_id, 0, DMU_OBJECT_END); - if (error) { - /* - * Not enough space. Leave the file in the unlinked set. - */ - zfs_znode_dmu_fini(zp); - return; + if (S_ISREG(ZTOI(zp)->i_mode)) { + error = dmu_free_long_range(os, zp->z_id, 0, DMU_OBJECT_END); + if (error) { + /* + * Not enough space. Leave the file in the unlinked + * set. + */ + zfs_znode_dmu_fini(zp); + return; + } } /* |