mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 03:01:39 -04:00
fs: change d_compare for rcu-walk
Change d_compare so it may be called from lock-free RCU lookups. This does put significant restrictions on what may be done from the callback, however there don't seem to have been any problems with in-tree fses. If some strange use case pops up that _really_ cannot cope with the rcu-walk rules, we can just add new rcu-unaware callbacks, which would cause name lookup to drop out of rcu-walk mode. For in-tree filesystems, this is just a mechanical change. Signed-off-by: Nick Piggin <[email protected]>
This commit is contained in:
parent
fb2d5b86af
commit
621e155a35
23 changed files with 242 additions and 157 deletions
|
|
@ -164,16 +164,18 @@ static int msdos_hash(struct dentry *dentry, struct qstr *qstr)
|
|||
* Compare two msdos names. If either of the names are invalid,
|
||||
* we fall back to doing the standard name comparison.
|
||||
*/
|
||||
static int msdos_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b)
|
||||
static int msdos_cmp(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)
|
||||
{
|
||||
struct fat_mount_options *options = &MSDOS_SB(dentry->d_sb)->options;
|
||||
struct fat_mount_options *options = &MSDOS_SB(parent->d_sb)->options;
|
||||
unsigned char a_msdos_name[MSDOS_NAME], b_msdos_name[MSDOS_NAME];
|
||||
int error;
|
||||
|
||||
error = msdos_format_name(a->name, a->len, a_msdos_name, options);
|
||||
error = msdos_format_name(name->name, name->len, a_msdos_name, options);
|
||||
if (error)
|
||||
goto old_compare;
|
||||
error = msdos_format_name(b->name, b->len, b_msdos_name, options);
|
||||
error = msdos_format_name(str, len, b_msdos_name, options);
|
||||
if (error)
|
||||
goto old_compare;
|
||||
error = memcmp(a_msdos_name, b_msdos_name, MSDOS_NAME);
|
||||
|
|
@ -182,8 +184,8 @@ out:
|
|||
|
||||
old_compare:
|
||||
error = 1;
|
||||
if (a->len == b->len)
|
||||
error = memcmp(a->name, b->name, a->len);
|
||||
if (name->len == len)
|
||||
error = memcmp(name->name, str, len);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -85,15 +85,18 @@ static int vfat_revalidate_ci(struct dentry *dentry, struct nameidata *nd)
|
|||
}
|
||||
|
||||
/* returns the length of a struct qstr, ignoring trailing dots */
|
||||
static unsigned int vfat_striptail_len(struct qstr *qstr)
|
||||
static unsigned int __vfat_striptail_len(unsigned int len, const char *name)
|
||||
{
|
||||
unsigned int len = qstr->len;
|
||||
|
||||
while (len && qstr->name[len - 1] == '.')
|
||||
while (len && name[len - 1] == '.')
|
||||
len--;
|
||||
return len;
|
||||
}
|
||||
|
||||
static unsigned int vfat_striptail_len(const struct qstr *qstr)
|
||||
{
|
||||
return __vfat_striptail_len(qstr->len, qstr->name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute the hash for the vfat name corresponding to the dentry.
|
||||
* Note: if the name is invalid, we leave the hash code unchanged so
|
||||
|
|
@ -133,16 +136,18 @@ static int vfat_hashi(struct dentry *dentry, struct qstr *qstr)
|
|||
/*
|
||||
* Case insensitive compare of two vfat names.
|
||||
*/
|
||||
static int vfat_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b)
|
||||
static int vfat_cmpi(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)
|
||||
{
|
||||
struct nls_table *t = MSDOS_SB(dentry->d_inode->i_sb)->nls_io;
|
||||
struct nls_table *t = MSDOS_SB(parent->d_sb)->nls_io;
|
||||
unsigned int alen, blen;
|
||||
|
||||
/* A filename cannot end in '.' or we treat it like it has none */
|
||||
alen = vfat_striptail_len(a);
|
||||
blen = vfat_striptail_len(b);
|
||||
alen = vfat_striptail_len(name);
|
||||
blen = __vfat_striptail_len(len, str);
|
||||
if (alen == blen) {
|
||||
if (nls_strnicmp(t, a->name, b->name, alen) == 0)
|
||||
if (nls_strnicmp(t, name->name, str, alen) == 0)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
|
|
@ -151,15 +156,17 @@ static int vfat_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b)
|
|||
/*
|
||||
* Case sensitive compare of two vfat names.
|
||||
*/
|
||||
static int vfat_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b)
|
||||
static int vfat_cmp(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 alen, blen;
|
||||
|
||||
/* A filename cannot end in '.' or we treat it like it has none */
|
||||
alen = vfat_striptail_len(a);
|
||||
blen = vfat_striptail_len(b);
|
||||
alen = vfat_striptail_len(name);
|
||||
blen = __vfat_striptail_len(len, str);
|
||||
if (alen == blen) {
|
||||
if (strncmp(a->name, b->name, alen) == 0)
|
||||
if (strncmp(name->name, str, alen) == 0)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
|
|
|
|||
Loading…
Reference in a new issue