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
This commit is contained in:
parent
bf0db19339
commit
e94f2f1be3
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user