aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2021-01-29 12:31:52 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2021-02-12 01:02:21 +0000
commit06f2918ab8a2621c6e6bc5729ed9ab982741aaf2 (patch)
treeef9e87af0b8bd4c5a68be4206b976469c5b1a6b0
parent038fe6e089f03ca864c1dd5ac0c76404a13bbe79 (diff)
downloadsrc-06f2918ab8a2621c6e6bc5729ed9ab982741aaf2.tar.gz
src-06f2918ab8a2621c6e6bc5729ed9ab982741aaf2.zip
ufs_direnter: directory truncation does not need special case for rename
In ufs_rename case, tdvp is locked from the place where ufs_direnter() is done till VOP_VPUT_PAIR(), which means that we no longer need to specially handle rename in ufs_direnter(). Truncation, if possible, is done in the same way in ffs_vput_pair() both for rename and other VOPs calling ufs_direnter(). Remove isrename argument and set IN_ENDOFF if ufs_direnter() succeeded and directory needs truncation. In ffs_vput_pair(), stop verifying the condition that directory needs truncation when IN_ENDOFF is set, instead assert that the condition is true. Suggested by: mckusick Reviewed by: chs, mckusick Tested by: pho MFC after: 2 weeks Sponsored by: The FreeBSD Foundation
-rw-r--r--sys/ufs/ffs/ffs_vnops.c25
-rw-r--r--sys/ufs/ufs/ufs_extern.h2
-rw-r--r--sys/ufs/ufs/ufs_lookup.c12
-rw-r--r--sys/ufs/ufs/ufs_vnops.c10
4 files changed, 23 insertions, 26 deletions
diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c
index dd0f1ba6b81d..38511647c502 100644
--- a/sys/ufs/ffs/ffs_vnops.c
+++ b/sys/ufs/ffs/ffs_vnops.c
@@ -1968,22 +1968,21 @@ ffs_vput_pair(struct vop_vput_pair_args *ap)
* now that other locks are no longer held.
*/
if ((dp->i_flag & IN_ENDOFF) != 0) {
+ VNASSERT(I_ENDOFF(dp) != 0 && I_ENDOFF(dp) < dp->i_size, dvp,
+ ("IN_ENDOFF set but I_ENDOFF() is not"));
dp->i_flag &= ~IN_ENDOFF;
- if (I_ENDOFF(dp) != 0 && I_ENDOFF(dp) < dp->i_size) {
- old_size = dp->i_size;
- error = UFS_TRUNCATE(dvp, (off_t)I_ENDOFF(dp),
- IO_NORMAL | (DOINGASYNC(dvp) ? 0 : IO_SYNC),
- curthread->td_ucred);
- if (error != 0 && error != ERELOOKUP) {
- if (!ffs_fsfail_cleanup(VFSTOUFS(mp), error)) {
- vn_printf(dvp,
- "IN_ENDOFF: failed to truncate, "
- "error %d\n", error);
- }
+ old_size = dp->i_size;
+ error = UFS_TRUNCATE(dvp, (off_t)I_ENDOFF(dp), IO_NORMAL |
+ (DOINGASYNC(dvp) ? 0 : IO_SYNC), curthread->td_ucred);
+ if (error != 0 && error != ERELOOKUP) {
+ if (!ffs_fsfail_cleanup(VFSTOUFS(mp), error)) {
+ vn_printf(dvp,
+ "IN_ENDOFF: failed to truncate, "
+ "error %d\n", error);
+ }
#ifdef UFS_DIRHASH
- ufsdirhash_free(dp);
+ ufsdirhash_free(dp);
#endif
- }
}
SET_I_ENDOFF(dp, 0);
}
diff --git a/sys/ufs/ufs/ufs_extern.h b/sys/ufs/ufs/ufs_extern.h
index 1697f2c0ba61..3ac631e6ab0b 100644
--- a/sys/ufs/ufs/ufs_extern.h
+++ b/sys/ufs/ufs/ufs_extern.h
@@ -68,7 +68,7 @@ int ufs_extwrite(struct vop_write_args *);
void ufs_makedirentry(struct inode *, struct componentname *,
struct direct *);
int ufs_direnter(struct vnode *, struct vnode *, struct direct *,
- struct componentname *, struct buf *, int);
+ struct componentname *, struct buf *);
int ufs_dirremove(struct vnode *, struct inode *, int, int);
int ufs_dirrewrite(struct inode *, struct inode *, ino_t, int, int);
int ufs_lookup_ino(struct vnode *, struct vnode **, struct componentname *,
diff --git a/sys/ufs/ufs/ufs_lookup.c b/sys/ufs/ufs/ufs_lookup.c
index 3036bce81caf..0509185c4663 100644
--- a/sys/ufs/ufs/ufs_lookup.c
+++ b/sys/ufs/ufs/ufs_lookup.c
@@ -876,13 +876,12 @@ ufs_makedirentry(ip, cnp, newdirp)
* soft dependency code).
*/
int
-ufs_direnter(dvp, tvp, dirp, cnp, newdirbp, isrename)
+ufs_direnter(dvp, tvp, dirp, cnp, newdirbp)
struct vnode *dvp;
struct vnode *tvp;
struct direct *dirp;
struct componentname *cnp;
struct buf *newdirbp;
- int isrename;
{
struct ucred *cr;
struct thread *td;
@@ -1111,14 +1110,13 @@ ufs_direnter(dvp, tvp, dirp, cnp, newdirbp, isrename)
error = bwrite(bp);
}
}
- UFS_INODE_SET_FLAG(dp, IN_CHANGE | IN_UPDATE);
/*
- * If all went well, and the directory can be shortened, mark directory inode
- * with the truncation request right before unlock.
+ * If all went well, and the directory can be shortened,
+ * mark directory inode with the truncation request.
*/
- if (isrename == 0 && error == 0)
- UFS_INODE_SET_FLAG(dp, IN_ENDOFF);
+ UFS_INODE_SET_FLAG(dp, IN_CHANGE | IN_UPDATE | (error == 0 &&
+ I_ENDOFF(dp) != 0 && I_ENDOFF(dp) < dp->i_size ? IN_ENDOFF : 0));
return (error);
}
diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c
index c101e699bad6..22199a390dd4 100644
--- a/sys/ufs/ufs/ufs_vnops.c
+++ b/sys/ufs/ufs/ufs_vnops.c
@@ -1111,7 +1111,7 @@ ufs_link(ap)
error = UFS_UPDATE(vp, !DOINGSOFTDEP(vp) && !DOINGASYNC(vp));
if (!error) {
ufs_makedirentry(ip, cnp, &newdir);
- error = ufs_direnter(tdvp, vp, &newdir, cnp, NULL, 0);
+ error = ufs_direnter(tdvp, vp, &newdir, cnp, NULL);
}
if (error) {
@@ -1171,7 +1171,7 @@ ufs_whiteout(ap)
newdir.d_namlen = cnp->cn_namelen;
bcopy(cnp->cn_nameptr, newdir.d_name, (unsigned)cnp->cn_namelen + 1);
newdir.d_type = DT_WHT;
- error = ufs_direnter(dvp, NULL, &newdir, cnp, NULL, 0);
+ error = ufs_direnter(dvp, NULL, &newdir, cnp, NULL);
break;
case DELETE:
@@ -1511,7 +1511,7 @@ relock:
}
}
ufs_makedirentry(fip, tcnp, &newdir);
- error = ufs_direnter(tdvp, NULL, &newdir, tcnp, NULL, 1);
+ error = ufs_direnter(tdvp, NULL, &newdir, tcnp, NULL);
if (error)
goto bad;
/* Setup tdvp for directory compaction if needed. */
@@ -2132,7 +2132,7 @@ ufs_mkdir(ap)
else if (!DOINGSOFTDEP(dvp) && ((error = bwrite(bp))))
goto bad;
ufs_makedirentry(ip, cnp, &newdir);
- error = ufs_direnter(dvp, tvp, &newdir, cnp, bp, 0);
+ error = ufs_direnter(dvp, tvp, &newdir, cnp, bp);
bad:
if (error == 0) {
@@ -2865,7 +2865,7 @@ ufs_makeinode(mode, dvp, vpp, cnp, callfunc)
}
#endif /* !UFS_ACL */
ufs_makedirentry(ip, cnp, &newdir);
- error = ufs_direnter(dvp, tvp, &newdir, cnp, NULL, 0);
+ error = ufs_direnter(dvp, tvp, &newdir, cnp, NULL);
if (error)
goto bad;
vn_seqc_write_end(tvp);