aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2021-01-28 18:33:58 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2021-02-12 01:02:19 +0000
commite94f2f1be32294cb6d519b6631f7522466fbbb3b (patch)
treeb6c5765ec250879562ff56c75fab3d8033831cee /sys
parentbf0db19339e770a82236b74f523be4b572bde15d (diff)
downloadsrc-e94f2f1be32294cb6d519b6631f7522466fbbb3b.tar.gz
src-e94f2f1be32294cb6d519b6631f7522466fbbb3b.zip
ffs: call ufsdirhash_dirtrunc() right after setting directory size
Later processing of ffs_truncate() might temporary unlock the directory vnode, causing unsychronized dirhash and inode sizes if update is postponed to UFS_TRUNCATE() callers. Reviewed by: chs, mkcusick Tested by: pho MFC after: 2 weeks Sponsored by: The FreeBSD Foundation
Diffstat (limited to 'sys')
-rw-r--r--sys/ufs/ffs/ffs_inode.c13
-rw-r--r--sys/ufs/ufs/ufs_lookup.c4
-rw-r--r--sys/ufs/ufs/ufs_vnops.c2
3 files changed, 13 insertions, 6 deletions
diff --git a/sys/ufs/ffs/ffs_inode.c b/sys/ufs/ffs/ffs_inode.c
index 0b4172b34300..3df7bf8e8596 100644
--- a/sys/ufs/ffs/ffs_inode.c
+++ b/sys/ufs/ffs/ffs_inode.c
@@ -34,6 +34,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_ufs.h"
#include "opt_quota.h"
#include <sys/param.h>
@@ -59,6 +60,10 @@ __FBSDID("$FreeBSD$");
#include <ufs/ufs/quota.h>
#include <ufs/ufs/ufsmount.h>
#include <ufs/ufs/inode.h>
+#include <ufs/ufs/dir.h>
+#ifdef UFS_DIRHASH
+#include <ufs/ufs/dirhash.h>
+#endif
#include <ufs/ufs/ufs_extern.h>
#include <ufs/ffs/fs.h>
@@ -456,6 +461,10 @@ ffs_truncate(vp, length, flags, cred)
ip->i_size = length;
DIP_SET(ip, i_size, length);
UFS_INODE_SET_FLAG(ip, IN_SIZEMOD | IN_CHANGE | IN_UPDATE);
+#ifdef UFS_DIRHASH
+ if (vp->v_type == VDIR && ip->i_dirhash != NULL)
+ ufsdirhash_dirtrunc(ip, length);
+#endif
} else {
lbn = lblkno(fs, length);
flags |= BA_CLRBUF;
@@ -482,6 +491,10 @@ ffs_truncate(vp, length, flags, cred)
return (error);
ip->i_size = length;
DIP_SET(ip, i_size, length);
+#ifdef UFS_DIRHASH
+ if (vp->v_type == VDIR && ip->i_dirhash != NULL)
+ ufsdirhash_dirtrunc(ip, length);
+#endif
size = blksize(fs, ip, lbn);
if (vp->v_type != VDIR && offset != 0)
bzero((char *)bp->b_data + offset,
diff --git a/sys/ufs/ufs/ufs_lookup.c b/sys/ufs/ufs/ufs_lookup.c
index 7dbd58f795cc..2f5fbf3d8001 100644
--- a/sys/ufs/ufs/ufs_lookup.c
+++ b/sys/ufs/ufs/ufs_lookup.c
@@ -1131,10 +1131,6 @@ ufs_direnter(dvp, tvp, dirp, cnp, newdirbp, isrename)
vn_printf(dvp,
"ufs_direnter: failed to truncate, error %d\n",
error);
-#ifdef UFS_DIRHASH
- if (error == 0 && dp->i_dirhash != NULL)
- ufsdirhash_dirtrunc(dp, I_ENDOFF(dp));
-#endif
error = 0;
if (tvp != NULL)
vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY);
diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c
index 0e7ec7ae5453..70b5a44ca21d 100644
--- a/sys/ufs/ufs/ufs_vnops.c
+++ b/sys/ufs/ufs/ufs_vnops.c
@@ -1694,8 +1694,6 @@ unlockout:
#ifdef UFS_DIRHASH
if (error != 0)
ufsdirhash_free(tdp);
- else if (tdp->i_dirhash != NULL)
- ufsdirhash_dirtrunc(tdp, endoff);
#endif
/*
* Even if the directory compaction failed, rename was