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:
parent
038fe6e089
commit
06f2918ab8
@ -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);
|
||||
}
|
||||
|
@ -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 *,
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user