static int noinline_for_stack au_opts_parse_mod(struct au_opt_mod *mod, substring_t args[]) { int err; struct path path; char *p; err = -EINVAL; mod->path = args[0].from; p = strchr(mod->path, '='); if (unlikely(!p)) { pr_err("no permssion %s\n", args[0].from); goto out; } *p++ = 0; err = vfsub_kern_path(mod->path, lkup_dirflags, &path); if (unlikely(err)) { pr_err("lookup failed %s (%d)\n", mod->path, err); goto out; } mod->perm = br_perm_val(p); AuDbg("mod path %s, perm 0x%x, %s\n", mod->path, mod->perm, p); mod->h_root = dget(path.dentry); path_put(&path); out: return err; }
static int opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags, aufs_bindex_t bindex) { int err; struct au_opt_add *add = &opt->add; char *p; add->bindex = bindex; add->perm = AuBrPerm_RO; add->pathname = opt_str; p = strchr(opt_str, '='); if (p) { *p++ = 0; if (*p) add->perm = br_perm_val(p); } err = vfsub_kern_path(add->pathname, lkup_dirflags, &add->path); if (!err) { if (!p) { add->perm = AuBrPerm_RO; if (au_test_fs_rr(add->path.dentry->d_sb)) add->perm = AuBrPerm_RR; else if (!bindex && !(sb_flags & MS_RDONLY)) add->perm = AuBrPerm_RW; } opt->type = Opt_add; goto out; } pr_err("lookup failed %s (%d)\n", add->pathname, err); err = -EINVAL; out: return err; }
static int au_opts_parse_del(struct au_opt_del *del, substring_t args[]) { int err; del->pathname = args[0].from; AuDbg("del path %s\n", del->pathname); err = vfsub_kern_path(del->pathname, lkup_dirflags, &del->h_path); if (unlikely(err)) pr_err("lookup failed %s (%d)\n", del->pathname, err); return err; }
static int noinline_for_stack au_opts_parse_xino_itrunc_path(struct super_block *sb, struct au_opt_xino_itrunc *xino_itrunc, substring_t args[]) { int err; aufs_bindex_t bend, bindex; struct path path; struct dentry *root; err = vfsub_kern_path(args[0].from, lkup_dirflags, &path); if (unlikely(err)) { pr_err("lookup failed %s (%d)\n", args[0].from, err); goto out; } xino_itrunc->bindex = -1; root = sb->s_root; aufs_read_lock(root, AuLock_FLUSH); bend = au_sbend(sb); for (bindex = 0; bindex <= bend; bindex++) { if (au_h_dptr(root, bindex) == path.dentry) { xino_itrunc->bindex = bindex; break; } } aufs_read_unlock(root, !AuLock_IR); path_put(&path); if (unlikely(xino_itrunc->bindex < 0)) { pr_err("no such branch %s\n", args[0].from); err = -EINVAL; } out: return err; }
static struct dentry *decode_by_path(struct super_block *sb, aufs_bindex_t bindex, ino_t ino, __u32 *fh, int fh_len, struct au_nfsd_si_lock *nsi_lock) { struct dentry *dentry, *h_parent, *root; struct super_block *h_sb; char *pathname, *p; struct vfsmount *h_mnt; struct au_branch *br; int err; struct path path; br = au_sbr(sb, bindex); /* au_br_get(br); */ h_mnt = br->br_mnt; h_sb = h_mnt->mnt_sb; /* todo: call lower fh_to_dentry()? fh_to_parent()? */ h_parent = exportfs_decode_fh(h_mnt, (void *)(fh + Fh_tail), fh_len - Fh_tail, fh[Fh_h_type], h_acceptable, /*context*/NULL); dentry = h_parent; if (unlikely(!h_parent || IS_ERR(h_parent))) { AuWarn1("%s decode_fh failed, %ld\n", au_sbtype(h_sb), PTR_ERR(h_parent)); goto out; } dentry = NULL; if (unlikely(au_test_anon(h_parent))) { AuWarn1("%s decode_fh returned a disconnected dentry\n", au_sbtype(h_sb)); goto out_h_parent; } dentry = ERR_PTR(-ENOMEM); pathname = (void *)__get_free_page(GFP_NOFS); if (unlikely(!pathname)) goto out_h_parent; root = sb->s_root; path.mnt = h_mnt; di_read_lock_parent(root, !AuLock_IR); path.dentry = au_h_dptr(root, bindex); di_read_unlock(root, !AuLock_IR); p = au_build_path(h_parent, &path, pathname, PAGE_SIZE, sb); dentry = (void *)p; if (IS_ERR(p)) goto out_pathname; si_read_unlock(sb); err = vfsub_kern_path(p, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path); dentry = ERR_PTR(err); if (unlikely(err)) goto out_relock; dentry = ERR_PTR(-ENOENT); AuDebugOn(au_test_anon(path.dentry)); if (unlikely(!path.dentry->d_inode)) goto out_path; if (ino != path.dentry->d_inode->i_ino) dentry = au_lkup_by_ino(&path, ino, /*nsi_lock*/NULL); else dentry = dget(path.dentry); out_path: path_put(&path); out_relock: if (unlikely(si_nfsd_read_lock(sb, nsi_lock) < 0)) if (!IS_ERR(dentry)) { dput(dentry); dentry = ERR_PTR(-ESTALE); } out_pathname: free_page((unsigned long)pathname); out_h_parent: dput(h_parent); out: /* au_br_put(br); */ AuTraceErrPtr(dentry); return dentry; }