static int sdcardfskk_hash_ci(const struct dentry *dentry, const struct inode *inode, struct qstr *qstr) { /* * This function is copy of vfat_hashi. * FIXME Should we support national language? * Refer to vfat_hashi() * struct nls_table *t = MSDOS_SB(dentry->d_sb)->nls_io; */ const unsigned char *name; unsigned int len; unsigned long hash; name = qstr->name; //len = vfat_striptail_len(qstr); len = qstr->len; hash = init_name_hash(); while (len--) //hash = partial_name_hash(nls_tolower(t, *name++), hash); hash = partial_name_hash(tolower(*name++), hash); qstr->hash = end_name_hash(hash); return 0; }
static int adfs_hash(struct dentry *parent, struct qstr *qstr) { const unsigned int name_len = parent->d_sb->u.adfs_sb.s_namelen; const unsigned char *name; unsigned long hash; int i; if (qstr->len < name_len) return 0; /* * Truncate the name in place, avoids * having to define a compare function. */ qstr->len = i = name_len; name = qstr->name; hash = init_name_hash(); while (i--) { char c; c = *name++; if (c >= 'A' && c <= 'Z') c += 'a' - 'A'; hash = partial_name_hash(c, hash); } qstr->hash = end_name_hash(hash); return 0; }
static int cifs_ci_hash(struct dentry *dentry, struct qstr *q) { struct nls_table *codepage = CIFS_SB(dentry->d_inode->i_sb)->local_nls; unsigned long hash; int i; hash = init_name_hash(); for (i = 0; i < q->len; i++) hash = partial_name_hash(nls_tolower(codepage, q->name[i]), hash); q->hash = end_name_hash(hash); return 0; }
/*! 2016-06-04 study -ing */ static unsigned int kernfs_name_hash(const char *name, const void *ns) { unsigned long hash = init_name_hash(); unsigned int len = strlen(name); while (len--) hash = partial_name_hash(*name++, hash); hash = (end_name_hash(hash) ^ hash_ptr((void *)ns, 31)); hash &= 0x7fffffffU; /* Reserve hash numbers 0, 1 and INT_MAX for magic directory entries */ if (hash < 2) hash += 2; if (hash >= INT_MAX) hash = INT_MAX - 1; return hash; }
/* based on vfat_hashi() in fs/fat/namei_vfat.c (no code pages) */ static int esdfs_d_hash(const struct dentry *dentry, const struct inode *inode, struct qstr *qstr) { const unsigned char *name; unsigned int len; unsigned long hash; name = qstr->name; len = vfat_striptail_len(qstr); hash = init_name_hash(); while (len--) hash = partial_name_hash(tolower(*name++), hash); qstr->hash = end_name_hash(hash); return 0; }
/* * Hash a string to an integer as appropriate for the HFS+ filesystem. * Composed unicode characters are decomposed and case-folding is performed * if the appropriate bits are (un)set on the superblock. */ int hfsplus_hash_dentry(const struct dentry *dentry, struct qstr *str) { struct super_block *sb = dentry->d_sb; const char *astr; const u16 *dstr; int casefold, decompose, size, len; unsigned long hash; wchar_t c; u16 c2; casefold = test_bit(HFSPLUS_SB_CASEFOLD, &HFSPLUS_SB(sb)->flags); decompose = !test_bit(HFSPLUS_SB_NODECOMPOSE, &HFSPLUS_SB(sb)->flags); hash = init_name_hash(dentry); astr = str->name; len = str->len; while (len > 0) { int uninitialized_var(dsize); size = asc2unichar(sb, astr, len, &c); astr += size; len -= size; if (decompose) dstr = decompose_unichar(c, &dsize); else dstr = NULL; if (dstr) { do { c2 = *dstr++; if (casefold) c2 = case_fold(c2); if (!casefold || c2) hash = partial_name_hash(c2, hash); } while (--dsize > 0); } else { c2 = c; if (casefold) c2 = case_fold(c2); if (!casefold || c2) hash = partial_name_hash(c2, hash); } } str->hash = end_name_hash(hash); return 0; }
static int minix_hash(struct dentry *dentry, struct qstr *qstr) { unsigned long hash; int i; const unsigned char *name; i = minix_sb(dentry->d_inode->i_sb)->s_namelen; if (i >= qstr->len) return 0; /* Truncate the name in place, avoids having to define a compare function. */ qstr->len = i; name = qstr->name; hash = init_name_hash(); while (i--) hash = partial_name_hash(*name++, hash); qstr->hash = end_name_hash(hash); return 0; }
/* * Note: the dentry argument is the parent dentry. */ static inline int __affs_hash_dentry(struct dentry *dentry, struct qstr *qstr, toupper_t toupper) { const u8 *name = qstr->name; unsigned long hash; int i; i = affs_check_name(qstr->name,qstr->len); if (i) return i; hash = init_name_hash(); i = min(qstr->len, 30u); for (; i > 0; name++, i--) hash = partial_name_hash(toupper(*name), hash); qstr->hash = end_name_hash(hash); return 0; }
static int cifs_ci_hash(const struct dentry *dentry, struct qstr *q) { struct nls_table *codepage = CIFS_SB(dentry->d_sb)->local_nls; unsigned long hash; wchar_t c; int i, charlen; hash = init_name_hash(); for (i = 0; i < q->len; i += charlen) { charlen = codepage->char2uni(&q->name[i], q->len - i, &c); /* error out if we can't convert the character */ if (unlikely(charlen < 0)) return charlen; hash = partial_name_hash(cifs_toupper(c), hash); } q->hash = end_name_hash(hash); return 0; }
static int efivarfs_d_hash(const struct dentry *dentry, struct qstr *qstr) { unsigned long hash = init_name_hash(); const unsigned char *s = qstr->name; unsigned int len = qstr->len; if (!efivarfs_valid_name(s, len)) return -EINVAL; while (len-- > EFI_VARIABLE_GUID_LEN) hash = partial_name_hash(*s++, hash); /* GUID is case-insensitive. */ while (len--) hash = partial_name_hash(tolower(*s++), hash); qstr->hash = end_name_hash(hash); return 0; }
/* * Note: the dentry argument is the parent dentry. */ static inline int __affs_hash_dentry(struct qstr *qstr, toupper_t toupper, bool notruncate) { const u8 *name = qstr->name; unsigned long hash; int retval; u32 len; retval = affs_check_name(qstr->name, qstr->len, notruncate); if (retval) return retval; hash = init_name_hash(); len = min(qstr->len, AFFSNAMEMAX); for (; len > 0; name++, len--) hash = partial_name_hash(toupper(*name), hash); qstr->hash = end_name_hash(hash); return 0; }
/* * Note: the dentry argument is the parent dentry. */ static int affs_hash_dentry(struct dentry *dentry, struct qstr *qstr) { unsigned int (*toupper)(unsigned int) = affs_toupper; unsigned long hash; int i; if ((i = affs_check_name(qstr->name,qstr->len))) return i; /* Check whether to use the international 'toupper' routine */ if (AFFS_I2FSTYPE(dentry->d_inode)) toupper = affs_intl_toupper; hash = init_name_hash(); for (i = 0; i < qstr->len && i < 30; i++) hash = partial_name_hash(toupper(qstr->name[i]), hash); qstr->hash = end_name_hash(hash); return 0; }
static int hpfs_hash_dentry(struct dentry *dentry, struct qstr *qstr) { unsigned long hash; int i; unsigned l = qstr->len; if (l == 1) if (qstr->name[0]=='.') goto x; if (l == 2) if (qstr->name[0]=='.' || qstr->name[1]=='.') goto x; hpfs_adjust_length((char *)qstr->name, &l); /*if (hpfs_chk_name((char *)qstr->name,&l))*/ /*return -ENAMETOOLONG;*/ /*return -ENOENT;*/ x: hash = init_name_hash(); for (i = 0; i < l; i++) hash = partial_name_hash(hpfs_upcase(hpfs_sb(dentry->d_sb)->sb_cp_table,qstr->name[i]), hash); qstr->hash = end_name_hash(hash); return 0; }
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 int ncp_hash_dentry(const struct dentry *dentry, const struct inode *inode, struct qstr *this) { if (!ncp_case_sensitive(inode)) { struct super_block *sb = dentry->d_sb; struct nls_table *t; unsigned long hash; int i; t = NCP_IO_TABLE(sb); hash = init_name_hash(); for (i=0; i<this->len ; i++) hash = partial_name_hash(ncp_tolower(t, this->name[i]), hash); this->hash = end_name_hash(hash); } return 0; } static int ncp_compare_dentry(const struct dentry *parent, const struct inode *pinode, const struct dentry *dentry, const struct inode *inode, unsigned int len, const char *str, const struct qstr *name) { if (len != name->len) return 1;
.read = generic_read_dir, .iterate = jfs_readdir, .fsync = jfs_fsync, .unlocked_ioctl = jfs_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = jfs_compat_ioctl, #endif .llseek = generic_file_llseek, }; static int jfs_ci_hash(const struct dentry *dir, struct qstr *this) { unsigned long hash; int i; hash = init_name_hash(dir); for (i=0; i < this->len; i++) hash = partial_name_hash(tolower(this->name[i]), hash); this->hash = end_name_hash(hash); return 0; } static int jfs_ci_compare(const struct dentry *dentry, unsigned int len, const char *str, const struct qstr *name) { int i, result = 1; if (len != name->len) goto out; for (i=0; i < len; i++) {
/* * Name resolution. * This is the basic name resolution function, turning a pathname into * the final dentry. We expect 'base' to be positive and a directory. * * Returns 0 and nd will have valid dentry and mnt on success. * Returns error and drops reference to input namei data on failure. */ static int link_path_walk(const char *name, struct nameidata *nd) { struct path next; int err; unsigned int lookup_flags = nd->flags; while (*name=='/') name++; if (!*name) goto return_reval; if (nd->depth) lookup_flags = LOOKUP_FOLLOW | (nd->flags & LOOKUP_CONTINUE); /* At this point we know we have a real path component. */ for(;;) { struct inode *inode; unsigned long hash; struct qstr this; unsigned int c; nd->flags |= LOOKUP_CONTINUE; this.name = name; c = *(const unsigned char *)name; hash = init_name_hash(); do { name++; hash = partial_name_hash(c, hash); c = *(const unsigned char *)name; } while (c && (c != '/')); this.len = name - (const char *) this.name; this.hash = end_name_hash(hash); /* remove trailing slashes? */ if (!c) goto last_component; while (*++name == '/'); if (!*name) goto last_with_slashes; /* This does the actual lookups.. */ err = do_lookup(nd, &this, &next, &inode); if (err) break; err = -1; if (!inode) goto out_dput; if (inode->i_op->follow_link){ err = do_follow_link(inode, &next, nd); } last_with_slashes: last_component: return_reval: out_dput: } }
struct dentry *vfsub_lookup_hash(struct nameidata *nd) { struct path path = { .mnt = nd->path.mnt }; IMustLock(nd->path.dentry->d_inode); path.dentry = lookup_hash(nd); if (IS_ERR(path.dentry)) goto out; if (path.dentry->d_inode) vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/ out: AuTraceErrPtr(path.dentry); return path.dentry; } /* * this is "VFS:__lookup_one_len()" which was removed and merged into * VFS:lookup_one_len() by the commit. * 6a96ba5 2011-03-14 kill __lookup_one_len() * this function should always be equivalent to the corresponding part in * VFS:lookup_one_len(). */ int vfsub_name_hash(const char *name, struct qstr *this, int len) { unsigned long hash; unsigned int c; this->name = name; this->len = len; if (!len) return -EACCES; hash = init_name_hash(); while (len--) { c = *(const unsigned char *)name++; if (c == '/' || c == '\0') return -EACCES; hash = partial_name_hash(c, hash); } this->hash = end_name_hash(hash); return 0; } /* ---------------------------------------------------------------------- */ struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1, struct dentry *d2, struct au_hinode *hdir2) { struct dentry *d; lockdep_off(); d = lock_rename(d1, d2); lockdep_on(); au_hn_suspend(hdir1); if (hdir1 != hdir2) au_hn_suspend(hdir2); return d; } void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1, struct dentry *d2, struct au_hinode *hdir2) { au_hn_resume(hdir1); if (hdir1 != hdir2) au_hn_resume(hdir2); lockdep_off(); unlock_rename(d1, d2); lockdep_on(); }