diff options
author | jhb <jhb@FreeBSD.org> | 2009-02-09 20:50:23 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2009-02-09 20:50:23 +0000 |
commit | 48ea2cb2ca9b5c828fc829924277900c2a269471 (patch) | |
tree | 7875828c5ce171cb0127f73d765d184133bfd384 /sys/fs/udf/udf_vfsops.c | |
parent | cf9ddd99b24e2dc96a1c93ff5ce6baaca7cb8ea5 (diff) | |
download | FreeBSD-src-48ea2cb2ca9b5c828fc829924277900c2a269471.zip FreeBSD-src-48ea2cb2ca9b5c828fc829924277900c2a269471.tar.gz |
Mark udf(4) MPSAFE and add support for shared vnode locks during pathname
lookups:
- Honor the caller's locking flags in udf_root() and udf_vget().
- Set VV_ROOT for the root vnode in udf_vget() instead of only doing it in
udf_root().
- Honor the requested locking flags during pathname lookups in udf_lookup().
- Release the buffer holding the directory data before looking up the vnode
for a given file to avoid a LOR between the "udf" vnode locks and
"bufwait".
- Use vn_vget_ino() to handle ".." lookups.
- Special case "." lookups instead of calling udf_vget(). We have to do
extra checking for the vnode lock for "." lookups.
Diffstat (limited to 'sys/fs/udf/udf_vfsops.c')
-rw-r--r-- | sys/fs/udf/udf_vfsops.c | 35 |
1 files changed, 25 insertions, 10 deletions
diff --git a/sys/fs/udf/udf_vfsops.c b/sys/fs/udf/udf_vfsops.c index faab9df..3d3b86d 100644 --- a/sys/fs/udf/udf_vfsops.c +++ b/sys/fs/udf/udf_vfsops.c @@ -344,6 +344,7 @@ udf_mountfs(struct vnode *devvp, struct mount *mp) { mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum; MNT_ILOCK(mp); mp->mnt_flag |= MNT_LOCAL; + mp->mnt_kern_flag |= MNTK_MPSAFE | MNTK_LOOKUP_SHARED; MNT_IUNLOCK(mp); udfmp->im_mountp = mp; udfmp->im_dev = devvp->v_rdev; @@ -546,22 +547,13 @@ static int udf_root(struct mount *mp, int flags, struct vnode **vpp, struct thread *td) { struct udf_mnt *udfmp; - struct vnode *vp; ino_t id; - int error; udfmp = VFSTOUDFFS(mp); id = udf_getid(&udfmp->root_icb); - error = udf_vget(mp, id, LK_EXCLUSIVE, vpp); - if (error) - return error; - - vp = *vpp; - vp->v_vflag |= VV_ROOT; - - return (0); + return (udf_vget(mp, id, flags, vpp)); } static int @@ -597,6 +589,22 @@ udf_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp) if (error || *vpp != NULL) return (error); + /* + * We must promote to an exclusive lock for vnode creation. This + * can happen if lookup is passed LOCKSHARED. + */ + if ((flags & LK_TYPE_MASK) == LK_SHARED) { + flags &= ~LK_TYPE_MASK; + flags |= LK_EXCLUSIVE; + } + + /* + * We do not lock vnode creation as it is believed to be too + * expensive for such rare case as simultaneous creation of vnode + * for same ino by different processes. We just allow them to race + * and check later to decide who wins. Let the race begin! + */ + td = curthread; udfmp = VFSTOUDFFS(mp); @@ -689,6 +697,13 @@ udf_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp) vp->v_type = VLNK; break; } + + if (vp->v_type != VFIFO) + VN_LOCK_ASHARE(vp); + + if (ino == udf_getid(&udfmp->root_icb)) + vp->v_vflag |= VV_ROOT; + *vpp = vp; return (0); |