/* * follow a link from a mountpoint directory, thus causing it to be mounted */ static void *afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd) { struct vfsmount *newmnt; int err; _enter("%p{%s},{%s:%p{%s},}", dentry, dentry->d_name.name, nd->mnt->mnt_devname, dentry, nd->dentry->d_name.name); dput(nd->dentry); nd->dentry = dget(dentry); newmnt = afs_mntpt_do_automount(nd->dentry); if (IS_ERR(newmnt)) { path_release(nd); return (void *)newmnt; } mntget(newmnt); err = do_add_mount(newmnt, nd, MNT_SHRINKABLE, &afs_vfsmounts); switch (err) { case 0: mntput(nd->mnt); dput(nd->dentry); nd->mnt = newmnt; nd->dentry = dget(newmnt->mnt_root); schedule_delayed_work(&afs_mntpt_expiry_timer, afs_mntpt_expiry_timeout * HZ); break; case -EBUSY: /* someone else made a mount here whilst we were busy */ while (d_mountpoint(nd->dentry) && follow_down(&nd->mnt, &nd->dentry)) ; err = 0; default: mntput(newmnt); break; } _leave(" = %d", err); return ERR_PTR(err); }
/* * handle an automount point */ struct vfsmount *afs_d_automount(struct path *path) { struct vfsmount *newmnt; _enter("{%pd}", path->dentry); newmnt = afs_mntpt_do_automount(path->dentry); if (IS_ERR(newmnt)) return newmnt; mntget(newmnt); /* prevent immediate expiration */ mnt_set_expiry(newmnt, &afs_vfsmounts); queue_delayed_work(afs_wq, &afs_mntpt_expiry_timer, afs_mntpt_expiry_timeout * HZ); _leave(" = %p", newmnt); return newmnt; }
/* * follow a link from a mountpoint directory, thus causing it to be mounted */ static void *afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd) { struct vfsmount *newmnt; struct dentry *old_dentry; int err; kenter("%p{%s},{%s:%p{%s}}", dentry, dentry->d_name.name, nd->mnt->mnt_devname, dentry, nd->dentry->d_name.name); newmnt = afs_mntpt_do_automount(dentry); if (IS_ERR(newmnt)) { path_release(nd); return (void *)newmnt; } old_dentry = nd->dentry; nd->dentry = dentry; err = do_add_mount(newmnt, nd, 0, &afs_vfsmounts); nd->dentry = old_dentry; path_release(nd); if (!err) { mntget(newmnt); nd->mnt = newmnt; dget(newmnt->mnt_root); nd->dentry = newmnt->mnt_root; } kleave(" = %d", err); return ERR_PTR(err); } /* end afs_mntpt_follow_link() */