mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-17 02:15:57 +00:00
Don't pass inode to ->d_hash() and ->d_compare()
Instances either don't look at it at all (the majority of cases) or only want it to find the superblock (which can be had as dentry->d_sb). A few cases that want more are actually safe with dentry->d_inode - the only precaution needed is the check that it hadn't been replaced with NULL by rmdir() or by overwriting rename(), which case should be simply treated as cache miss. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
642b704cd7
commit
da53be12bb
@ -11,10 +11,8 @@ be able to use diff(1).
|
|||||||
prototypes:
|
prototypes:
|
||||||
int (*d_revalidate)(struct dentry *, unsigned int);
|
int (*d_revalidate)(struct dentry *, unsigned int);
|
||||||
int (*d_weak_revalidate)(struct dentry *, unsigned int);
|
int (*d_weak_revalidate)(struct dentry *, unsigned int);
|
||||||
int (*d_hash)(const struct dentry *, const struct inode *,
|
int (*d_hash)(const struct dentry *, struct qstr *);
|
||||||
struct qstr *);
|
int (*d_compare)(const struct dentry *, const struct dentry *,
|
||||||
int (*d_compare)(const struct dentry *, const struct inode *,
|
|
||||||
const struct dentry *, const struct inode *,
|
|
||||||
unsigned int, const char *, const struct qstr *);
|
unsigned int, const char *, const struct qstr *);
|
||||||
int (*d_delete)(struct dentry *);
|
int (*d_delete)(struct dentry *);
|
||||||
void (*d_release)(struct dentry *);
|
void (*d_release)(struct dentry *);
|
||||||
|
@ -901,10 +901,8 @@ defined:
|
|||||||
struct dentry_operations {
|
struct dentry_operations {
|
||||||
int (*d_revalidate)(struct dentry *, unsigned int);
|
int (*d_revalidate)(struct dentry *, unsigned int);
|
||||||
int (*d_weak_revalidate)(struct dentry *, unsigned int);
|
int (*d_weak_revalidate)(struct dentry *, unsigned int);
|
||||||
int (*d_hash)(const struct dentry *, const struct inode *,
|
int (*d_hash)(const struct dentry *, struct qstr *);
|
||||||
struct qstr *);
|
int (*d_compare)(const struct dentry *, const struct dentry *,
|
||||||
int (*d_compare)(const struct dentry *, const struct inode *,
|
|
||||||
const struct dentry *, const struct inode *,
|
|
||||||
unsigned int, const char *, const struct qstr *);
|
unsigned int, const char *, const struct qstr *);
|
||||||
int (*d_delete)(const struct dentry *);
|
int (*d_delete)(const struct dentry *);
|
||||||
void (*d_release)(struct dentry *);
|
void (*d_release)(struct dentry *);
|
||||||
@ -949,25 +947,24 @@ struct dentry_operations {
|
|||||||
|
|
||||||
d_hash: called when the VFS adds a dentry to the hash table. The first
|
d_hash: called when the VFS adds a dentry to the hash table. The first
|
||||||
dentry passed to d_hash is the parent directory that the name is
|
dentry passed to d_hash is the parent directory that the name is
|
||||||
to be hashed into. The inode is the dentry's inode.
|
to be hashed into.
|
||||||
|
|
||||||
Same locking and synchronisation rules as d_compare regarding
|
Same locking and synchronisation rules as d_compare regarding
|
||||||
what is safe to dereference etc.
|
what is safe to dereference etc.
|
||||||
|
|
||||||
d_compare: called to compare a dentry name with a given name. The first
|
d_compare: called to compare a dentry name with a given name. The first
|
||||||
dentry is the parent of the dentry to be compared, the second is
|
dentry is the parent of the dentry to be compared, the second is
|
||||||
the parent's inode, then the dentry and inode (may be NULL) of the
|
the child dentry. len and name string are properties of the dentry
|
||||||
child dentry. len and name string are properties of the dentry to be
|
to be compared. qstr is the name to compare it with.
|
||||||
compared. qstr is the name to compare it with.
|
|
||||||
|
|
||||||
Must be constant and idempotent, and should not take locks if
|
Must be constant and idempotent, and should not take locks if
|
||||||
possible, and should not or store into the dentry or inodes.
|
possible, and should not or store into the dentry.
|
||||||
Should not dereference pointers outside the dentry or inodes without
|
Should not dereference pointers outside the dentry without
|
||||||
lots of care (eg. d_parent, d_inode, d_name should not be used).
|
lots of care (eg. d_parent, d_inode, d_name should not be used).
|
||||||
|
|
||||||
However, our vfsmount is pinned, and RCU held, so the dentries and
|
However, our vfsmount is pinned, and RCU held, so the dentries and
|
||||||
inodes won't disappear, neither will our sb or filesystem module.
|
inodes won't disappear, neither will our sb or filesystem module.
|
||||||
->i_sb and ->d_sb may be used.
|
->d_sb may be used.
|
||||||
|
|
||||||
It is a tricky calling convention because it needs to be called under
|
It is a tricky calling convention because it needs to be called under
|
||||||
"rcu-walk", ie. without any locks or references on things.
|
"rcu-walk", ie. without any locks or references on things.
|
||||||
|
@ -191,8 +191,7 @@ const struct file_operations adfs_dir_operations = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
adfs_hash(const struct dentry *parent, const struct inode *inode,
|
adfs_hash(const struct dentry *parent, struct qstr *qstr)
|
||||||
struct qstr *qstr)
|
|
||||||
{
|
{
|
||||||
const unsigned int name_len = ADFS_SB(parent->d_sb)->s_namelen;
|
const unsigned int name_len = ADFS_SB(parent->d_sb)->s_namelen;
|
||||||
const unsigned char *name;
|
const unsigned char *name;
|
||||||
@ -228,8 +227,7 @@ adfs_hash(const struct dentry *parent, const struct inode *inode,
|
|||||||
* requirements of the underlying filesystem.
|
* requirements of the underlying filesystem.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
adfs_compare(const struct dentry *parent, const struct inode *pinode,
|
adfs_compare(const struct dentry *parent, const struct dentry *dentry,
|
||||||
const struct dentry *dentry, const struct inode *inode,
|
|
||||||
unsigned int len, const char *str, const struct qstr *name)
|
unsigned int len, const char *str, const struct qstr *name)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -13,18 +13,12 @@
|
|||||||
typedef int (*toupper_t)(int);
|
typedef int (*toupper_t)(int);
|
||||||
|
|
||||||
static int affs_toupper(int ch);
|
static int affs_toupper(int ch);
|
||||||
static int affs_hash_dentry(const struct dentry *,
|
static int affs_hash_dentry(const struct dentry *, struct qstr *);
|
||||||
const struct inode *, struct qstr *);
|
static int affs_compare_dentry(const struct dentry *parent, const struct dentry *dentry,
|
||||||
static int affs_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);
|
unsigned int len, const char *str, const struct qstr *name);
|
||||||
static int affs_intl_toupper(int ch);
|
static int affs_intl_toupper(int ch);
|
||||||
static int affs_intl_hash_dentry(const struct dentry *,
|
static int affs_intl_hash_dentry(const struct dentry *, struct qstr *);
|
||||||
const struct inode *, struct qstr *);
|
static int affs_intl_compare_dentry(const struct dentry *parent, const struct dentry *dentry,
|
||||||
static int affs_intl_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);
|
unsigned int len, const char *str, const struct qstr *name);
|
||||||
|
|
||||||
const struct dentry_operations affs_dentry_operations = {
|
const struct dentry_operations affs_dentry_operations = {
|
||||||
@ -86,14 +80,12 @@ __affs_hash_dentry(struct qstr *qstr, toupper_t toupper)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
affs_hash_dentry(const struct dentry *dentry, const struct inode *inode,
|
affs_hash_dentry(const struct dentry *dentry, struct qstr *qstr)
|
||||||
struct qstr *qstr)
|
|
||||||
{
|
{
|
||||||
return __affs_hash_dentry(qstr, affs_toupper);
|
return __affs_hash_dentry(qstr, affs_toupper);
|
||||||
}
|
}
|
||||||
static int
|
static int
|
||||||
affs_intl_hash_dentry(const struct dentry *dentry, const struct inode *inode,
|
affs_intl_hash_dentry(const struct dentry *dentry, struct qstr *qstr)
|
||||||
struct qstr *qstr)
|
|
||||||
{
|
{
|
||||||
return __affs_hash_dentry(qstr, affs_intl_toupper);
|
return __affs_hash_dentry(qstr, affs_intl_toupper);
|
||||||
}
|
}
|
||||||
@ -131,15 +123,13 @@ static inline int __affs_compare_dentry(unsigned int len,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
affs_compare_dentry(const struct dentry *parent, const struct inode *pinode,
|
affs_compare_dentry(const struct dentry *parent, const struct dentry *dentry,
|
||||||
const struct dentry *dentry, const struct inode *inode,
|
|
||||||
unsigned int len, const char *str, const struct qstr *name)
|
unsigned int len, const char *str, const struct qstr *name)
|
||||||
{
|
{
|
||||||
return __affs_compare_dentry(len, str, name, affs_toupper);
|
return __affs_compare_dentry(len, str, name, affs_toupper);
|
||||||
}
|
}
|
||||||
static int
|
static int
|
||||||
affs_intl_compare_dentry(const struct dentry *parent,const struct inode *pinode,
|
affs_intl_compare_dentry(const struct dentry *parent, const struct dentry *dentry,
|
||||||
const struct dentry *dentry, const struct inode *inode,
|
|
||||||
unsigned int len, const char *str, const struct qstr *name)
|
unsigned int len, const char *str, const struct qstr *name)
|
||||||
{
|
{
|
||||||
return __affs_compare_dentry(len, str, name, affs_intl_toupper);
|
return __affs_compare_dentry(len, str, name, affs_intl_toupper);
|
||||||
|
@ -822,8 +822,7 @@ const struct dentry_operations cifs_dentry_ops = {
|
|||||||
/* d_delete: cifs_d_delete, */ /* not needed except for debugging */
|
/* d_delete: cifs_d_delete, */ /* not needed except for debugging */
|
||||||
};
|
};
|
||||||
|
|
||||||
static int cifs_ci_hash(const struct dentry *dentry, const struct inode *inode,
|
static int cifs_ci_hash(const struct dentry *dentry, struct qstr *q)
|
||||||
struct qstr *q)
|
|
||||||
{
|
{
|
||||||
struct nls_table *codepage = CIFS_SB(dentry->d_sb)->local_nls;
|
struct nls_table *codepage = CIFS_SB(dentry->d_sb)->local_nls;
|
||||||
unsigned long hash;
|
unsigned long hash;
|
||||||
@ -838,12 +837,10 @@ static int cifs_ci_hash(const struct dentry *dentry, const struct inode *inode,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cifs_ci_compare(const struct dentry *parent,
|
static int cifs_ci_compare(const struct dentry *parent, const struct dentry *dentry,
|
||||||
const struct inode *pinode,
|
|
||||||
const struct dentry *dentry, const struct inode *inode,
|
|
||||||
unsigned int len, const char *str, const struct qstr *name)
|
unsigned int len, const char *str, const struct qstr *name)
|
||||||
{
|
{
|
||||||
struct nls_table *codepage = CIFS_SB(pinode->i_sb)->local_nls;
|
struct nls_table *codepage = CIFS_SB(parent->d_sb)->local_nls;
|
||||||
|
|
||||||
if ((name->len == len) &&
|
if ((name->len == len) &&
|
||||||
(nls_strnicmp(codepage, name->name, str, len) == 0))
|
(nls_strnicmp(codepage, name->name, str, len) == 0))
|
||||||
|
27
fs/dcache.c
27
fs/dcache.c
@ -1723,7 +1723,7 @@ EXPORT_SYMBOL(d_add_ci);
|
|||||||
* Do the slow-case of the dentry name compare.
|
* Do the slow-case of the dentry name compare.
|
||||||
*
|
*
|
||||||
* Unlike the dentry_cmp() function, we need to atomically
|
* Unlike the dentry_cmp() function, we need to atomically
|
||||||
* load the name, length and inode information, so that the
|
* load the name and length information, so that the
|
||||||
* filesystem can rely on them, and can use the 'name' and
|
* filesystem can rely on them, and can use the 'name' and
|
||||||
* 'len' information without worrying about walking off the
|
* 'len' information without worrying about walking off the
|
||||||
* end of memory etc.
|
* end of memory etc.
|
||||||
@ -1741,22 +1741,18 @@ enum slow_d_compare {
|
|||||||
|
|
||||||
static noinline enum slow_d_compare slow_dentry_cmp(
|
static noinline enum slow_d_compare slow_dentry_cmp(
|
||||||
const struct dentry *parent,
|
const struct dentry *parent,
|
||||||
struct inode *inode,
|
|
||||||
struct dentry *dentry,
|
struct dentry *dentry,
|
||||||
unsigned int seq,
|
unsigned int seq,
|
||||||
const struct qstr *name)
|
const struct qstr *name)
|
||||||
{
|
{
|
||||||
int tlen = dentry->d_name.len;
|
int tlen = dentry->d_name.len;
|
||||||
const char *tname = dentry->d_name.name;
|
const char *tname = dentry->d_name.name;
|
||||||
struct inode *i = dentry->d_inode;
|
|
||||||
|
|
||||||
if (read_seqcount_retry(&dentry->d_seq, seq)) {
|
if (read_seqcount_retry(&dentry->d_seq, seq)) {
|
||||||
cpu_relax();
|
cpu_relax();
|
||||||
return D_COMP_SEQRETRY;
|
return D_COMP_SEQRETRY;
|
||||||
}
|
}
|
||||||
if (parent->d_op->d_compare(parent, inode,
|
if (parent->d_op->d_compare(parent, dentry, tlen, tname, name))
|
||||||
dentry, i,
|
|
||||||
tlen, tname, name))
|
|
||||||
return D_COMP_NOMATCH;
|
return D_COMP_NOMATCH;
|
||||||
return D_COMP_OK;
|
return D_COMP_OK;
|
||||||
}
|
}
|
||||||
@ -1766,7 +1762,6 @@ static noinline enum slow_d_compare slow_dentry_cmp(
|
|||||||
* @parent: parent dentry
|
* @parent: parent dentry
|
||||||
* @name: qstr of name we wish to find
|
* @name: qstr of name we wish to find
|
||||||
* @seqp: returns d_seq value at the point where the dentry was found
|
* @seqp: returns d_seq value at the point where the dentry was found
|
||||||
* @inode: returns dentry->d_inode when the inode was found valid.
|
|
||||||
* Returns: dentry, or NULL
|
* Returns: dentry, or NULL
|
||||||
*
|
*
|
||||||
* __d_lookup_rcu is the dcache lookup function for rcu-walk name
|
* __d_lookup_rcu is the dcache lookup function for rcu-walk name
|
||||||
@ -1793,7 +1788,7 @@ static noinline enum slow_d_compare slow_dentry_cmp(
|
|||||||
*/
|
*/
|
||||||
struct dentry *__d_lookup_rcu(const struct dentry *parent,
|
struct dentry *__d_lookup_rcu(const struct dentry *parent,
|
||||||
const struct qstr *name,
|
const struct qstr *name,
|
||||||
unsigned *seqp, struct inode *inode)
|
unsigned *seqp)
|
||||||
{
|
{
|
||||||
u64 hashlen = name->hash_len;
|
u64 hashlen = name->hash_len;
|
||||||
const unsigned char *str = name->name;
|
const unsigned char *str = name->name;
|
||||||
@ -1827,11 +1822,10 @@ struct dentry *__d_lookup_rcu(const struct dentry *parent,
|
|||||||
seqretry:
|
seqretry:
|
||||||
/*
|
/*
|
||||||
* The dentry sequence count protects us from concurrent
|
* The dentry sequence count protects us from concurrent
|
||||||
* renames, and thus protects inode, parent and name fields.
|
* renames, and thus protects parent and name fields.
|
||||||
*
|
*
|
||||||
* The caller must perform a seqcount check in order
|
* The caller must perform a seqcount check in order
|
||||||
* to do anything useful with the returned dentry,
|
* to do anything useful with the returned dentry.
|
||||||
* including using the 'd_inode' pointer.
|
|
||||||
*
|
*
|
||||||
* NOTE! We do a "raw" seqcount_begin here. That means that
|
* NOTE! We do a "raw" seqcount_begin here. That means that
|
||||||
* we don't wait for the sequence count to stabilize if it
|
* we don't wait for the sequence count to stabilize if it
|
||||||
@ -1845,12 +1839,12 @@ seqretry:
|
|||||||
continue;
|
continue;
|
||||||
if (d_unhashed(dentry))
|
if (d_unhashed(dentry))
|
||||||
continue;
|
continue;
|
||||||
*seqp = seq;
|
|
||||||
|
|
||||||
if (unlikely(parent->d_flags & DCACHE_OP_COMPARE)) {
|
if (unlikely(parent->d_flags & DCACHE_OP_COMPARE)) {
|
||||||
if (dentry->d_name.hash != hashlen_hash(hashlen))
|
if (dentry->d_name.hash != hashlen_hash(hashlen))
|
||||||
continue;
|
continue;
|
||||||
switch (slow_dentry_cmp(parent, inode, dentry, seq, name)) {
|
*seqp = seq;
|
||||||
|
switch (slow_dentry_cmp(parent, dentry, seq, name)) {
|
||||||
case D_COMP_OK:
|
case D_COMP_OK:
|
||||||
return dentry;
|
return dentry;
|
||||||
case D_COMP_NOMATCH:
|
case D_COMP_NOMATCH:
|
||||||
@ -1862,6 +1856,7 @@ seqretry:
|
|||||||
|
|
||||||
if (dentry->d_name.hash_len != hashlen)
|
if (dentry->d_name.hash_len != hashlen)
|
||||||
continue;
|
continue;
|
||||||
|
*seqp = seq;
|
||||||
if (!dentry_cmp(dentry, str, hashlen_len(hashlen)))
|
if (!dentry_cmp(dentry, str, hashlen_len(hashlen)))
|
||||||
return dentry;
|
return dentry;
|
||||||
}
|
}
|
||||||
@ -1959,9 +1954,7 @@ struct dentry *__d_lookup(const struct dentry *parent, const struct qstr *name)
|
|||||||
if (parent->d_flags & DCACHE_OP_COMPARE) {
|
if (parent->d_flags & DCACHE_OP_COMPARE) {
|
||||||
int tlen = dentry->d_name.len;
|
int tlen = dentry->d_name.len;
|
||||||
const char *tname = dentry->d_name.name;
|
const char *tname = dentry->d_name.name;
|
||||||
if (parent->d_op->d_compare(parent, parent->d_inode,
|
if (parent->d_op->d_compare(parent, dentry, tlen, tname, name))
|
||||||
dentry, dentry->d_inode,
|
|
||||||
tlen, tname, name))
|
|
||||||
goto next;
|
goto next;
|
||||||
} else {
|
} else {
|
||||||
if (dentry->d_name.len != len)
|
if (dentry->d_name.len != len)
|
||||||
@ -1998,7 +1991,7 @@ struct dentry *d_hash_and_lookup(struct dentry *dir, struct qstr *name)
|
|||||||
*/
|
*/
|
||||||
name->hash = full_name_hash(name->name, name->len);
|
name->hash = full_name_hash(name->name, name->len);
|
||||||
if (dir->d_flags & DCACHE_OP_HASH) {
|
if (dir->d_flags & DCACHE_OP_HASH) {
|
||||||
int err = dir->d_op->d_hash(dir, dir->d_inode, name);
|
int err = dir->d_op->d_hash(dir, name);
|
||||||
if (unlikely(err < 0))
|
if (unlikely(err < 0))
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
}
|
}
|
||||||
|
@ -45,8 +45,8 @@ static struct super_block *efivarfs_sb;
|
|||||||
* So we need to perform a case-sensitive match on part 1 and a
|
* So we need to perform a case-sensitive match on part 1 and a
|
||||||
* case-insensitive match on part 2.
|
* case-insensitive match on part 2.
|
||||||
*/
|
*/
|
||||||
static int efivarfs_d_compare(const struct dentry *parent, const struct inode *pinode,
|
static int efivarfs_d_compare(const struct dentry *parent,
|
||||||
const struct dentry *dentry, const struct inode *inode,
|
const struct dentry *dentry,
|
||||||
unsigned int len, const char *str,
|
unsigned int len, const char *str,
|
||||||
const struct qstr *name)
|
const struct qstr *name)
|
||||||
{
|
{
|
||||||
@ -63,8 +63,7 @@ static int efivarfs_d_compare(const struct dentry *parent, const struct inode *p
|
|||||||
return strncasecmp(name->name + guid, str + guid, EFI_VARIABLE_GUID_LEN);
|
return strncasecmp(name->name + guid, str + guid, EFI_VARIABLE_GUID_LEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int efivarfs_d_hash(const struct dentry *dentry,
|
static int efivarfs_d_hash(const struct dentry *dentry, struct qstr *qstr)
|
||||||
const struct inode *inode, struct qstr *qstr)
|
|
||||||
{
|
{
|
||||||
unsigned long hash = init_name_hash();
|
unsigned long hash = init_name_hash();
|
||||||
const unsigned char *s = qstr->name;
|
const unsigned char *s = qstr->name;
|
||||||
@ -108,7 +107,7 @@ static struct dentry *efivarfs_alloc_dentry(struct dentry *parent, char *name)
|
|||||||
q.name = name;
|
q.name = name;
|
||||||
q.len = strlen(name);
|
q.len = strlen(name);
|
||||||
|
|
||||||
err = efivarfs_d_hash(NULL, NULL, &q);
|
err = efivarfs_d_hash(NULL, &q);
|
||||||
if (err)
|
if (err)
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
|
|
||||||
|
@ -148,8 +148,7 @@ static int msdos_find(struct inode *dir, const unsigned char *name, int len,
|
|||||||
* that the existing dentry can be used. The msdos fs routines will
|
* that the existing dentry can be used. The msdos fs routines will
|
||||||
* return ENOENT or EINVAL as appropriate.
|
* return ENOENT or EINVAL as appropriate.
|
||||||
*/
|
*/
|
||||||
static int msdos_hash(const struct dentry *dentry, const struct inode *inode,
|
static int msdos_hash(const struct dentry *dentry, struct qstr *qstr)
|
||||||
struct qstr *qstr)
|
|
||||||
{
|
{
|
||||||
struct fat_mount_options *options = &MSDOS_SB(dentry->d_sb)->options;
|
struct fat_mount_options *options = &MSDOS_SB(dentry->d_sb)->options;
|
||||||
unsigned char msdos_name[MSDOS_NAME];
|
unsigned char msdos_name[MSDOS_NAME];
|
||||||
@ -165,8 +164,7 @@ static int msdos_hash(const struct dentry *dentry, const struct inode *inode,
|
|||||||
* Compare two msdos names. If either of the names are invalid,
|
* Compare two msdos names. If either of the names are invalid,
|
||||||
* we fall back to doing the standard name comparison.
|
* we fall back to doing the standard name comparison.
|
||||||
*/
|
*/
|
||||||
static int msdos_cmp(const struct dentry *parent, const struct inode *pinode,
|
static int msdos_cmp(const struct dentry *parent, const struct dentry *dentry,
|
||||||
const struct dentry *dentry, const struct inode *inode,
|
|
||||||
unsigned int len, const char *str, const struct qstr *name)
|
unsigned int len, const char *str, const struct qstr *name)
|
||||||
{
|
{
|
||||||
struct fat_mount_options *options = &MSDOS_SB(parent->d_sb)->options;
|
struct fat_mount_options *options = &MSDOS_SB(parent->d_sb)->options;
|
||||||
|
@ -107,8 +107,7 @@ static unsigned int vfat_striptail_len(const struct qstr *qstr)
|
|||||||
* that the existing dentry can be used. The vfat fs routines will
|
* that the existing dentry can be used. The vfat fs routines will
|
||||||
* return ENOENT or EINVAL as appropriate.
|
* return ENOENT or EINVAL as appropriate.
|
||||||
*/
|
*/
|
||||||
static int vfat_hash(const struct dentry *dentry, const struct inode *inode,
|
static int vfat_hash(const struct dentry *dentry, struct qstr *qstr)
|
||||||
struct qstr *qstr)
|
|
||||||
{
|
{
|
||||||
qstr->hash = full_name_hash(qstr->name, vfat_striptail_len(qstr));
|
qstr->hash = full_name_hash(qstr->name, vfat_striptail_len(qstr));
|
||||||
return 0;
|
return 0;
|
||||||
@ -120,8 +119,7 @@ static int vfat_hash(const struct dentry *dentry, const struct inode *inode,
|
|||||||
* that the existing dentry can be used. The vfat fs routines will
|
* that the existing dentry can be used. The vfat fs routines will
|
||||||
* return ENOENT or EINVAL as appropriate.
|
* return ENOENT or EINVAL as appropriate.
|
||||||
*/
|
*/
|
||||||
static int vfat_hashi(const struct dentry *dentry, const struct inode *inode,
|
static int vfat_hashi(const struct dentry *dentry, struct qstr *qstr)
|
||||||
struct qstr *qstr)
|
|
||||||
{
|
{
|
||||||
struct nls_table *t = MSDOS_SB(dentry->d_sb)->nls_io;
|
struct nls_table *t = MSDOS_SB(dentry->d_sb)->nls_io;
|
||||||
const unsigned char *name;
|
const unsigned char *name;
|
||||||
@ -142,8 +140,7 @@ static int vfat_hashi(const struct dentry *dentry, const struct inode *inode,
|
|||||||
/*
|
/*
|
||||||
* Case insensitive compare of two vfat names.
|
* Case insensitive compare of two vfat names.
|
||||||
*/
|
*/
|
||||||
static int vfat_cmpi(const struct dentry *parent, const struct inode *pinode,
|
static int vfat_cmpi(const struct dentry *parent, const struct dentry *dentry,
|
||||||
const struct dentry *dentry, const struct inode *inode,
|
|
||||||
unsigned int len, const char *str, const struct qstr *name)
|
unsigned int len, const char *str, const struct qstr *name)
|
||||||
{
|
{
|
||||||
struct nls_table *t = MSDOS_SB(parent->d_sb)->nls_io;
|
struct nls_table *t = MSDOS_SB(parent->d_sb)->nls_io;
|
||||||
@ -162,8 +159,7 @@ static int vfat_cmpi(const struct dentry *parent, const struct inode *pinode,
|
|||||||
/*
|
/*
|
||||||
* Case sensitive compare of two vfat names.
|
* Case sensitive compare of two vfat names.
|
||||||
*/
|
*/
|
||||||
static int vfat_cmp(const struct dentry *parent, const struct inode *pinode,
|
static int vfat_cmp(const struct dentry *parent, const struct dentry *dentry,
|
||||||
const struct dentry *dentry, const struct inode *inode,
|
|
||||||
unsigned int len, const char *str, const struct qstr *name)
|
unsigned int len, const char *str, const struct qstr *name)
|
||||||
{
|
{
|
||||||
unsigned int alen, blen;
|
unsigned int alen, blen;
|
||||||
|
@ -109,8 +109,7 @@ fail:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int gfs2_dhash(const struct dentry *dentry, const struct inode *inode,
|
static int gfs2_dhash(const struct dentry *dentry, struct qstr *str)
|
||||||
struct qstr *str)
|
|
||||||
{
|
{
|
||||||
str->hash = gfs2_disk_hash(str->name, str->len);
|
str->hash = gfs2_disk_hash(str->name, str->len);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -229,13 +229,10 @@ extern int hfs_part_find(struct super_block *, sector_t *, sector_t *);
|
|||||||
/* string.c */
|
/* string.c */
|
||||||
extern const struct dentry_operations hfs_dentry_operations;
|
extern const struct dentry_operations hfs_dentry_operations;
|
||||||
|
|
||||||
extern int hfs_hash_dentry(const struct dentry *, const struct inode *,
|
extern int hfs_hash_dentry(const struct dentry *, struct qstr *);
|
||||||
struct qstr *);
|
|
||||||
extern int hfs_strcmp(const unsigned char *, unsigned int,
|
extern int hfs_strcmp(const unsigned char *, unsigned int,
|
||||||
const unsigned char *, unsigned int);
|
const unsigned char *, unsigned int);
|
||||||
extern int hfs_compare_dentry(const struct dentry *parent,
|
extern int hfs_compare_dentry(const struct dentry *parent, const struct dentry *dentry,
|
||||||
const struct inode *pinode,
|
|
||||||
const struct dentry *dentry, const struct inode *inode,
|
|
||||||
unsigned int len, const char *str, const struct qstr *name);
|
unsigned int len, const char *str, const struct qstr *name);
|
||||||
|
|
||||||
/* trans.c */
|
/* trans.c */
|
||||||
|
@ -51,8 +51,7 @@ static unsigned char caseorder[256] = {
|
|||||||
/*
|
/*
|
||||||
* Hash a string to an integer in a case-independent way
|
* Hash a string to an integer in a case-independent way
|
||||||
*/
|
*/
|
||||||
int hfs_hash_dentry(const struct dentry *dentry, const struct inode *inode,
|
int hfs_hash_dentry(const struct dentry *dentry, struct qstr *this)
|
||||||
struct qstr *this)
|
|
||||||
{
|
{
|
||||||
const unsigned char *name = this->name;
|
const unsigned char *name = this->name;
|
||||||
unsigned int hash, len = this->len;
|
unsigned int hash, len = this->len;
|
||||||
@ -93,8 +92,7 @@ int hfs_strcmp(const unsigned char *s1, unsigned int len1,
|
|||||||
* Test for equality of two strings in the HFS filename character ordering.
|
* Test for equality of two strings in the HFS filename character ordering.
|
||||||
* return 1 on failure and 0 on success
|
* return 1 on failure and 0 on success
|
||||||
*/
|
*/
|
||||||
int hfs_compare_dentry(const struct dentry *parent, const struct inode *pinode,
|
int hfs_compare_dentry(const struct dentry *parent, const struct dentry *dentry,
|
||||||
const struct dentry *dentry, const struct inode *inode,
|
|
||||||
unsigned int len, const char *str, const struct qstr *name)
|
unsigned int len, const char *str, const struct qstr *name)
|
||||||
{
|
{
|
||||||
const unsigned char *n1, *n2;
|
const unsigned char *n1, *n2;
|
||||||
|
@ -495,11 +495,8 @@ int hfsplus_uni2asc(struct super_block *,
|
|||||||
const struct hfsplus_unistr *, char *, int *);
|
const struct hfsplus_unistr *, char *, int *);
|
||||||
int hfsplus_asc2uni(struct super_block *,
|
int hfsplus_asc2uni(struct super_block *,
|
||||||
struct hfsplus_unistr *, int, const char *, int);
|
struct hfsplus_unistr *, int, const char *, int);
|
||||||
int hfsplus_hash_dentry(const struct dentry *dentry,
|
int hfsplus_hash_dentry(const struct dentry *dentry, struct qstr *str);
|
||||||
const struct inode *inode, struct qstr *str);
|
int hfsplus_compare_dentry(const struct dentry *parent, const struct dentry *dentry,
|
||||||
int hfsplus_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);
|
unsigned int len, const char *str, const struct qstr *name);
|
||||||
|
|
||||||
/* wrapper.c */
|
/* wrapper.c */
|
||||||
|
@ -334,8 +334,7 @@ int hfsplus_asc2uni(struct super_block *sb,
|
|||||||
* Composed unicode characters are decomposed and case-folding is performed
|
* Composed unicode characters are decomposed and case-folding is performed
|
||||||
* if the appropriate bits are (un)set on the superblock.
|
* if the appropriate bits are (un)set on the superblock.
|
||||||
*/
|
*/
|
||||||
int hfsplus_hash_dentry(const struct dentry *dentry, const struct inode *inode,
|
int hfsplus_hash_dentry(const struct dentry *dentry, struct qstr *str)
|
||||||
struct qstr *str)
|
|
||||||
{
|
{
|
||||||
struct super_block *sb = dentry->d_sb;
|
struct super_block *sb = dentry->d_sb;
|
||||||
const char *astr;
|
const char *astr;
|
||||||
@ -386,9 +385,7 @@ int hfsplus_hash_dentry(const struct dentry *dentry, const struct inode *inode,
|
|||||||
* Composed unicode characters are decomposed and case-folding is performed
|
* Composed unicode characters are decomposed and case-folding is performed
|
||||||
* if the appropriate bits are (un)set on the superblock.
|
* if the appropriate bits are (un)set on the superblock.
|
||||||
*/
|
*/
|
||||||
int hfsplus_compare_dentry(const struct dentry *parent,
|
int hfsplus_compare_dentry(const struct dentry *parent, const struct dentry *dentry,
|
||||||
const struct inode *pinode,
|
|
||||||
const struct dentry *dentry, const struct inode *inode,
|
|
||||||
unsigned int len, const char *str, const struct qstr *name)
|
unsigned int len, const char *str, const struct qstr *name)
|
||||||
{
|
{
|
||||||
struct super_block *sb = parent->d_sb;
|
struct super_block *sb = parent->d_sb;
|
||||||
|
@ -12,8 +12,7 @@
|
|||||||
* Note: the dentry argument is the parent dentry.
|
* Note: the dentry argument is the parent dentry.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int hpfs_hash_dentry(const struct dentry *dentry, const struct inode *inode,
|
static int hpfs_hash_dentry(const struct dentry *dentry, struct qstr *qstr)
|
||||||
struct qstr *qstr)
|
|
||||||
{
|
{
|
||||||
unsigned long hash;
|
unsigned long hash;
|
||||||
int i;
|
int i;
|
||||||
@ -35,9 +34,7 @@ static int hpfs_hash_dentry(const struct dentry *dentry, const struct inode *ino
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hpfs_compare_dentry(const struct dentry *parent,
|
static int hpfs_compare_dentry(const struct dentry *parent, const struct dentry *dentry,
|
||||||
const struct inode *pinode,
|
|
||||||
const struct dentry *dentry, const struct inode *inode,
|
|
||||||
unsigned int len, const char *str, const struct qstr *name)
|
unsigned int len, const char *str, const struct qstr *name)
|
||||||
{
|
{
|
||||||
unsigned al = len;
|
unsigned al = len;
|
||||||
|
@ -28,31 +28,23 @@
|
|||||||
|
|
||||||
#define BEQUIET
|
#define BEQUIET
|
||||||
|
|
||||||
static int isofs_hashi(const struct dentry *parent, const struct inode *inode,
|
static int isofs_hashi(const struct dentry *parent, struct qstr *qstr);
|
||||||
struct qstr *qstr);
|
static int isofs_hash(const struct dentry *parent, struct qstr *qstr);
|
||||||
static int isofs_hash(const struct dentry *parent, const struct inode *inode,
|
|
||||||
struct qstr *qstr);
|
|
||||||
static int isofs_dentry_cmpi(const struct dentry *parent,
|
static int isofs_dentry_cmpi(const struct dentry *parent,
|
||||||
const struct inode *pinode,
|
const struct dentry *dentry,
|
||||||
const struct dentry *dentry, const struct inode *inode,
|
|
||||||
unsigned int len, const char *str, const struct qstr *name);
|
unsigned int len, const char *str, const struct qstr *name);
|
||||||
static int isofs_dentry_cmp(const struct dentry *parent,
|
static int isofs_dentry_cmp(const struct dentry *parent,
|
||||||
const struct inode *pinode,
|
const struct dentry *dentry,
|
||||||
const struct dentry *dentry, const struct inode *inode,
|
|
||||||
unsigned int len, const char *str, const struct qstr *name);
|
unsigned int len, const char *str, const struct qstr *name);
|
||||||
|
|
||||||
#ifdef CONFIG_JOLIET
|
#ifdef CONFIG_JOLIET
|
||||||
static int isofs_hashi_ms(const struct dentry *parent, const struct inode *inode,
|
static int isofs_hashi_ms(const struct dentry *parent, struct qstr *qstr);
|
||||||
struct qstr *qstr);
|
static int isofs_hash_ms(const struct dentry *parent, struct qstr *qstr);
|
||||||
static int isofs_hash_ms(const struct dentry *parent, const struct inode *inode,
|
|
||||||
struct qstr *qstr);
|
|
||||||
static int isofs_dentry_cmpi_ms(const struct dentry *parent,
|
static int isofs_dentry_cmpi_ms(const struct dentry *parent,
|
||||||
const struct inode *pinode,
|
const struct dentry *dentry,
|
||||||
const struct dentry *dentry, const struct inode *inode,
|
|
||||||
unsigned int len, const char *str, const struct qstr *name);
|
unsigned int len, const char *str, const struct qstr *name);
|
||||||
static int isofs_dentry_cmp_ms(const struct dentry *parent,
|
static int isofs_dentry_cmp_ms(const struct dentry *parent,
|
||||||
const struct inode *pinode,
|
const struct dentry *dentry,
|
||||||
const struct dentry *dentry, const struct inode *inode,
|
|
||||||
unsigned int len, const char *str, const struct qstr *name);
|
unsigned int len, const char *str, const struct qstr *name);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -265,30 +257,26 @@ static int isofs_dentry_cmp_common(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
isofs_hash(const struct dentry *dentry, const struct inode *inode,
|
isofs_hash(const struct dentry *dentry, struct qstr *qstr)
|
||||||
struct qstr *qstr)
|
|
||||||
{
|
{
|
||||||
return isofs_hash_common(dentry, qstr, 0);
|
return isofs_hash_common(dentry, qstr, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
isofs_hashi(const struct dentry *dentry, const struct inode *inode,
|
isofs_hashi(const struct dentry *dentry, struct qstr *qstr)
|
||||||
struct qstr *qstr)
|
|
||||||
{
|
{
|
||||||
return isofs_hashi_common(dentry, qstr, 0);
|
return isofs_hashi_common(dentry, qstr, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
isofs_dentry_cmp(const struct dentry *parent, const struct inode *pinode,
|
isofs_dentry_cmp(const struct dentry *parent, const struct dentry *dentry,
|
||||||
const struct dentry *dentry, const struct inode *inode,
|
|
||||||
unsigned int len, const char *str, const struct qstr *name)
|
unsigned int len, const char *str, const struct qstr *name)
|
||||||
{
|
{
|
||||||
return isofs_dentry_cmp_common(len, str, name, 0, 0);
|
return isofs_dentry_cmp_common(len, str, name, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
isofs_dentry_cmpi(const struct dentry *parent, const struct inode *pinode,
|
isofs_dentry_cmpi(const struct dentry *parent, const struct dentry *dentry,
|
||||||
const struct dentry *dentry, const struct inode *inode,
|
|
||||||
unsigned int len, const char *str, const struct qstr *name)
|
unsigned int len, const char *str, const struct qstr *name)
|
||||||
{
|
{
|
||||||
return isofs_dentry_cmp_common(len, str, name, 0, 1);
|
return isofs_dentry_cmp_common(len, str, name, 0, 1);
|
||||||
@ -296,30 +284,26 @@ isofs_dentry_cmpi(const struct dentry *parent, const struct inode *pinode,
|
|||||||
|
|
||||||
#ifdef CONFIG_JOLIET
|
#ifdef CONFIG_JOLIET
|
||||||
static int
|
static int
|
||||||
isofs_hash_ms(const struct dentry *dentry, const struct inode *inode,
|
isofs_hash_ms(const struct dentry *dentry, struct qstr *qstr)
|
||||||
struct qstr *qstr)
|
|
||||||
{
|
{
|
||||||
return isofs_hash_common(dentry, qstr, 1);
|
return isofs_hash_common(dentry, qstr, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
isofs_hashi_ms(const struct dentry *dentry, const struct inode *inode,
|
isofs_hashi_ms(const struct dentry *dentry, struct qstr *qstr)
|
||||||
struct qstr *qstr)
|
|
||||||
{
|
{
|
||||||
return isofs_hashi_common(dentry, qstr, 1);
|
return isofs_hashi_common(dentry, qstr, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
isofs_dentry_cmp_ms(const struct dentry *parent, const struct inode *pinode,
|
isofs_dentry_cmp_ms(const struct dentry *parent, const struct dentry *dentry,
|
||||||
const struct dentry *dentry, const struct inode *inode,
|
|
||||||
unsigned int len, const char *str, const struct qstr *name)
|
unsigned int len, const char *str, const struct qstr *name)
|
||||||
{
|
{
|
||||||
return isofs_dentry_cmp_common(len, str, name, 1, 0);
|
return isofs_dentry_cmp_common(len, str, name, 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
isofs_dentry_cmpi_ms(const struct dentry *parent, const struct inode *pinode,
|
isofs_dentry_cmpi_ms(const struct dentry *parent, const struct dentry *dentry,
|
||||||
const struct dentry *dentry, const struct inode *inode,
|
|
||||||
unsigned int len, const char *str, const struct qstr *name)
|
unsigned int len, const char *str, const struct qstr *name)
|
||||||
{
|
{
|
||||||
return isofs_dentry_cmp_common(len, str, name, 1, 1);
|
return isofs_dentry_cmp_common(len, str, name, 1, 1);
|
||||||
|
@ -37,8 +37,7 @@ isofs_cmp(struct dentry *dentry, const char *compare, int dlen)
|
|||||||
|
|
||||||
qstr.name = compare;
|
qstr.name = compare;
|
||||||
qstr.len = dlen;
|
qstr.len = dlen;
|
||||||
return dentry->d_op->d_compare(NULL, NULL, NULL, NULL,
|
return dentry->d_op->d_compare(NULL, NULL, dentry->d_name.len, dentry->d_name.name, &qstr);
|
||||||
dentry->d_name.len, dentry->d_name.name, &qstr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1538,8 +1538,7 @@ const struct file_operations jfs_dir_operations = {
|
|||||||
.llseek = generic_file_llseek,
|
.llseek = generic_file_llseek,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int jfs_ci_hash(const struct dentry *dir, const struct inode *inode,
|
static int jfs_ci_hash(const struct dentry *dir, struct qstr *this)
|
||||||
struct qstr *this)
|
|
||||||
{
|
{
|
||||||
unsigned long hash;
|
unsigned long hash;
|
||||||
int i;
|
int i;
|
||||||
@ -1552,9 +1551,7 @@ static int jfs_ci_hash(const struct dentry *dir, const struct inode *inode,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int jfs_ci_compare(const struct dentry *parent,
|
static int jfs_ci_compare(const struct dentry *parent, const struct dentry *dentry,
|
||||||
const struct inode *pinode,
|
|
||||||
const struct dentry *dentry, const struct inode *inode,
|
|
||||||
unsigned int len, const char *str, const struct qstr *name)
|
unsigned int len, const char *str, const struct qstr *name)
|
||||||
{
|
{
|
||||||
int i, result = 1;
|
int i, result = 1;
|
||||||
|
@ -1352,7 +1352,7 @@ static int lookup_fast(struct nameidata *nd,
|
|||||||
*/
|
*/
|
||||||
if (nd->flags & LOOKUP_RCU) {
|
if (nd->flags & LOOKUP_RCU) {
|
||||||
unsigned seq;
|
unsigned seq;
|
||||||
dentry = __d_lookup_rcu(parent, &nd->last, &seq, nd->inode);
|
dentry = __d_lookup_rcu(parent, &nd->last, &seq);
|
||||||
if (!dentry)
|
if (!dentry)
|
||||||
goto unlazy;
|
goto unlazy;
|
||||||
|
|
||||||
@ -1787,8 +1787,7 @@ static int link_path_walk(const char *name, struct nameidata *nd)
|
|||||||
struct dentry *parent = nd->path.dentry;
|
struct dentry *parent = nd->path.dentry;
|
||||||
nd->flags &= ~LOOKUP_JUMPED;
|
nd->flags &= ~LOOKUP_JUMPED;
|
||||||
if (unlikely(parent->d_flags & DCACHE_OP_HASH)) {
|
if (unlikely(parent->d_flags & DCACHE_OP_HASH)) {
|
||||||
err = parent->d_op->d_hash(parent, nd->inode,
|
err = parent->d_op->d_hash(parent, &this);
|
||||||
&this);
|
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2121,7 +2120,7 @@ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len)
|
|||||||
* to use its own hash..
|
* to use its own hash..
|
||||||
*/
|
*/
|
||||||
if (base->d_flags & DCACHE_OP_HASH) {
|
if (base->d_flags & DCACHE_OP_HASH) {
|
||||||
int err = base->d_op->d_hash(base, base->d_inode, &this);
|
int err = base->d_op->d_hash(base, &this);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
}
|
}
|
||||||
|
@ -73,10 +73,8 @@ const struct inode_operations ncp_dir_inode_operations =
|
|||||||
* Dentry operations routines
|
* Dentry operations routines
|
||||||
*/
|
*/
|
||||||
static int ncp_lookup_validate(struct dentry *, unsigned int);
|
static int ncp_lookup_validate(struct dentry *, unsigned int);
|
||||||
static int ncp_hash_dentry(const struct dentry *, const struct inode *,
|
static int ncp_hash_dentry(const struct dentry *, struct qstr *);
|
||||||
struct qstr *);
|
static int ncp_compare_dentry(const struct dentry *, const struct dentry *,
|
||||||
static int ncp_compare_dentry(const struct dentry *, const struct inode *,
|
|
||||||
const struct dentry *, const struct inode *,
|
|
||||||
unsigned int, const char *, const struct qstr *);
|
unsigned int, const char *, const struct qstr *);
|
||||||
static int ncp_delete_dentry(const struct dentry *);
|
static int ncp_delete_dentry(const struct dentry *);
|
||||||
|
|
||||||
@ -119,11 +117,19 @@ static inline int ncp_case_sensitive(const struct inode *i)
|
|||||||
/*
|
/*
|
||||||
* Note: leave the hash unchanged if the directory
|
* Note: leave the hash unchanged if the directory
|
||||||
* is case-sensitive.
|
* is case-sensitive.
|
||||||
|
*
|
||||||
|
* Accessing the parent inode can be racy under RCU pathwalking.
|
||||||
|
* Use ACCESS_ONCE() to make sure we use _one_ particular inode,
|
||||||
|
* the callers will handle races.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
ncp_hash_dentry(const struct dentry *dentry, const struct inode *inode,
|
ncp_hash_dentry(const struct dentry *dentry, struct qstr *this)
|
||||||
struct qstr *this)
|
|
||||||
{
|
{
|
||||||
|
struct inode *inode = ACCESS_ONCE(dentry->d_inode);
|
||||||
|
|
||||||
|
if (!inode)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (!ncp_case_sensitive(inode)) {
|
if (!ncp_case_sensitive(inode)) {
|
||||||
struct super_block *sb = dentry->d_sb;
|
struct super_block *sb = dentry->d_sb;
|
||||||
struct nls_table *t;
|
struct nls_table *t;
|
||||||
@ -140,14 +146,24 @@ ncp_hash_dentry(const struct dentry *dentry, const struct inode *inode,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Accessing the parent inode can be racy under RCU pathwalking.
|
||||||
|
* Use ACCESS_ONCE() to make sure we use _one_ particular inode,
|
||||||
|
* the callers will handle races.
|
||||||
|
*/
|
||||||
static int
|
static int
|
||||||
ncp_compare_dentry(const struct dentry *parent, const struct inode *pinode,
|
ncp_compare_dentry(const struct dentry *parent, const struct dentry *dentry,
|
||||||
const struct dentry *dentry, const struct inode *inode,
|
|
||||||
unsigned int len, const char *str, const struct qstr *name)
|
unsigned int len, const char *str, const struct qstr *name)
|
||||||
{
|
{
|
||||||
|
struct inode *pinode;
|
||||||
|
|
||||||
if (len != name->len)
|
if (len != name->len)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
pinode = ACCESS_ONCE(parent->d_inode);
|
||||||
|
if (!pinode)
|
||||||
|
return 1;
|
||||||
|
|
||||||
if (ncp_case_sensitive(pinode))
|
if (ncp_case_sensitive(pinode))
|
||||||
return strncmp(str, name->name, len);
|
return strncmp(str, name->name, len);
|
||||||
|
|
||||||
|
@ -796,15 +796,16 @@ static int sysctl_is_seen(struct ctl_table_header *p)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int proc_sys_compare(const struct dentry *parent,
|
static int proc_sys_compare(const struct dentry *parent, const struct dentry *dentry,
|
||||||
const struct inode *pinode,
|
|
||||||
const struct dentry *dentry, const struct inode *inode,
|
|
||||||
unsigned int len, const char *str, const struct qstr *name)
|
unsigned int len, const char *str, const struct qstr *name)
|
||||||
{
|
{
|
||||||
struct ctl_table_header *head;
|
struct ctl_table_header *head;
|
||||||
|
struct inode *inode;
|
||||||
|
|
||||||
/* Although proc doesn't have negative dentries, rcu-walk means
|
/* Although proc doesn't have negative dentries, rcu-walk means
|
||||||
* that inode here can be NULL */
|
* that inode here can be NULL */
|
||||||
/* AV: can it, indeed? */
|
/* AV: can it, indeed? */
|
||||||
|
inode = ACCESS_ONCE(dentry->d_inode);
|
||||||
if (!inode)
|
if (!inode)
|
||||||
return 1;
|
return 1;
|
||||||
if (name->len != len)
|
if (name->len != len)
|
||||||
|
@ -27,8 +27,7 @@ static int add_nondir(struct dentry *dentry, struct inode *inode)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sysv_hash(const struct dentry *dentry, const struct inode *inode,
|
static int sysv_hash(const struct dentry *dentry, struct qstr *qstr)
|
||||||
struct qstr *qstr)
|
|
||||||
{
|
{
|
||||||
/* Truncate the name in place, avoids having to define a compare
|
/* Truncate the name in place, avoids having to define a compare
|
||||||
function. */
|
function. */
|
||||||
|
@ -146,10 +146,8 @@ enum dentry_d_lock_class
|
|||||||
struct dentry_operations {
|
struct dentry_operations {
|
||||||
int (*d_revalidate)(struct dentry *, unsigned int);
|
int (*d_revalidate)(struct dentry *, unsigned int);
|
||||||
int (*d_weak_revalidate)(struct dentry *, unsigned int);
|
int (*d_weak_revalidate)(struct dentry *, unsigned int);
|
||||||
int (*d_hash)(const struct dentry *, const struct inode *,
|
int (*d_hash)(const struct dentry *, struct qstr *);
|
||||||
struct qstr *);
|
int (*d_compare)(const struct dentry *, const struct dentry *,
|
||||||
int (*d_compare)(const struct dentry *, const struct inode *,
|
|
||||||
const struct dentry *, const struct inode *,
|
|
||||||
unsigned int, const char *, const struct qstr *);
|
unsigned int, const char *, const struct qstr *);
|
||||||
int (*d_delete)(const struct dentry *);
|
int (*d_delete)(const struct dentry *);
|
||||||
void (*d_release)(struct dentry *);
|
void (*d_release)(struct dentry *);
|
||||||
@ -302,8 +300,7 @@ extern struct dentry *d_lookup(const struct dentry *, const struct qstr *);
|
|||||||
extern struct dentry *d_hash_and_lookup(struct dentry *, struct qstr *);
|
extern struct dentry *d_hash_and_lookup(struct dentry *, struct qstr *);
|
||||||
extern struct dentry *__d_lookup(const struct dentry *, const struct qstr *);
|
extern struct dentry *__d_lookup(const struct dentry *, const struct qstr *);
|
||||||
extern struct dentry *__d_lookup_rcu(const struct dentry *parent,
|
extern struct dentry *__d_lookup_rcu(const struct dentry *parent,
|
||||||
const struct qstr *name,
|
const struct qstr *name, unsigned *seq);
|
||||||
unsigned *seq, struct inode *inode);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __d_rcu_to_refcount - take a refcount on dentry if sequence check is ok
|
* __d_rcu_to_refcount - take a refcount on dentry if sequence check is ok
|
||||||
|
Loading…
x
Reference in New Issue
Block a user