struct dentry *vfsub__lookup_hash(struct qstr *name, struct dentry *parent, struct nameidata *nd) { struct dentry *d; LKTRTrace("%.*s/%.*s, nd %d\n", AuDLNPair(parent), AuLNPair(name), !!nd); if (nd) LKTRTrace("nd{0x%x}\n", nd->flags); IMustLock(parent->d_inode); d = __lookup_hash(name, parent, nd); if (!IS_ERR(d)) au_update_fuse_h_inode(NULL, d); /*ignore*/ return d; }
static struct dentry *lkup_hash(const char *name, struct dentry *parent, int len, struct lkup_args *lkup) { struct dentry *dentry; char *p; unsigned long hash; struct qstr this; unsigned int c; struct nameidata tmp_nd; dentry = ERR_PTR(-EACCES); this.name = name; this.len = len; if (unlikely(!len)) goto out; p = (void*)name; hash = init_name_hash(); while (len--) { c = *p++; if (unlikely(c == '/' || c == '\0')) goto out; hash = partial_name_hash(c, hash); } this.hash = end_name_hash(hash); memset(&tmp_nd, 0, sizeof(tmp_nd)); tmp_nd.dentry = dget(parent); tmp_nd.mnt = mntget(lkup->nfsmnt); #ifndef CONFIG_AUFS_DLGT dentry = __lookup_hash(&this, parent, &tmp_nd); #else if (!lkup->dlgt) dentry = __lookup_hash(&this, parent, &tmp_nd); else { int wkq_err; struct lookup_hash_args args = { .errp = &dentry, .name = &this, .base = parent, .nd = &tmp_nd }; wkq_err = au_wkq_wait(call_lookup_hash, &args, /*dlgt*/1); if (unlikely(wkq_err)) dentry = ERR_PTR(wkq_err); } #endif path_release(&tmp_nd); out: TraceErrPtr(dentry); return dentry; } #elif defined(CONFIG_AUFS_DLGT) static struct dentry *lkup_hash(const char *name, struct dentry *parent, int len, struct lkup_args *lkup) { return ERR_PTR(-ENOSYS); } #endif #ifdef CONFIG_AUFS_DLGT struct lookup_one_len_args { struct dentry **errp; const char *name; struct dentry *parent; int len; }; static void call_lookup_one_len(void *args) { struct lookup_one_len_args *a = args; *a->errp = lookup_one_len(a->name, a->parent, a->len); } #endif /* CONFIG_AUFS_DLGT */ #if defined(CONFIG_AUFS_LHASH_PATCH) || defined(CONFIG_AUFS_DLGT) /* cf. lookup_one_len() in linux/fs/namei.c */ struct dentry *lkup_one(const char *name, struct dentry *parent, int len, struct lkup_args *lkup) { struct dentry *dentry; LKTRTrace("%.*s/%.*s, lkup{%p, %d}\n", DLNPair(parent), len, name, lkup->nfsmnt, lkup->dlgt); if (!lkup->nfsmnt) { #ifndef CONFIG_AUFS_DLGT dentry = lookup_one_len(name, parent, len); #else if (!lkup->dlgt) dentry = lookup_one_len(name, parent, len); else { int wkq_err; struct lookup_one_len_args args = { .errp = &dentry, .name = name, .parent = parent, .len = len }; wkq_err = au_wkq_wait(call_lookup_one_len, &args, /*dlgt*/1); if (unlikely(wkq_err)) dentry = ERR_PTR(wkq_err); } #endif } else
static void call_lookup_hash(void *args) { struct lookup_hash_args *a = args; *a->errp = __lookup_hash(a->name, a->base, a->nd); }