diff options
author | Constantine Sapuntzakis <csapuntz@cvs.openbsd.org> | 1997-12-02 17:11:14 +0000 |
---|---|---|
committer | Constantine Sapuntzakis <csapuntz@cvs.openbsd.org> | 1997-12-02 17:11:14 +0000 |
commit | 6f7ac56ccd19416ad8f2dae8788acfabc298f11a (patch) | |
tree | 6988d3dc3a47ce62c11a78a50b5dd6ab855209d5 /sys/ufs | |
parent | 82232fad242af9b522d3f55e8ebda456f534f59d (diff) |
Unlock child temporarily while truncating directory. This prevents
a double locking bug in the soft updates code.
Diffstat (limited to 'sys/ufs')
-rw-r--r-- | sys/ufs/ufs/ufs_extern.h | 4 | ||||
-rw-r--r-- | sys/ufs/ufs/ufs_lookup.c | 22 | ||||
-rw-r--r-- | sys/ufs/ufs/ufs_vnops.c | 17 |
3 files changed, 32 insertions, 11 deletions
diff --git a/sys/ufs/ufs/ufs_extern.h b/sys/ufs/ufs/ufs_extern.h index 6c49d78717c..8a20bbbac48 100644 --- a/sys/ufs/ufs/ufs_extern.h +++ b/sys/ufs/ufs/ufs_extern.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ufs_extern.h,v 1.5 1997/11/06 05:59:26 csapuntz Exp $ */ +/* $OpenBSD: ufs_extern.h,v 1.6 1997/12/02 17:11:10 csapuntz Exp $ */ /* $NetBSD: ufs_extern.h,v 1.5 1996/02/09 22:36:03 christos Exp $ */ /*- @@ -127,7 +127,7 @@ void ufs_dirbad __P((struct inode *, doff_t, char *)); int ufs_dirbadentry __P((struct vnode *, struct direct *, int)); void ufs_makedirentry __P((struct inode *, struct componentname *, struct direct *)); -int ufs_direnter __P((struct vnode *, struct direct *, +int ufs_direnter __P((struct vnode *, struct vnode *, struct direct *, struct componentname *, struct buf *)); int ufs_dirremove __P((struct vnode *, struct inode *, int, int)); int ufs_dirrewrite __P((struct inode *, struct inode *, diff --git a/sys/ufs/ufs/ufs_lookup.c b/sys/ufs/ufs/ufs_lookup.c index 31a7a5fd169..c89d4b7ee0c 100644 --- a/sys/ufs/ufs/ufs_lookup.c +++ b/sys/ufs/ufs/ufs_lookup.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ufs_lookup.c,v 1.7 1997/11/06 05:59:27 csapuntz Exp $ */ +/* $OpenBSD: ufs_lookup.c,v 1.8 1997/12/02 17:11:11 csapuntz Exp $ */ /* $NetBSD: ufs_lookup.c,v 1.7 1996/02/09 22:36:06 christos Exp $ */ /* @@ -721,8 +721,9 @@ ufs_makedirentry(ip, cnp, newdirp) * soft dependency code). */ int -ufs_direnter(dvp, dirp, cnp, newdirbp) +ufs_direnter(dvp, tvp, dirp, cnp, newdirbp) struct vnode *dvp; + struct vnode *tvp; struct direct *dirp; struct componentname *cnp; struct buf *newdirbp; @@ -877,8 +878,23 @@ ufs_direnter(dvp, dirp, cnp, newdirbp) error = VOP_BWRITE(bp); } dp->i_flag |= IN_CHANGE | IN_UPDATE; - if (error == 0 && dp->i_endoff && dp->i_endoff < dp->i_ffs_size) + + /* + * If all went well, and the directory can be shortened, proceed + * with the truncation. Note that we have to unlock the inode for + * the entry that we just entered, as the truncation may need to + * lock other inodes which can lead to deadlock if we also hold a + * lock on the newly entered node. + */ + + if (error == 0 && dp->i_endoff && dp->i_endoff < dp->i_ffs_size) { + if (tvp != NULL) + VOP_UNLOCK(tvp, 0, p); + error = VOP_TRUNCATE(dvp, (off_t)dp->i_endoff, IO_SYNC, cr, p); + if (tvp != NULL) + vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY, p); + } return (error); } diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c index a261a24c54f..1f71e54da9d 100644 --- a/sys/ufs/ufs/ufs_vnops.c +++ b/sys/ufs/ufs/ufs_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ufs_vnops.c,v 1.16 1997/11/06 23:07:24 csapuntz Exp $ */ +/* $OpenBSD: ufs_vnops.c,v 1.17 1997/12/02 17:11:13 csapuntz Exp $ */ /* $NetBSD: ufs_vnops.c,v 1.18 1996/05/11 18:28:04 mycroft Exp $ */ /* @@ -737,7 +737,7 @@ ufs_link(v) TIMEVAL_TO_TIMESPEC(&time, &ts); if ((error = VOP_UPDATE(vp, &ts, &ts, !DOINGSOFTDEP(vp))) == 0) { ufs_makedirentry(ip, cnp, &newdir); - error = ufs_direnter(dvp, &newdir, cnp, NULL); + error = ufs_direnter(dvp, vp, &newdir, cnp, NULL); } if (error) { ip->i_effnlink--; @@ -790,7 +790,7 @@ ufs_whiteout(v) 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, &newdir, cnp, NULL); + error = ufs_direnter(dvp, NULL, &newdir, cnp, NULL); break; case DELETE: @@ -1042,7 +1042,7 @@ abortit: goto bad; } ufs_makedirentry(ip, tcnp, &newdir); - if ((error = ufs_direnter(tdvp, &newdir, tcnp, NULL)) != 0) { + if ((error = ufs_direnter(tdvp, fvp, &newdir, tcnp, NULL)) != 0) { if (doingdirectory && newparent) { dp->i_effnlink--; dp->i_ffs_nlink--; @@ -1313,7 +1313,7 @@ ufs_mkdir(v) if (!DOINGSOFTDEP(dvp) && ((error = VOP_BWRITE(bp)) != 0)) goto bad; ufs_makedirentry(ip, cnp, &newdir); - error = ufs_direnter(dvp, &newdir, cnp, bp); + error = ufs_direnter(dvp, tvp, &newdir, cnp, bp); bad: if (error == 0) { @@ -1728,6 +1728,11 @@ ufs_print(v) printf("tag VT_UFS, ino %d, on dev %d, %d", ip->i_number, major(ip->i_dev), minor(ip->i_dev)); + printf(" flags 0x%x, effnlink %d, nlink %d\n", + ip->i_flag, ip->i_effnlink, ip->i_ffs_nlink); + printf("\tmode 0%o, owner %d, group %d, size %qd", + ip->i_ffs_mode, ip->i_ffs_uid, ip->i_ffs_gid, ip->i_ffs_size); + #ifdef FIFO if (vp->v_type == VFIFO) fifo_printinfo(vp); @@ -2064,7 +2069,7 @@ ufs_makeinode(mode, dvp, vpp, cnp) goto bad; ufs_makedirentry(ip, cnp, &newdir); - if ((error = ufs_direnter(dvp, &newdir, cnp, NULL)) != 0) + if ((error = ufs_direnter(dvp, tvp, &newdir, cnp, NULL)) != 0) goto bad; if ((cnp->cn_flags & SAVESTART) == 0) |