new helper: __legitimize_mnt()
same as legitimize_mnt(), except that it does *not* drop and regain rcu_read_lock; return values are 0 => grabbed a reference, we are fine 1 => failed, just go away -1 => failed, go away and mntput(bastard) when outside of rcu_read_lock Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
31956502dd
commit
294d71ff2f
|
@ -88,6 +88,7 @@ static inline int is_mounted(struct vfsmount *mnt)
|
||||||
extern struct mount *__lookup_mnt(struct vfsmount *, struct dentry *);
|
extern struct mount *__lookup_mnt(struct vfsmount *, struct dentry *);
|
||||||
extern struct mount *__lookup_mnt_last(struct vfsmount *, struct dentry *);
|
extern struct mount *__lookup_mnt_last(struct vfsmount *, struct dentry *);
|
||||||
|
|
||||||
|
extern int __legitimize_mnt(struct vfsmount *, unsigned);
|
||||||
extern bool legitimize_mnt(struct vfsmount *, unsigned);
|
extern bool legitimize_mnt(struct vfsmount *, unsigned);
|
||||||
|
|
||||||
extern void __detach_mounts(struct dentry *dentry);
|
extern void __detach_mounts(struct dentry *dentry);
|
||||||
|
|
|
@ -590,24 +590,35 @@ static void delayed_free_vfsmnt(struct rcu_head *head)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* call under rcu_read_lock */
|
/* call under rcu_read_lock */
|
||||||
bool legitimize_mnt(struct vfsmount *bastard, unsigned seq)
|
int __legitimize_mnt(struct vfsmount *bastard, unsigned seq)
|
||||||
{
|
{
|
||||||
struct mount *mnt;
|
struct mount *mnt;
|
||||||
if (read_seqretry(&mount_lock, seq))
|
if (read_seqretry(&mount_lock, seq))
|
||||||
return false;
|
return 1;
|
||||||
if (bastard == NULL)
|
if (bastard == NULL)
|
||||||
return true;
|
return 0;
|
||||||
mnt = real_mount(bastard);
|
mnt = real_mount(bastard);
|
||||||
mnt_add_count(mnt, 1);
|
mnt_add_count(mnt, 1);
|
||||||
if (likely(!read_seqretry(&mount_lock, seq)))
|
if (likely(!read_seqretry(&mount_lock, seq)))
|
||||||
return true;
|
return 0;
|
||||||
if (bastard->mnt_flags & MNT_SYNC_UMOUNT) {
|
if (bastard->mnt_flags & MNT_SYNC_UMOUNT) {
|
||||||
mnt_add_count(mnt, -1);
|
mnt_add_count(mnt, -1);
|
||||||
return false;
|
return 1;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* call under rcu_read_lock */
|
||||||
|
bool legitimize_mnt(struct vfsmount *bastard, unsigned seq)
|
||||||
|
{
|
||||||
|
int res = __legitimize_mnt(bastard, seq);
|
||||||
|
if (likely(!res))
|
||||||
|
return true;
|
||||||
|
if (unlikely(res < 0)) {
|
||||||
|
rcu_read_unlock();
|
||||||
|
mntput(bastard);
|
||||||
|
rcu_read_lock();
|
||||||
}
|
}
|
||||||
rcu_read_unlock();
|
|
||||||
mntput(bastard);
|
|
||||||
rcu_read_lock();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue