162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved 462306a36Sopenharmony_ci * Copyright 1999-2000 Jeremy Fitzhardinge <jeremy@goop.org> 562306a36Sopenharmony_ci * Copyright 2001-2006 Ian Kent <raven@themaw.net> 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/capability.h> 962306a36Sopenharmony_ci#include <linux/compat.h> 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include "autofs_i.h" 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_cistatic int autofs_dir_permission(struct mnt_idmap *, struct inode *, int); 1462306a36Sopenharmony_cistatic int autofs_dir_symlink(struct mnt_idmap *, struct inode *, 1562306a36Sopenharmony_ci struct dentry *, const char *); 1662306a36Sopenharmony_cistatic int autofs_dir_unlink(struct inode *, struct dentry *); 1762306a36Sopenharmony_cistatic int autofs_dir_rmdir(struct inode *, struct dentry *); 1862306a36Sopenharmony_cistatic int autofs_dir_mkdir(struct mnt_idmap *, struct inode *, 1962306a36Sopenharmony_ci struct dentry *, umode_t); 2062306a36Sopenharmony_cistatic long autofs_root_ioctl(struct file *, unsigned int, unsigned long); 2162306a36Sopenharmony_ci#ifdef CONFIG_COMPAT 2262306a36Sopenharmony_cistatic long autofs_root_compat_ioctl(struct file *, 2362306a36Sopenharmony_ci unsigned int, unsigned long); 2462306a36Sopenharmony_ci#endif 2562306a36Sopenharmony_cistatic int autofs_dir_open(struct inode *inode, struct file *file); 2662306a36Sopenharmony_cistatic struct dentry *autofs_lookup(struct inode *, 2762306a36Sopenharmony_ci struct dentry *, unsigned int); 2862306a36Sopenharmony_cistatic struct vfsmount *autofs_d_automount(struct path *); 2962306a36Sopenharmony_cistatic int autofs_d_manage(const struct path *, bool); 3062306a36Sopenharmony_cistatic void autofs_dentry_release(struct dentry *); 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ciconst struct file_operations autofs_root_operations = { 3362306a36Sopenharmony_ci .open = dcache_dir_open, 3462306a36Sopenharmony_ci .release = dcache_dir_close, 3562306a36Sopenharmony_ci .read = generic_read_dir, 3662306a36Sopenharmony_ci .iterate_shared = dcache_readdir, 3762306a36Sopenharmony_ci .llseek = dcache_dir_lseek, 3862306a36Sopenharmony_ci .unlocked_ioctl = autofs_root_ioctl, 3962306a36Sopenharmony_ci#ifdef CONFIG_COMPAT 4062306a36Sopenharmony_ci .compat_ioctl = autofs_root_compat_ioctl, 4162306a36Sopenharmony_ci#endif 4262306a36Sopenharmony_ci}; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ciconst struct file_operations autofs_dir_operations = { 4562306a36Sopenharmony_ci .open = autofs_dir_open, 4662306a36Sopenharmony_ci .release = dcache_dir_close, 4762306a36Sopenharmony_ci .read = generic_read_dir, 4862306a36Sopenharmony_ci .iterate_shared = dcache_readdir, 4962306a36Sopenharmony_ci .llseek = dcache_dir_lseek, 5062306a36Sopenharmony_ci}; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ciconst struct inode_operations autofs_dir_inode_operations = { 5362306a36Sopenharmony_ci .lookup = autofs_lookup, 5462306a36Sopenharmony_ci .permission = autofs_dir_permission, 5562306a36Sopenharmony_ci .unlink = autofs_dir_unlink, 5662306a36Sopenharmony_ci .symlink = autofs_dir_symlink, 5762306a36Sopenharmony_ci .mkdir = autofs_dir_mkdir, 5862306a36Sopenharmony_ci .rmdir = autofs_dir_rmdir, 5962306a36Sopenharmony_ci}; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ciconst struct dentry_operations autofs_dentry_operations = { 6262306a36Sopenharmony_ci .d_automount = autofs_d_automount, 6362306a36Sopenharmony_ci .d_manage = autofs_d_manage, 6462306a36Sopenharmony_ci .d_release = autofs_dentry_release, 6562306a36Sopenharmony_ci}; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_cistatic void autofs_del_active(struct dentry *dentry) 6862306a36Sopenharmony_ci{ 6962306a36Sopenharmony_ci struct autofs_sb_info *sbi = autofs_sbi(dentry->d_sb); 7062306a36Sopenharmony_ci struct autofs_info *ino; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci ino = autofs_dentry_ino(dentry); 7362306a36Sopenharmony_ci spin_lock(&sbi->lookup_lock); 7462306a36Sopenharmony_ci list_del_init(&ino->active); 7562306a36Sopenharmony_ci spin_unlock(&sbi->lookup_lock); 7662306a36Sopenharmony_ci} 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_cistatic int autofs_dir_open(struct inode *inode, struct file *file) 7962306a36Sopenharmony_ci{ 8062306a36Sopenharmony_ci struct dentry *dentry = file->f_path.dentry; 8162306a36Sopenharmony_ci struct autofs_sb_info *sbi = autofs_sbi(dentry->d_sb); 8262306a36Sopenharmony_ci struct autofs_info *ino = autofs_dentry_ino(dentry); 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci pr_debug("file=%p dentry=%p %pd\n", file, dentry, dentry); 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci if (autofs_oz_mode(sbi)) 8762306a36Sopenharmony_ci goto out; 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci /* 9062306a36Sopenharmony_ci * An empty directory in an autofs file system is always a 9162306a36Sopenharmony_ci * mount point. The daemon must have failed to mount this 9262306a36Sopenharmony_ci * during lookup so it doesn't exist. This can happen, for 9362306a36Sopenharmony_ci * example, if user space returns an incorrect status for a 9462306a36Sopenharmony_ci * mount request. Otherwise we're doing a readdir on the 9562306a36Sopenharmony_ci * autofs file system so just let the libfs routines handle 9662306a36Sopenharmony_ci * it. 9762306a36Sopenharmony_ci */ 9862306a36Sopenharmony_ci spin_lock(&sbi->lookup_lock); 9962306a36Sopenharmony_ci if (!path_is_mountpoint(&file->f_path) && autofs_empty(ino)) { 10062306a36Sopenharmony_ci spin_unlock(&sbi->lookup_lock); 10162306a36Sopenharmony_ci return -ENOENT; 10262306a36Sopenharmony_ci } 10362306a36Sopenharmony_ci spin_unlock(&sbi->lookup_lock); 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ciout: 10662306a36Sopenharmony_ci return dcache_dir_open(inode, file); 10762306a36Sopenharmony_ci} 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_cistatic void autofs_dentry_release(struct dentry *de) 11062306a36Sopenharmony_ci{ 11162306a36Sopenharmony_ci struct autofs_info *ino = autofs_dentry_ino(de); 11262306a36Sopenharmony_ci struct autofs_sb_info *sbi = autofs_sbi(de->d_sb); 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci pr_debug("releasing %p\n", de); 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci if (!ino) 11762306a36Sopenharmony_ci return; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci if (sbi) { 12062306a36Sopenharmony_ci spin_lock(&sbi->lookup_lock); 12162306a36Sopenharmony_ci if (!list_empty(&ino->active)) 12262306a36Sopenharmony_ci list_del(&ino->active); 12362306a36Sopenharmony_ci if (!list_empty(&ino->expiring)) 12462306a36Sopenharmony_ci list_del(&ino->expiring); 12562306a36Sopenharmony_ci spin_unlock(&sbi->lookup_lock); 12662306a36Sopenharmony_ci } 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci autofs_free_ino(ino); 12962306a36Sopenharmony_ci} 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_cistatic struct dentry *autofs_lookup_active(struct dentry *dentry) 13262306a36Sopenharmony_ci{ 13362306a36Sopenharmony_ci struct autofs_sb_info *sbi = autofs_sbi(dentry->d_sb); 13462306a36Sopenharmony_ci struct dentry *parent = dentry->d_parent; 13562306a36Sopenharmony_ci const struct qstr *name = &dentry->d_name; 13662306a36Sopenharmony_ci unsigned int len = name->len; 13762306a36Sopenharmony_ci unsigned int hash = name->hash; 13862306a36Sopenharmony_ci const unsigned char *str = name->name; 13962306a36Sopenharmony_ci struct list_head *p, *head; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci head = &sbi->active_list; 14262306a36Sopenharmony_ci if (list_empty(head)) 14362306a36Sopenharmony_ci return NULL; 14462306a36Sopenharmony_ci spin_lock(&sbi->lookup_lock); 14562306a36Sopenharmony_ci list_for_each(p, head) { 14662306a36Sopenharmony_ci struct autofs_info *ino; 14762306a36Sopenharmony_ci struct dentry *active; 14862306a36Sopenharmony_ci const struct qstr *qstr; 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci ino = list_entry(p, struct autofs_info, active); 15162306a36Sopenharmony_ci active = ino->dentry; 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci spin_lock(&active->d_lock); 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci /* Already gone? */ 15662306a36Sopenharmony_ci if ((int) d_count(active) <= 0) 15762306a36Sopenharmony_ci goto next; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci qstr = &active->d_name; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci if (active->d_name.hash != hash) 16262306a36Sopenharmony_ci goto next; 16362306a36Sopenharmony_ci if (active->d_parent != parent) 16462306a36Sopenharmony_ci goto next; 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci if (qstr->len != len) 16762306a36Sopenharmony_ci goto next; 16862306a36Sopenharmony_ci if (memcmp(qstr->name, str, len)) 16962306a36Sopenharmony_ci goto next; 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci if (d_unhashed(active)) { 17262306a36Sopenharmony_ci dget_dlock(active); 17362306a36Sopenharmony_ci spin_unlock(&active->d_lock); 17462306a36Sopenharmony_ci spin_unlock(&sbi->lookup_lock); 17562306a36Sopenharmony_ci return active; 17662306a36Sopenharmony_ci } 17762306a36Sopenharmony_cinext: 17862306a36Sopenharmony_ci spin_unlock(&active->d_lock); 17962306a36Sopenharmony_ci } 18062306a36Sopenharmony_ci spin_unlock(&sbi->lookup_lock); 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci return NULL; 18362306a36Sopenharmony_ci} 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_cistatic struct dentry *autofs_lookup_expiring(struct dentry *dentry, 18662306a36Sopenharmony_ci bool rcu_walk) 18762306a36Sopenharmony_ci{ 18862306a36Sopenharmony_ci struct autofs_sb_info *sbi = autofs_sbi(dentry->d_sb); 18962306a36Sopenharmony_ci struct dentry *parent = dentry->d_parent; 19062306a36Sopenharmony_ci const struct qstr *name = &dentry->d_name; 19162306a36Sopenharmony_ci unsigned int len = name->len; 19262306a36Sopenharmony_ci unsigned int hash = name->hash; 19362306a36Sopenharmony_ci const unsigned char *str = name->name; 19462306a36Sopenharmony_ci struct list_head *p, *head; 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci head = &sbi->expiring_list; 19762306a36Sopenharmony_ci if (list_empty(head)) 19862306a36Sopenharmony_ci return NULL; 19962306a36Sopenharmony_ci spin_lock(&sbi->lookup_lock); 20062306a36Sopenharmony_ci list_for_each(p, head) { 20162306a36Sopenharmony_ci struct autofs_info *ino; 20262306a36Sopenharmony_ci struct dentry *expiring; 20362306a36Sopenharmony_ci const struct qstr *qstr; 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci if (rcu_walk) { 20662306a36Sopenharmony_ci spin_unlock(&sbi->lookup_lock); 20762306a36Sopenharmony_ci return ERR_PTR(-ECHILD); 20862306a36Sopenharmony_ci } 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci ino = list_entry(p, struct autofs_info, expiring); 21162306a36Sopenharmony_ci expiring = ino->dentry; 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci spin_lock(&expiring->d_lock); 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci /* We've already been dentry_iput or unlinked */ 21662306a36Sopenharmony_ci if (d_really_is_negative(expiring)) 21762306a36Sopenharmony_ci goto next; 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci qstr = &expiring->d_name; 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci if (expiring->d_name.hash != hash) 22262306a36Sopenharmony_ci goto next; 22362306a36Sopenharmony_ci if (expiring->d_parent != parent) 22462306a36Sopenharmony_ci goto next; 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci if (qstr->len != len) 22762306a36Sopenharmony_ci goto next; 22862306a36Sopenharmony_ci if (memcmp(qstr->name, str, len)) 22962306a36Sopenharmony_ci goto next; 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci if (d_unhashed(expiring)) { 23262306a36Sopenharmony_ci dget_dlock(expiring); 23362306a36Sopenharmony_ci spin_unlock(&expiring->d_lock); 23462306a36Sopenharmony_ci spin_unlock(&sbi->lookup_lock); 23562306a36Sopenharmony_ci return expiring; 23662306a36Sopenharmony_ci } 23762306a36Sopenharmony_cinext: 23862306a36Sopenharmony_ci spin_unlock(&expiring->d_lock); 23962306a36Sopenharmony_ci } 24062306a36Sopenharmony_ci spin_unlock(&sbi->lookup_lock); 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci return NULL; 24362306a36Sopenharmony_ci} 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_cistatic int autofs_mount_wait(const struct path *path, bool rcu_walk) 24662306a36Sopenharmony_ci{ 24762306a36Sopenharmony_ci struct autofs_sb_info *sbi = autofs_sbi(path->dentry->d_sb); 24862306a36Sopenharmony_ci struct autofs_info *ino = autofs_dentry_ino(path->dentry); 24962306a36Sopenharmony_ci int status = 0; 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci if (ino->flags & AUTOFS_INF_PENDING) { 25262306a36Sopenharmony_ci if (rcu_walk) 25362306a36Sopenharmony_ci return -ECHILD; 25462306a36Sopenharmony_ci pr_debug("waiting for mount name=%pd\n", path->dentry); 25562306a36Sopenharmony_ci status = autofs_wait(sbi, path, NFY_MOUNT); 25662306a36Sopenharmony_ci pr_debug("mount wait done status=%d\n", status); 25762306a36Sopenharmony_ci ino->last_used = jiffies; 25862306a36Sopenharmony_ci return status; 25962306a36Sopenharmony_ci } 26062306a36Sopenharmony_ci if (!(sbi->flags & AUTOFS_SBI_STRICTEXPIRE)) 26162306a36Sopenharmony_ci ino->last_used = jiffies; 26262306a36Sopenharmony_ci return status; 26362306a36Sopenharmony_ci} 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_cistatic int do_expire_wait(const struct path *path, bool rcu_walk) 26662306a36Sopenharmony_ci{ 26762306a36Sopenharmony_ci struct dentry *dentry = path->dentry; 26862306a36Sopenharmony_ci struct dentry *expiring; 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci expiring = autofs_lookup_expiring(dentry, rcu_walk); 27162306a36Sopenharmony_ci if (IS_ERR(expiring)) 27262306a36Sopenharmony_ci return PTR_ERR(expiring); 27362306a36Sopenharmony_ci if (!expiring) 27462306a36Sopenharmony_ci return autofs_expire_wait(path, rcu_walk); 27562306a36Sopenharmony_ci else { 27662306a36Sopenharmony_ci const struct path this = { .mnt = path->mnt, .dentry = expiring }; 27762306a36Sopenharmony_ci /* 27862306a36Sopenharmony_ci * If we are racing with expire the request might not 27962306a36Sopenharmony_ci * be quite complete, but the directory has been removed 28062306a36Sopenharmony_ci * so it must have been successful, just wait for it. 28162306a36Sopenharmony_ci */ 28262306a36Sopenharmony_ci autofs_expire_wait(&this, 0); 28362306a36Sopenharmony_ci autofs_del_expiring(expiring); 28462306a36Sopenharmony_ci dput(expiring); 28562306a36Sopenharmony_ci } 28662306a36Sopenharmony_ci return 0; 28762306a36Sopenharmony_ci} 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_cistatic struct dentry *autofs_mountpoint_changed(struct path *path) 29062306a36Sopenharmony_ci{ 29162306a36Sopenharmony_ci struct dentry *dentry = path->dentry; 29262306a36Sopenharmony_ci struct autofs_sb_info *sbi = autofs_sbi(dentry->d_sb); 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci /* If this is an indirect mount the dentry could have gone away 29562306a36Sopenharmony_ci * and a new one created. 29662306a36Sopenharmony_ci * 29762306a36Sopenharmony_ci * This is unusual and I can't remember the case for which it 29862306a36Sopenharmony_ci * was originally added now. But an example of how this can 29962306a36Sopenharmony_ci * happen is an autofs indirect mount that has the "browse" 30062306a36Sopenharmony_ci * option set and also has the "symlink" option in the autofs 30162306a36Sopenharmony_ci * map entry. In this case the daemon will remove the browse 30262306a36Sopenharmony_ci * directory and create a symlink as the mount leaving the 30362306a36Sopenharmony_ci * struct path stale. 30462306a36Sopenharmony_ci * 30562306a36Sopenharmony_ci * Another not so obvious case is when a mount in an autofs 30662306a36Sopenharmony_ci * indirect mount that uses the "nobrowse" option is being 30762306a36Sopenharmony_ci * expired at the same time as a path walk. If the mount has 30862306a36Sopenharmony_ci * been umounted but the mount point directory seen before 30962306a36Sopenharmony_ci * becoming unhashed (during a lockless path walk) when a stat 31062306a36Sopenharmony_ci * family system call is made the mount won't be re-mounted as 31162306a36Sopenharmony_ci * it should. In this case the mount point that's been removed 31262306a36Sopenharmony_ci * (by the daemon) will be stale and the a new mount point 31362306a36Sopenharmony_ci * dentry created. 31462306a36Sopenharmony_ci */ 31562306a36Sopenharmony_ci if (autofs_type_indirect(sbi->type) && d_unhashed(dentry)) { 31662306a36Sopenharmony_ci struct dentry *parent = dentry->d_parent; 31762306a36Sopenharmony_ci struct autofs_info *ino; 31862306a36Sopenharmony_ci struct dentry *new; 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci new = d_lookup(parent, &dentry->d_name); 32162306a36Sopenharmony_ci if (!new) 32262306a36Sopenharmony_ci return NULL; 32362306a36Sopenharmony_ci ino = autofs_dentry_ino(new); 32462306a36Sopenharmony_ci ino->last_used = jiffies; 32562306a36Sopenharmony_ci dput(path->dentry); 32662306a36Sopenharmony_ci path->dentry = new; 32762306a36Sopenharmony_ci } 32862306a36Sopenharmony_ci return path->dentry; 32962306a36Sopenharmony_ci} 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_cistatic struct vfsmount *autofs_d_automount(struct path *path) 33262306a36Sopenharmony_ci{ 33362306a36Sopenharmony_ci struct dentry *dentry = path->dentry; 33462306a36Sopenharmony_ci struct autofs_sb_info *sbi = autofs_sbi(dentry->d_sb); 33562306a36Sopenharmony_ci struct autofs_info *ino = autofs_dentry_ino(dentry); 33662306a36Sopenharmony_ci int status; 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci pr_debug("dentry=%p %pd\n", dentry, dentry); 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci /* The daemon never triggers a mount. */ 34162306a36Sopenharmony_ci if (autofs_oz_mode(sbi)) 34262306a36Sopenharmony_ci return NULL; 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci /* 34562306a36Sopenharmony_ci * If an expire request is pending everyone must wait. 34662306a36Sopenharmony_ci * If the expire fails we're still mounted so continue 34762306a36Sopenharmony_ci * the follow and return. A return of -EAGAIN (which only 34862306a36Sopenharmony_ci * happens with indirect mounts) means the expire completed 34962306a36Sopenharmony_ci * and the directory was removed, so just go ahead and try 35062306a36Sopenharmony_ci * the mount. 35162306a36Sopenharmony_ci */ 35262306a36Sopenharmony_ci status = do_expire_wait(path, 0); 35362306a36Sopenharmony_ci if (status && status != -EAGAIN) 35462306a36Sopenharmony_ci return NULL; 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci /* Callback to the daemon to perform the mount or wait */ 35762306a36Sopenharmony_ci spin_lock(&sbi->fs_lock); 35862306a36Sopenharmony_ci if (ino->flags & AUTOFS_INF_PENDING) { 35962306a36Sopenharmony_ci spin_unlock(&sbi->fs_lock); 36062306a36Sopenharmony_ci status = autofs_mount_wait(path, 0); 36162306a36Sopenharmony_ci if (status) 36262306a36Sopenharmony_ci return ERR_PTR(status); 36362306a36Sopenharmony_ci goto done; 36462306a36Sopenharmony_ci } 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci /* 36762306a36Sopenharmony_ci * If the dentry is a symlink it's equivalent to a directory 36862306a36Sopenharmony_ci * having path_is_mountpoint() true, so there's no need to call 36962306a36Sopenharmony_ci * back to the daemon. 37062306a36Sopenharmony_ci */ 37162306a36Sopenharmony_ci if (d_really_is_positive(dentry) && d_is_symlink(dentry)) { 37262306a36Sopenharmony_ci spin_unlock(&sbi->fs_lock); 37362306a36Sopenharmony_ci goto done; 37462306a36Sopenharmony_ci } 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci if (!path_is_mountpoint(path)) { 37762306a36Sopenharmony_ci /* 37862306a36Sopenharmony_ci * It's possible that user space hasn't removed directories 37962306a36Sopenharmony_ci * after umounting a rootless multi-mount, although it 38062306a36Sopenharmony_ci * should. For v5 path_has_submounts() is sufficient to 38162306a36Sopenharmony_ci * handle this because the leaves of the directory tree under 38262306a36Sopenharmony_ci * the mount never trigger mounts themselves (they have an 38362306a36Sopenharmony_ci * autofs trigger mount mounted on them). But v4 pseudo direct 38462306a36Sopenharmony_ci * mounts do need the leaves to trigger mounts. In this case 38562306a36Sopenharmony_ci * we have no choice but to use the autofs_empty() check and 38662306a36Sopenharmony_ci * require user space behave. 38762306a36Sopenharmony_ci */ 38862306a36Sopenharmony_ci if (sbi->version > 4) { 38962306a36Sopenharmony_ci if (path_has_submounts(path)) { 39062306a36Sopenharmony_ci spin_unlock(&sbi->fs_lock); 39162306a36Sopenharmony_ci goto done; 39262306a36Sopenharmony_ci } 39362306a36Sopenharmony_ci } else { 39462306a36Sopenharmony_ci if (!autofs_empty(ino)) { 39562306a36Sopenharmony_ci spin_unlock(&sbi->fs_lock); 39662306a36Sopenharmony_ci goto done; 39762306a36Sopenharmony_ci } 39862306a36Sopenharmony_ci } 39962306a36Sopenharmony_ci ino->flags |= AUTOFS_INF_PENDING; 40062306a36Sopenharmony_ci spin_unlock(&sbi->fs_lock); 40162306a36Sopenharmony_ci status = autofs_mount_wait(path, 0); 40262306a36Sopenharmony_ci spin_lock(&sbi->fs_lock); 40362306a36Sopenharmony_ci ino->flags &= ~AUTOFS_INF_PENDING; 40462306a36Sopenharmony_ci if (status) { 40562306a36Sopenharmony_ci spin_unlock(&sbi->fs_lock); 40662306a36Sopenharmony_ci return ERR_PTR(status); 40762306a36Sopenharmony_ci } 40862306a36Sopenharmony_ci } 40962306a36Sopenharmony_ci spin_unlock(&sbi->fs_lock); 41062306a36Sopenharmony_cidone: 41162306a36Sopenharmony_ci /* Mount succeeded, check if we ended up with a new dentry */ 41262306a36Sopenharmony_ci dentry = autofs_mountpoint_changed(path); 41362306a36Sopenharmony_ci if (!dentry) 41462306a36Sopenharmony_ci return ERR_PTR(-ENOENT); 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci return NULL; 41762306a36Sopenharmony_ci} 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_cistatic int autofs_d_manage(const struct path *path, bool rcu_walk) 42062306a36Sopenharmony_ci{ 42162306a36Sopenharmony_ci struct dentry *dentry = path->dentry; 42262306a36Sopenharmony_ci struct autofs_sb_info *sbi = autofs_sbi(dentry->d_sb); 42362306a36Sopenharmony_ci struct autofs_info *ino = autofs_dentry_ino(dentry); 42462306a36Sopenharmony_ci int status; 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci pr_debug("dentry=%p %pd\n", dentry, dentry); 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci /* The daemon never waits. */ 42962306a36Sopenharmony_ci if (autofs_oz_mode(sbi)) { 43062306a36Sopenharmony_ci if (!path_is_mountpoint(path)) 43162306a36Sopenharmony_ci return -EISDIR; 43262306a36Sopenharmony_ci return 0; 43362306a36Sopenharmony_ci } 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci /* Wait for pending expires */ 43662306a36Sopenharmony_ci if (do_expire_wait(path, rcu_walk) == -ECHILD) 43762306a36Sopenharmony_ci return -ECHILD; 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci /* 44062306a36Sopenharmony_ci * This dentry may be under construction so wait on mount 44162306a36Sopenharmony_ci * completion. 44262306a36Sopenharmony_ci */ 44362306a36Sopenharmony_ci status = autofs_mount_wait(path, rcu_walk); 44462306a36Sopenharmony_ci if (status) 44562306a36Sopenharmony_ci return status; 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci if (rcu_walk) { 44862306a36Sopenharmony_ci /* We don't need fs_lock in rcu_walk mode, 44962306a36Sopenharmony_ci * just testing 'AUTOFS_INF_WANT_EXPIRE' is enough. 45062306a36Sopenharmony_ci * 45162306a36Sopenharmony_ci * We only return -EISDIR when certain this isn't 45262306a36Sopenharmony_ci * a mount-trap. 45362306a36Sopenharmony_ci */ 45462306a36Sopenharmony_ci struct inode *inode; 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci if (ino->flags & AUTOFS_INF_WANT_EXPIRE) 45762306a36Sopenharmony_ci return 0; 45862306a36Sopenharmony_ci if (path_is_mountpoint(path)) 45962306a36Sopenharmony_ci return 0; 46062306a36Sopenharmony_ci inode = d_inode_rcu(dentry); 46162306a36Sopenharmony_ci if (inode && S_ISLNK(inode->i_mode)) 46262306a36Sopenharmony_ci return -EISDIR; 46362306a36Sopenharmony_ci if (!autofs_empty(ino)) 46462306a36Sopenharmony_ci return -EISDIR; 46562306a36Sopenharmony_ci return 0; 46662306a36Sopenharmony_ci } 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci spin_lock(&sbi->fs_lock); 46962306a36Sopenharmony_ci /* 47062306a36Sopenharmony_ci * If the dentry has been selected for expire while we slept 47162306a36Sopenharmony_ci * on the lock then it might go away. We'll deal with that in 47262306a36Sopenharmony_ci * ->d_automount() and wait on a new mount if the expire 47362306a36Sopenharmony_ci * succeeds or return here if it doesn't (since there's no 47462306a36Sopenharmony_ci * mount to follow with a rootless multi-mount). 47562306a36Sopenharmony_ci */ 47662306a36Sopenharmony_ci if (!(ino->flags & AUTOFS_INF_EXPIRING)) { 47762306a36Sopenharmony_ci /* 47862306a36Sopenharmony_ci * Any needed mounting has been completed and the path 47962306a36Sopenharmony_ci * updated so check if this is a rootless multi-mount so 48062306a36Sopenharmony_ci * we can avoid needless calls ->d_automount() and avoid 48162306a36Sopenharmony_ci * an incorrect ELOOP error return. 48262306a36Sopenharmony_ci */ 48362306a36Sopenharmony_ci if ((!path_is_mountpoint(path) && !autofs_empty(ino)) || 48462306a36Sopenharmony_ci (d_really_is_positive(dentry) && d_is_symlink(dentry))) 48562306a36Sopenharmony_ci status = -EISDIR; 48662306a36Sopenharmony_ci } 48762306a36Sopenharmony_ci spin_unlock(&sbi->fs_lock); 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci return status; 49062306a36Sopenharmony_ci} 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci/* Lookups in the root directory */ 49362306a36Sopenharmony_cistatic struct dentry *autofs_lookup(struct inode *dir, 49462306a36Sopenharmony_ci struct dentry *dentry, unsigned int flags) 49562306a36Sopenharmony_ci{ 49662306a36Sopenharmony_ci struct autofs_sb_info *sbi; 49762306a36Sopenharmony_ci struct autofs_info *ino; 49862306a36Sopenharmony_ci struct dentry *active; 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_ci pr_debug("name = %pd\n", dentry); 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci /* File name too long to exist */ 50362306a36Sopenharmony_ci if (dentry->d_name.len > NAME_MAX) 50462306a36Sopenharmony_ci return ERR_PTR(-ENAMETOOLONG); 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci sbi = autofs_sbi(dir->i_sb); 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci pr_debug("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d\n", 50962306a36Sopenharmony_ci current->pid, task_pgrp_nr(current), 51062306a36Sopenharmony_ci sbi->flags & AUTOFS_SBI_CATATONIC, 51162306a36Sopenharmony_ci autofs_oz_mode(sbi)); 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci active = autofs_lookup_active(dentry); 51462306a36Sopenharmony_ci if (active) 51562306a36Sopenharmony_ci return active; 51662306a36Sopenharmony_ci else { 51762306a36Sopenharmony_ci /* 51862306a36Sopenharmony_ci * A dentry that is not within the root can never trigger a 51962306a36Sopenharmony_ci * mount operation, unless the directory already exists, so we 52062306a36Sopenharmony_ci * can return fail immediately. The daemon however does need 52162306a36Sopenharmony_ci * to create directories within the file system. 52262306a36Sopenharmony_ci */ 52362306a36Sopenharmony_ci if (!autofs_oz_mode(sbi) && !IS_ROOT(dentry->d_parent)) 52462306a36Sopenharmony_ci return ERR_PTR(-ENOENT); 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci ino = autofs_new_ino(sbi); 52762306a36Sopenharmony_ci if (!ino) 52862306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci spin_lock(&sbi->lookup_lock); 53162306a36Sopenharmony_ci spin_lock(&dentry->d_lock); 53262306a36Sopenharmony_ci /* Mark entries in the root as mount triggers */ 53362306a36Sopenharmony_ci if (IS_ROOT(dentry->d_parent) && 53462306a36Sopenharmony_ci autofs_type_indirect(sbi->type)) 53562306a36Sopenharmony_ci __managed_dentry_set_managed(dentry); 53662306a36Sopenharmony_ci dentry->d_fsdata = ino; 53762306a36Sopenharmony_ci ino->dentry = dentry; 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci list_add(&ino->active, &sbi->active_list); 54062306a36Sopenharmony_ci spin_unlock(&sbi->lookup_lock); 54162306a36Sopenharmony_ci spin_unlock(&dentry->d_lock); 54262306a36Sopenharmony_ci } 54362306a36Sopenharmony_ci return NULL; 54462306a36Sopenharmony_ci} 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_cistatic int autofs_dir_permission(struct mnt_idmap *idmap, 54762306a36Sopenharmony_ci struct inode *inode, int mask) 54862306a36Sopenharmony_ci{ 54962306a36Sopenharmony_ci if (mask & MAY_WRITE) { 55062306a36Sopenharmony_ci struct autofs_sb_info *sbi = autofs_sbi(inode->i_sb); 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ci if (!autofs_oz_mode(sbi)) 55362306a36Sopenharmony_ci return -EACCES; 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_ci /* autofs_oz_mode() needs to allow path walks when the 55662306a36Sopenharmony_ci * autofs mount is catatonic but the state of an autofs 55762306a36Sopenharmony_ci * file system needs to be preserved over restarts. 55862306a36Sopenharmony_ci */ 55962306a36Sopenharmony_ci if (sbi->flags & AUTOFS_SBI_CATATONIC) 56062306a36Sopenharmony_ci return -EACCES; 56162306a36Sopenharmony_ci } 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci return generic_permission(idmap, inode, mask); 56462306a36Sopenharmony_ci} 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_cistatic int autofs_dir_symlink(struct mnt_idmap *idmap, 56762306a36Sopenharmony_ci struct inode *dir, struct dentry *dentry, 56862306a36Sopenharmony_ci const char *symname) 56962306a36Sopenharmony_ci{ 57062306a36Sopenharmony_ci struct autofs_info *ino = autofs_dentry_ino(dentry); 57162306a36Sopenharmony_ci struct autofs_info *p_ino; 57262306a36Sopenharmony_ci struct inode *inode; 57362306a36Sopenharmony_ci size_t size = strlen(symname); 57462306a36Sopenharmony_ci char *cp; 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci pr_debug("%s <- %pd\n", symname, dentry); 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_ci BUG_ON(!ino); 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_ci autofs_clean_ino(ino); 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci autofs_del_active(dentry); 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci cp = kmalloc(size + 1, GFP_KERNEL); 58562306a36Sopenharmony_ci if (!cp) 58662306a36Sopenharmony_ci return -ENOMEM; 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci strcpy(cp, symname); 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci inode = autofs_get_inode(dir->i_sb, S_IFLNK | 0555); 59162306a36Sopenharmony_ci if (!inode) { 59262306a36Sopenharmony_ci kfree(cp); 59362306a36Sopenharmony_ci return -ENOMEM; 59462306a36Sopenharmony_ci } 59562306a36Sopenharmony_ci inode->i_private = cp; 59662306a36Sopenharmony_ci inode->i_size = size; 59762306a36Sopenharmony_ci d_add(dentry, inode); 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci dget(dentry); 60062306a36Sopenharmony_ci p_ino = autofs_dentry_ino(dentry->d_parent); 60162306a36Sopenharmony_ci p_ino->count++; 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci dir->i_mtime = inode_set_ctime_current(dir); 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_ci return 0; 60662306a36Sopenharmony_ci} 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci/* 60962306a36Sopenharmony_ci * NOTE! 61062306a36Sopenharmony_ci * 61162306a36Sopenharmony_ci * Normal filesystems would do a "d_delete()" to tell the VFS dcache 61262306a36Sopenharmony_ci * that the file no longer exists. However, doing that means that the 61362306a36Sopenharmony_ci * VFS layer can turn the dentry into a negative dentry. We don't want 61462306a36Sopenharmony_ci * this, because the unlink is probably the result of an expire. 61562306a36Sopenharmony_ci * We simply d_drop it and add it to a expiring list in the super block, 61662306a36Sopenharmony_ci * which allows the dentry lookup to check for an incomplete expire. 61762306a36Sopenharmony_ci * 61862306a36Sopenharmony_ci * If a process is blocked on the dentry waiting for the expire to finish, 61962306a36Sopenharmony_ci * it will invalidate the dentry and try to mount with a new one. 62062306a36Sopenharmony_ci * 62162306a36Sopenharmony_ci * Also see autofs_dir_rmdir().. 62262306a36Sopenharmony_ci */ 62362306a36Sopenharmony_cistatic int autofs_dir_unlink(struct inode *dir, struct dentry *dentry) 62462306a36Sopenharmony_ci{ 62562306a36Sopenharmony_ci struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb); 62662306a36Sopenharmony_ci struct autofs_info *ino = autofs_dentry_ino(dentry); 62762306a36Sopenharmony_ci struct autofs_info *p_ino; 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_ci p_ino = autofs_dentry_ino(dentry->d_parent); 63062306a36Sopenharmony_ci p_ino->count--; 63162306a36Sopenharmony_ci dput(ino->dentry); 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ci d_inode(dentry)->i_size = 0; 63462306a36Sopenharmony_ci clear_nlink(d_inode(dentry)); 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci dir->i_mtime = inode_set_ctime_current(dir); 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ci spin_lock(&sbi->lookup_lock); 63962306a36Sopenharmony_ci __autofs_add_expiring(dentry); 64062306a36Sopenharmony_ci d_drop(dentry); 64162306a36Sopenharmony_ci spin_unlock(&sbi->lookup_lock); 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci return 0; 64462306a36Sopenharmony_ci} 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_ci/* 64762306a36Sopenharmony_ci * Version 4 of autofs provides a pseudo direct mount implementation 64862306a36Sopenharmony_ci * that relies on directories at the leaves of a directory tree under 64962306a36Sopenharmony_ci * an indirect mount to trigger mounts. To allow for this we need to 65062306a36Sopenharmony_ci * set the DMANAGED_AUTOMOUNT and DMANAGED_TRANSIT flags on the leaves 65162306a36Sopenharmony_ci * of the directory tree. There is no need to clear the automount flag 65262306a36Sopenharmony_ci * following a mount or restore it after an expire because these mounts 65362306a36Sopenharmony_ci * are always covered. However, it is necessary to ensure that these 65462306a36Sopenharmony_ci * flags are clear on non-empty directories to avoid unnecessary calls 65562306a36Sopenharmony_ci * during path walks. 65662306a36Sopenharmony_ci */ 65762306a36Sopenharmony_cistatic void autofs_set_leaf_automount_flags(struct dentry *dentry) 65862306a36Sopenharmony_ci{ 65962306a36Sopenharmony_ci struct dentry *parent; 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_ci /* root and dentrys in the root are already handled */ 66262306a36Sopenharmony_ci if (IS_ROOT(dentry->d_parent)) 66362306a36Sopenharmony_ci return; 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_ci managed_dentry_set_managed(dentry); 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ci parent = dentry->d_parent; 66862306a36Sopenharmony_ci /* only consider parents below dentrys in the root */ 66962306a36Sopenharmony_ci if (IS_ROOT(parent->d_parent)) 67062306a36Sopenharmony_ci return; 67162306a36Sopenharmony_ci managed_dentry_clear_managed(parent); 67262306a36Sopenharmony_ci} 67362306a36Sopenharmony_ci 67462306a36Sopenharmony_cistatic void autofs_clear_leaf_automount_flags(struct dentry *dentry) 67562306a36Sopenharmony_ci{ 67662306a36Sopenharmony_ci struct dentry *parent; 67762306a36Sopenharmony_ci 67862306a36Sopenharmony_ci /* flags for dentrys in the root are handled elsewhere */ 67962306a36Sopenharmony_ci if (IS_ROOT(dentry->d_parent)) 68062306a36Sopenharmony_ci return; 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_ci managed_dentry_clear_managed(dentry); 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_ci parent = dentry->d_parent; 68562306a36Sopenharmony_ci /* only consider parents below dentrys in the root */ 68662306a36Sopenharmony_ci if (IS_ROOT(parent->d_parent)) 68762306a36Sopenharmony_ci return; 68862306a36Sopenharmony_ci if (autofs_dentry_ino(parent)->count == 2) 68962306a36Sopenharmony_ci managed_dentry_set_managed(parent); 69062306a36Sopenharmony_ci} 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_cistatic int autofs_dir_rmdir(struct inode *dir, struct dentry *dentry) 69362306a36Sopenharmony_ci{ 69462306a36Sopenharmony_ci struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb); 69562306a36Sopenharmony_ci struct autofs_info *ino = autofs_dentry_ino(dentry); 69662306a36Sopenharmony_ci struct autofs_info *p_ino; 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci pr_debug("dentry %p, removing %pd\n", dentry, dentry); 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci if (ino->count != 1) 70162306a36Sopenharmony_ci return -ENOTEMPTY; 70262306a36Sopenharmony_ci 70362306a36Sopenharmony_ci spin_lock(&sbi->lookup_lock); 70462306a36Sopenharmony_ci __autofs_add_expiring(dentry); 70562306a36Sopenharmony_ci d_drop(dentry); 70662306a36Sopenharmony_ci spin_unlock(&sbi->lookup_lock); 70762306a36Sopenharmony_ci 70862306a36Sopenharmony_ci if (sbi->version < 5) 70962306a36Sopenharmony_ci autofs_clear_leaf_automount_flags(dentry); 71062306a36Sopenharmony_ci 71162306a36Sopenharmony_ci p_ino = autofs_dentry_ino(dentry->d_parent); 71262306a36Sopenharmony_ci p_ino->count--; 71362306a36Sopenharmony_ci dput(ino->dentry); 71462306a36Sopenharmony_ci d_inode(dentry)->i_size = 0; 71562306a36Sopenharmony_ci clear_nlink(d_inode(dentry)); 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_ci if (dir->i_nlink) 71862306a36Sopenharmony_ci drop_nlink(dir); 71962306a36Sopenharmony_ci 72062306a36Sopenharmony_ci return 0; 72162306a36Sopenharmony_ci} 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_cistatic int autofs_dir_mkdir(struct mnt_idmap *idmap, 72462306a36Sopenharmony_ci struct inode *dir, struct dentry *dentry, 72562306a36Sopenharmony_ci umode_t mode) 72662306a36Sopenharmony_ci{ 72762306a36Sopenharmony_ci struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb); 72862306a36Sopenharmony_ci struct autofs_info *ino = autofs_dentry_ino(dentry); 72962306a36Sopenharmony_ci struct autofs_info *p_ino; 73062306a36Sopenharmony_ci struct inode *inode; 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_ci pr_debug("dentry %p, creating %pd\n", dentry, dentry); 73362306a36Sopenharmony_ci 73462306a36Sopenharmony_ci BUG_ON(!ino); 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_ci autofs_clean_ino(ino); 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_ci autofs_del_active(dentry); 73962306a36Sopenharmony_ci 74062306a36Sopenharmony_ci inode = autofs_get_inode(dir->i_sb, S_IFDIR | mode); 74162306a36Sopenharmony_ci if (!inode) 74262306a36Sopenharmony_ci return -ENOMEM; 74362306a36Sopenharmony_ci d_add(dentry, inode); 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_ci if (sbi->version < 5) 74662306a36Sopenharmony_ci autofs_set_leaf_automount_flags(dentry); 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_ci dget(dentry); 74962306a36Sopenharmony_ci p_ino = autofs_dentry_ino(dentry->d_parent); 75062306a36Sopenharmony_ci p_ino->count++; 75162306a36Sopenharmony_ci inc_nlink(dir); 75262306a36Sopenharmony_ci dir->i_mtime = inode_set_ctime_current(dir); 75362306a36Sopenharmony_ci 75462306a36Sopenharmony_ci return 0; 75562306a36Sopenharmony_ci} 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_ci/* Get/set timeout ioctl() operation */ 75862306a36Sopenharmony_ci#ifdef CONFIG_COMPAT 75962306a36Sopenharmony_cistatic inline int autofs_compat_get_set_timeout(struct autofs_sb_info *sbi, 76062306a36Sopenharmony_ci compat_ulong_t __user *p) 76162306a36Sopenharmony_ci{ 76262306a36Sopenharmony_ci unsigned long ntimeout; 76362306a36Sopenharmony_ci int rv; 76462306a36Sopenharmony_ci 76562306a36Sopenharmony_ci rv = get_user(ntimeout, p); 76662306a36Sopenharmony_ci if (rv) 76762306a36Sopenharmony_ci goto error; 76862306a36Sopenharmony_ci 76962306a36Sopenharmony_ci rv = put_user(sbi->exp_timeout/HZ, p); 77062306a36Sopenharmony_ci if (rv) 77162306a36Sopenharmony_ci goto error; 77262306a36Sopenharmony_ci 77362306a36Sopenharmony_ci if (ntimeout > UINT_MAX/HZ) 77462306a36Sopenharmony_ci sbi->exp_timeout = 0; 77562306a36Sopenharmony_ci else 77662306a36Sopenharmony_ci sbi->exp_timeout = ntimeout * HZ; 77762306a36Sopenharmony_ci 77862306a36Sopenharmony_ci return 0; 77962306a36Sopenharmony_cierror: 78062306a36Sopenharmony_ci return rv; 78162306a36Sopenharmony_ci} 78262306a36Sopenharmony_ci#endif 78362306a36Sopenharmony_ci 78462306a36Sopenharmony_cistatic inline int autofs_get_set_timeout(struct autofs_sb_info *sbi, 78562306a36Sopenharmony_ci unsigned long __user *p) 78662306a36Sopenharmony_ci{ 78762306a36Sopenharmony_ci unsigned long ntimeout; 78862306a36Sopenharmony_ci int rv; 78962306a36Sopenharmony_ci 79062306a36Sopenharmony_ci rv = get_user(ntimeout, p); 79162306a36Sopenharmony_ci if (rv) 79262306a36Sopenharmony_ci goto error; 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_ci rv = put_user(sbi->exp_timeout/HZ, p); 79562306a36Sopenharmony_ci if (rv) 79662306a36Sopenharmony_ci goto error; 79762306a36Sopenharmony_ci 79862306a36Sopenharmony_ci if (ntimeout > ULONG_MAX/HZ) 79962306a36Sopenharmony_ci sbi->exp_timeout = 0; 80062306a36Sopenharmony_ci else 80162306a36Sopenharmony_ci sbi->exp_timeout = ntimeout * HZ; 80262306a36Sopenharmony_ci 80362306a36Sopenharmony_ci return 0; 80462306a36Sopenharmony_cierror: 80562306a36Sopenharmony_ci return rv; 80662306a36Sopenharmony_ci} 80762306a36Sopenharmony_ci 80862306a36Sopenharmony_ci/* Return protocol version */ 80962306a36Sopenharmony_cistatic inline int autofs_get_protover(struct autofs_sb_info *sbi, 81062306a36Sopenharmony_ci int __user *p) 81162306a36Sopenharmony_ci{ 81262306a36Sopenharmony_ci return put_user(sbi->version, p); 81362306a36Sopenharmony_ci} 81462306a36Sopenharmony_ci 81562306a36Sopenharmony_ci/* Return protocol sub version */ 81662306a36Sopenharmony_cistatic inline int autofs_get_protosubver(struct autofs_sb_info *sbi, 81762306a36Sopenharmony_ci int __user *p) 81862306a36Sopenharmony_ci{ 81962306a36Sopenharmony_ci return put_user(sbi->sub_version, p); 82062306a36Sopenharmony_ci} 82162306a36Sopenharmony_ci 82262306a36Sopenharmony_ci/* 82362306a36Sopenharmony_ci* Tells the daemon whether it can umount the autofs mount. 82462306a36Sopenharmony_ci*/ 82562306a36Sopenharmony_cistatic inline int autofs_ask_umount(struct vfsmount *mnt, int __user *p) 82662306a36Sopenharmony_ci{ 82762306a36Sopenharmony_ci int status = 0; 82862306a36Sopenharmony_ci 82962306a36Sopenharmony_ci if (may_umount(mnt)) 83062306a36Sopenharmony_ci status = 1; 83162306a36Sopenharmony_ci 83262306a36Sopenharmony_ci pr_debug("may umount %d\n", status); 83362306a36Sopenharmony_ci 83462306a36Sopenharmony_ci status = put_user(status, p); 83562306a36Sopenharmony_ci 83662306a36Sopenharmony_ci return status; 83762306a36Sopenharmony_ci} 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_ci/* Identify autofs_dentries - this is so we can tell if there's 84062306a36Sopenharmony_ci * an extra dentry refcount or not. We only hold a refcount on the 84162306a36Sopenharmony_ci * dentry if its non-negative (ie, d_inode != NULL) 84262306a36Sopenharmony_ci */ 84362306a36Sopenharmony_ciint is_autofs_dentry(struct dentry *dentry) 84462306a36Sopenharmony_ci{ 84562306a36Sopenharmony_ci return dentry && d_really_is_positive(dentry) && 84662306a36Sopenharmony_ci dentry->d_op == &autofs_dentry_operations && 84762306a36Sopenharmony_ci dentry->d_fsdata != NULL; 84862306a36Sopenharmony_ci} 84962306a36Sopenharmony_ci 85062306a36Sopenharmony_ci/* 85162306a36Sopenharmony_ci * ioctl()'s on the root directory is the chief method for the daemon to 85262306a36Sopenharmony_ci * generate kernel reactions 85362306a36Sopenharmony_ci */ 85462306a36Sopenharmony_cistatic int autofs_root_ioctl_unlocked(struct inode *inode, struct file *filp, 85562306a36Sopenharmony_ci unsigned int cmd, unsigned long arg) 85662306a36Sopenharmony_ci{ 85762306a36Sopenharmony_ci struct autofs_sb_info *sbi = autofs_sbi(inode->i_sb); 85862306a36Sopenharmony_ci void __user *p = (void __user *)arg; 85962306a36Sopenharmony_ci 86062306a36Sopenharmony_ci pr_debug("cmd = 0x%08x, arg = 0x%08lx, sbi = %p, pgrp = %u\n", 86162306a36Sopenharmony_ci cmd, arg, sbi, task_pgrp_nr(current)); 86262306a36Sopenharmony_ci 86362306a36Sopenharmony_ci if (_IOC_TYPE(cmd) != _IOC_TYPE(AUTOFS_IOC_FIRST) || 86462306a36Sopenharmony_ci _IOC_NR(cmd) - _IOC_NR(AUTOFS_IOC_FIRST) >= AUTOFS_IOC_COUNT) 86562306a36Sopenharmony_ci return -ENOTTY; 86662306a36Sopenharmony_ci 86762306a36Sopenharmony_ci if (!autofs_oz_mode(sbi) && !capable(CAP_SYS_ADMIN)) 86862306a36Sopenharmony_ci return -EPERM; 86962306a36Sopenharmony_ci 87062306a36Sopenharmony_ci switch (cmd) { 87162306a36Sopenharmony_ci case AUTOFS_IOC_READY: /* Wait queue: go ahead and retry */ 87262306a36Sopenharmony_ci return autofs_wait_release(sbi, (autofs_wqt_t) arg, 0); 87362306a36Sopenharmony_ci case AUTOFS_IOC_FAIL: /* Wait queue: fail with ENOENT */ 87462306a36Sopenharmony_ci return autofs_wait_release(sbi, (autofs_wqt_t) arg, -ENOENT); 87562306a36Sopenharmony_ci case AUTOFS_IOC_CATATONIC: /* Enter catatonic mode (daemon shutdown) */ 87662306a36Sopenharmony_ci autofs_catatonic_mode(sbi); 87762306a36Sopenharmony_ci return 0; 87862306a36Sopenharmony_ci case AUTOFS_IOC_PROTOVER: /* Get protocol version */ 87962306a36Sopenharmony_ci return autofs_get_protover(sbi, p); 88062306a36Sopenharmony_ci case AUTOFS_IOC_PROTOSUBVER: /* Get protocol sub version */ 88162306a36Sopenharmony_ci return autofs_get_protosubver(sbi, p); 88262306a36Sopenharmony_ci case AUTOFS_IOC_SETTIMEOUT: 88362306a36Sopenharmony_ci return autofs_get_set_timeout(sbi, p); 88462306a36Sopenharmony_ci#ifdef CONFIG_COMPAT 88562306a36Sopenharmony_ci case AUTOFS_IOC_SETTIMEOUT32: 88662306a36Sopenharmony_ci return autofs_compat_get_set_timeout(sbi, p); 88762306a36Sopenharmony_ci#endif 88862306a36Sopenharmony_ci 88962306a36Sopenharmony_ci case AUTOFS_IOC_ASKUMOUNT: 89062306a36Sopenharmony_ci return autofs_ask_umount(filp->f_path.mnt, p); 89162306a36Sopenharmony_ci 89262306a36Sopenharmony_ci /* return a single thing to expire */ 89362306a36Sopenharmony_ci case AUTOFS_IOC_EXPIRE: 89462306a36Sopenharmony_ci return autofs_expire_run(inode->i_sb, filp->f_path.mnt, sbi, p); 89562306a36Sopenharmony_ci /* same as above, but can send multiple expires through pipe */ 89662306a36Sopenharmony_ci case AUTOFS_IOC_EXPIRE_MULTI: 89762306a36Sopenharmony_ci return autofs_expire_multi(inode->i_sb, 89862306a36Sopenharmony_ci filp->f_path.mnt, sbi, p); 89962306a36Sopenharmony_ci 90062306a36Sopenharmony_ci default: 90162306a36Sopenharmony_ci return -EINVAL; 90262306a36Sopenharmony_ci } 90362306a36Sopenharmony_ci} 90462306a36Sopenharmony_ci 90562306a36Sopenharmony_cistatic long autofs_root_ioctl(struct file *filp, 90662306a36Sopenharmony_ci unsigned int cmd, unsigned long arg) 90762306a36Sopenharmony_ci{ 90862306a36Sopenharmony_ci struct inode *inode = file_inode(filp); 90962306a36Sopenharmony_ci 91062306a36Sopenharmony_ci return autofs_root_ioctl_unlocked(inode, filp, cmd, arg); 91162306a36Sopenharmony_ci} 91262306a36Sopenharmony_ci 91362306a36Sopenharmony_ci#ifdef CONFIG_COMPAT 91462306a36Sopenharmony_cistatic long autofs_root_compat_ioctl(struct file *filp, 91562306a36Sopenharmony_ci unsigned int cmd, unsigned long arg) 91662306a36Sopenharmony_ci{ 91762306a36Sopenharmony_ci struct inode *inode = file_inode(filp); 91862306a36Sopenharmony_ci int ret; 91962306a36Sopenharmony_ci 92062306a36Sopenharmony_ci if (cmd == AUTOFS_IOC_READY || cmd == AUTOFS_IOC_FAIL) 92162306a36Sopenharmony_ci ret = autofs_root_ioctl_unlocked(inode, filp, cmd, arg); 92262306a36Sopenharmony_ci else 92362306a36Sopenharmony_ci ret = autofs_root_ioctl_unlocked(inode, filp, cmd, 92462306a36Sopenharmony_ci (unsigned long) compat_ptr(arg)); 92562306a36Sopenharmony_ci 92662306a36Sopenharmony_ci return ret; 92762306a36Sopenharmony_ci} 92862306a36Sopenharmony_ci#endif 929