Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/vfs_hash.c
Show First 20 Lines • Show All 70 Lines • ▼ Show 20 Lines | vfs_hash_bucket(const struct mount *mp, u_int hash) | ||||
return (&vfs_hash_tbl[(hash + mp->mnt_hashseed) & vfs_hash_mask]); | return (&vfs_hash_tbl[(hash + mp->mnt_hashseed) & vfs_hash_mask]); | ||||
} | } | ||||
int | int | ||||
vfs_hash_get(const struct mount *mp, u_int hash, int flags, struct thread *td, | vfs_hash_get(const struct mount *mp, u_int hash, int flags, struct thread *td, | ||||
struct vnode **vpp, vfs_hash_cmp_t *fn, void *arg) | struct vnode **vpp, vfs_hash_cmp_t *fn, void *arg) | ||||
{ | { | ||||
struct vnode *vp; | struct vnode *vp; | ||||
enum vgetstate vs; | |||||
int error; | int error; | ||||
while (1) { | while (1) { | ||||
rw_rlock(&vfs_hash_lock); | rw_rlock(&vfs_hash_lock); | ||||
LIST_FOREACH(vp, vfs_hash_bucket(mp, hash), v_hashlist) { | LIST_FOREACH(vp, vfs_hash_bucket(mp, hash), v_hashlist) { | ||||
if (vp->v_hash != hash) | if (vp->v_hash != hash) | ||||
continue; | continue; | ||||
if (vp->v_mount != mp) | if (vp->v_mount != mp) | ||||
continue; | continue; | ||||
if (fn != NULL && fn(vp, arg)) | if (fn != NULL && fn(vp, arg)) | ||||
continue; | continue; | ||||
vhold(vp); | vs = vget_prep(vp); | ||||
rw_runlock(&vfs_hash_lock); | rw_runlock(&vfs_hash_lock); | ||||
error = vget(vp, flags | LK_VNHELD, td); | error = vget_finish(vp, flags, vs); | ||||
if (error == ENOENT && (flags & LK_NOWAIT) == 0) | if (error == ENOENT && (flags & LK_NOWAIT) == 0) | ||||
break; | break; | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
*vpp = vp; | *vpp = vp; | ||||
return (0); | return (0); | ||||
} | } | ||||
if (vp == NULL) { | if (vp == NULL) { | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | vfs_hash_remove(struct vnode *vp) | ||||
rw_wunlock(&vfs_hash_lock); | rw_wunlock(&vfs_hash_lock); | ||||
} | } | ||||
int | int | ||||
vfs_hash_insert(struct vnode *vp, u_int hash, int flags, struct thread *td, | vfs_hash_insert(struct vnode *vp, u_int hash, int flags, struct thread *td, | ||||
struct vnode **vpp, vfs_hash_cmp_t *fn, void *arg) | struct vnode **vpp, vfs_hash_cmp_t *fn, void *arg) | ||||
{ | { | ||||
struct vnode *vp2; | struct vnode *vp2; | ||||
enum vgetstate vs; | |||||
int error; | int error; | ||||
*vpp = NULL; | *vpp = NULL; | ||||
while (1) { | while (1) { | ||||
rw_wlock(&vfs_hash_lock); | rw_wlock(&vfs_hash_lock); | ||||
LIST_FOREACH(vp2, | LIST_FOREACH(vp2, | ||||
vfs_hash_bucket(vp->v_mount, hash), v_hashlist) { | vfs_hash_bucket(vp->v_mount, hash), v_hashlist) { | ||||
if (vp2->v_hash != hash) | if (vp2->v_hash != hash) | ||||
continue; | continue; | ||||
if (vp2->v_mount != vp->v_mount) | if (vp2->v_mount != vp->v_mount) | ||||
continue; | continue; | ||||
if (fn != NULL && fn(vp2, arg)) | if (fn != NULL && fn(vp2, arg)) | ||||
continue; | continue; | ||||
vhold(vp2); | vs = vget_prep(vp2); | ||||
rw_wunlock(&vfs_hash_lock); | rw_wunlock(&vfs_hash_lock); | ||||
error = vget(vp2, flags | LK_VNHELD, td); | error = vget_finish(vp2, flags, vs); | ||||
if (error == ENOENT && (flags & LK_NOWAIT) == 0) | if (error == ENOENT && (flags & LK_NOWAIT) == 0) | ||||
break; | break; | ||||
rw_wlock(&vfs_hash_lock); | rw_wlock(&vfs_hash_lock); | ||||
LIST_INSERT_HEAD(&vfs_hash_side, vp, v_hashlist); | LIST_INSERT_HEAD(&vfs_hash_side, vp, v_hashlist); | ||||
rw_wunlock(&vfs_hash_lock); | rw_wunlock(&vfs_hash_lock); | ||||
vput(vp); | vput(vp); | ||||
if (!error) | if (!error) | ||||
*vpp = vp2; | *vpp = vp2; | ||||
▲ Show 20 Lines • Show All 59 Lines • Show Last 20 Lines |