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
This commit is contained in:
Konstantin Belousov 2021-01-29 14:31:52 +02:00
parent 038fe6e089
commit 06f2918ab8
4 changed files with 24 additions and 27 deletions

View File

@ -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);
}
#ifdef UFS_DIRHASH
ufsdirhash_free(dp);
#endif
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);
#endif
}
SET_I_ENDOFF(dp, 0);
}

View File

@ -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 *,

View File

@ -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);
}

View File

@ -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);