diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index 1b3c39a7de62..d30fb2cb5066 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking @@ -12,7 +12,7 @@ prototypes: int (*d_revalidate)(struct dentry *, unsigned int); int (*d_weak_revalidate)(struct dentry *, unsigned int); int (*d_hash)(const struct dentry *, struct qstr *); - int (*d_compare)(const struct dentry *, const struct dentry *, + int (*d_compare)(const struct dentry *, unsigned int, const char *, const struct qstr *); int (*d_delete)(struct dentry *); int (*d_init)(struct dentry *); diff --git a/Documentation/filesystems/porting b/Documentation/filesystems/porting index a5fb89cac615..b1bd05ea66b2 100644 --- a/Documentation/filesystems/porting +++ b/Documentation/filesystems/porting @@ -585,3 +585,10 @@ in your dentry operations instead. in the instances. Rationale: !@#!@# security_d_instantiate() needs to be called before we attach dentry to inode and !@#!@##!@$!$#!@#$!@$!@$ smack ->d_instantiate() uses not just ->getxattr() but ->setxattr() as well. +-- +[mandatory] + ->d_compare() doesn't get parent as a separate argument anymore. If you + used it for finding the struct super_block involved, dentry->d_sb will + work just as well; if it's something more complicated, use dentry->d_parent. + Just be careful not to assume that fetching it more than once will yield + the same value - in RCU mode it could change under you. diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index 8a196851f01d..9ace359d6cc5 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt @@ -931,7 +931,7 @@ struct dentry_operations { int (*d_revalidate)(struct dentry *, unsigned int); int (*d_weak_revalidate)(struct dentry *, unsigned int); int (*d_hash)(const struct dentry *, struct qstr *); - int (*d_compare)(const struct dentry *, const struct dentry *, + int (*d_compare)(const struct dentry *, unsigned int, const char *, const struct qstr *); int (*d_delete)(const struct dentry *); int (*d_init)(struct dentry *); diff --git a/drivers/staging/lustre/lustre/llite/dcache.c b/drivers/staging/lustre/lustre/llite/dcache.c index 581a63a0a63e..463b1a360733 100644 --- a/drivers/staging/lustre/lustre/llite/dcache.c +++ b/drivers/staging/lustre/lustre/llite/dcache.c @@ -78,7 +78,7 @@ static void ll_release(struct dentry *de) * INVALID) so d_lookup() matches it, but we have no lock on it (so * lock_match() fails) and we spin around real_lookup(). */ -static int ll_dcompare(const struct dentry *parent, const struct dentry *dentry, +static int ll_dcompare(const struct dentry *dentry, unsigned int len, const char *str, const struct qstr *name) { diff --git a/fs/adfs/dir.c b/fs/adfs/dir.c index bec25f7017c0..c30a5a65cbb5 100644 --- a/fs/adfs/dir.c +++ b/fs/adfs/dir.c @@ -227,7 +227,7 @@ adfs_hash(const struct dentry *parent, struct qstr *qstr) * requirements of the underlying filesystem. */ static int -adfs_compare(const struct dentry *parent, const struct dentry *dentry, +adfs_compare(const struct dentry *dentry, unsigned int len, const char *str, const struct qstr *name) { int i; diff --git a/fs/affs/namei.c b/fs/affs/namei.c index 27ca732680d9..a2d68f828d53 100644 --- a/fs/affs/namei.c +++ b/fs/affs/namei.c @@ -14,11 +14,11 @@ typedef int (*toupper_t)(int); static int affs_toupper(int ch); static int affs_hash_dentry(const struct dentry *, struct qstr *); -static int affs_compare_dentry(const struct dentry *parent, const struct dentry *dentry, +static int affs_compare_dentry(const struct dentry *dentry, unsigned int len, const char *str, const struct qstr *name); static int affs_intl_toupper(int ch); static int affs_intl_hash_dentry(const struct dentry *, 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 *dentry, unsigned int len, const char *str, const struct qstr *name); const struct dentry_operations affs_dentry_operations = { @@ -131,7 +131,7 @@ static inline int __affs_compare_dentry(unsigned int len, } static int -affs_compare_dentry(const struct dentry *parent, const struct dentry *dentry, +affs_compare_dentry(const struct dentry *dentry, unsigned int len, const char *str, const struct qstr *name) { @@ -140,7 +140,7 @@ affs_compare_dentry(const struct dentry *parent, const struct dentry *dentry, } static int -affs_intl_compare_dentry(const struct dentry *parent, const struct dentry *dentry, +affs_intl_compare_dentry(const struct dentry *dentry, unsigned int len, const char *str, const struct qstr *name) { return __affs_compare_dentry(len, str, name, affs_intl_toupper, diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index cf394da87cd4..4716c54dbfc6 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -903,7 +903,7 @@ static int cifs_ci_hash(const struct dentry *dentry, struct qstr *q) return 0; } -static int cifs_ci_compare(const struct dentry *parent, const struct dentry *dentry, +static int cifs_ci_compare(const struct dentry *dentry, unsigned int len, const char *str, const struct qstr *name) { struct nls_table *codepage = CIFS_SB(dentry->d_sb)->local_nls; diff --git a/fs/dcache.c b/fs/dcache.c index d9450bd496ac..32a9209c8138 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -2047,7 +2047,7 @@ static inline bool d_same_name(const struct dentry *dentry, return false; return dentry_cmp(dentry, name->name, name->len) == 0; } - return parent->d_op->d_compare(parent, dentry, + return parent->d_op->d_compare(dentry, dentry->d_name.len, dentry->d_name.name, name) == 0; } @@ -2150,7 +2150,7 @@ seqretry: cpu_relax(); goto seqretry; } - if (parent->d_op->d_compare(parent, dentry, + if (parent->d_op->d_compare(dentry, tlen, tname, name) != 0) continue; } else { diff --git a/fs/efivarfs/super.c b/fs/efivarfs/super.c index a5e607e8f056..688ccc16b702 100644 --- a/fs/efivarfs/super.c +++ b/fs/efivarfs/super.c @@ -45,8 +45,7 @@ static struct super_block *efivarfs_sb; * So we need to perform a case-sensitive match on part 1 and a * case-insensitive match on part 2. */ -static int efivarfs_d_compare(const struct dentry *parent, - const struct dentry *dentry, +static int efivarfs_d_compare(const struct dentry *dentry, unsigned int len, const char *str, const struct qstr *name) { diff --git a/fs/fat/namei_msdos.c b/fs/fat/namei_msdos.c index 0f177127e4d6..664655b2c55f 100644 --- a/fs/fat/namei_msdos.c +++ b/fs/fat/namei_msdos.c @@ -162,7 +162,7 @@ static int msdos_hash(const 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(const struct dentry *parent, const struct dentry *dentry, +static int msdos_cmp(const struct dentry *dentry, unsigned int len, const char *str, const struct qstr *name) { struct fat_mount_options *options = &MSDOS_SB(dentry->d_sb)->options; diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c index e60a90841381..0335e504e65a 100644 --- a/fs/fat/namei_vfat.c +++ b/fs/fat/namei_vfat.c @@ -138,7 +138,7 @@ static int vfat_hashi(const struct dentry *dentry, struct qstr *qstr) /* * Case insensitive compare of two vfat names. */ -static int vfat_cmpi(const struct dentry *parent, const struct dentry *dentry, +static int vfat_cmpi(const struct dentry *dentry, unsigned int len, const char *str, const struct qstr *name) { struct nls_table *t = MSDOS_SB(dentry->d_sb)->nls_io; @@ -157,7 +157,7 @@ static int vfat_cmpi(const struct dentry *parent, const struct dentry *dentry, /* * Case sensitive compare of two vfat names. */ -static int vfat_cmp(const struct dentry *parent, const struct dentry *dentry, +static int vfat_cmp(const struct dentry *dentry, unsigned int len, const char *str, const struct qstr *name) { unsigned int alen, blen; diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h index ee2f385811c8..f28d7a259105 100644 --- a/fs/hfs/hfs_fs.h +++ b/fs/hfs/hfs_fs.h @@ -233,7 +233,7 @@ extern const struct dentry_operations hfs_dentry_operations; extern int hfs_hash_dentry(const struct dentry *, struct qstr *); extern int hfs_strcmp(const unsigned char *, unsigned int, const unsigned char *, unsigned int); -extern int hfs_compare_dentry(const struct dentry *parent, const struct dentry *dentry, +extern int hfs_compare_dentry(const struct dentry *dentry, unsigned int len, const char *str, const struct qstr *name); /* trans.c */ diff --git a/fs/hfs/string.c b/fs/hfs/string.c index ec9f164c35a5..3912209153a8 100644 --- a/fs/hfs/string.c +++ b/fs/hfs/string.c @@ -92,7 +92,7 @@ int hfs_strcmp(const unsigned char *s1, unsigned int len1, * Test for equality of two strings in the HFS filename character ordering. * return 1 on failure and 0 on success */ -int hfs_compare_dentry(const struct dentry *parent, const struct dentry *dentry, +int hfs_compare_dentry(const struct dentry *dentry, unsigned int len, const char *str, const struct qstr *name) { const unsigned char *n1, *n2; diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h index 047245bd2cd6..e95c01f1d62e 100644 --- a/fs/hfsplus/hfsplus_fs.h +++ b/fs/hfsplus/hfsplus_fs.h @@ -520,8 +520,7 @@ int hfsplus_uni2asc(struct super_block *sb, const struct hfsplus_unistr *ustr, int hfsplus_asc2uni(struct super_block *sb, struct hfsplus_unistr *ustr, int max_unistr_len, const char *astr, int len); int hfsplus_hash_dentry(const struct dentry *dentry, struct qstr *str); -int hfsplus_compare_dentry(const struct dentry *parent, - const struct dentry *dentry, unsigned int len, +int hfsplus_compare_dentry(const struct dentry *dentry, unsigned int len, const char *str, const struct qstr *name); /* wrapper.c */ diff --git a/fs/hfsplus/unicode.c b/fs/hfsplus/unicode.c index 509d7e231460..e563939882f3 100644 --- a/fs/hfsplus/unicode.c +++ b/fs/hfsplus/unicode.c @@ -385,7 +385,7 @@ int hfsplus_hash_dentry(const struct dentry *dentry, struct qstr *str) * Composed unicode characters are decomposed and case-folding is performed * if the appropriate bits are (un)set on the superblock. */ -int hfsplus_compare_dentry(const struct dentry *parent, const struct dentry *dentry, +int hfsplus_compare_dentry(const struct dentry *dentry, unsigned int len, const char *str, const struct qstr *name) { struct super_block *sb = dentry->d_sb; diff --git a/fs/hpfs/dentry.c b/fs/hpfs/dentry.c index a804300f4dce..bb87d65f0d97 100644 --- a/fs/hpfs/dentry.c +++ b/fs/hpfs/dentry.c @@ -34,7 +34,7 @@ static int hpfs_hash_dentry(const struct dentry *dentry, struct qstr *qstr) return 0; } -static int hpfs_compare_dentry(const struct dentry *parent, const struct dentry *dentry, +static int hpfs_compare_dentry(const struct dentry *dentry, unsigned int len, const char *str, const struct qstr *name) { unsigned al = len; diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index 761fade7680f..ad0c745ebad7 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -29,18 +29,15 @@ #define BEQUIET static int isofs_hashi(const struct dentry *parent, struct qstr *qstr); -static int isofs_dentry_cmpi(const struct dentry *parent, - const struct dentry *dentry, +static int isofs_dentry_cmpi(const struct dentry *dentry, unsigned int len, const char *str, const struct qstr *name); #ifdef CONFIG_JOLIET static int isofs_hashi_ms(const struct dentry *parent, struct qstr *qstr); static int isofs_hash_ms(const struct dentry *parent, struct qstr *qstr); -static int isofs_dentry_cmpi_ms(const struct dentry *parent, - const struct dentry *dentry, +static int isofs_dentry_cmpi_ms(const struct dentry *dentry, unsigned int len, const char *str, const struct qstr *name); -static int isofs_dentry_cmp_ms(const struct dentry *parent, - const struct dentry *dentry, +static int isofs_dentry_cmp_ms(const struct dentry *dentry, unsigned int len, const char *str, const struct qstr *name); #endif @@ -235,7 +232,7 @@ isofs_hashi(const struct dentry *dentry, struct qstr *qstr) } static int -isofs_dentry_cmpi(const struct dentry *parent, const struct dentry *dentry, +isofs_dentry_cmpi(const struct dentry *dentry, unsigned int len, const char *str, const struct qstr *name) { return isofs_dentry_cmp_common(len, str, name, 0, 1); @@ -276,14 +273,14 @@ isofs_hashi_ms(const struct dentry *dentry, struct qstr *qstr) } static int -isofs_dentry_cmp_ms(const struct dentry *parent, const struct dentry *dentry, +isofs_dentry_cmp_ms(const struct dentry *dentry, unsigned int len, const char *str, const struct qstr *name) { return isofs_dentry_cmp_common(len, str, name, 1, 0); } static int -isofs_dentry_cmpi_ms(const struct dentry *parent, const struct dentry *dentry, +isofs_dentry_cmpi_ms(const struct dentry *dentry, unsigned int len, const char *str, const struct qstr *name) { return isofs_dentry_cmp_common(len, str, name, 1, 1); diff --git a/fs/isofs/namei.c b/fs/isofs/namei.c index 7b543e6b6526..aee592767f1d 100644 --- a/fs/isofs/namei.c +++ b/fs/isofs/namei.c @@ -22,7 +22,7 @@ isofs_cmp(struct dentry *dentry, const char *compare, int dlen) qstr.len = dlen; if (likely(!dentry->d_op)) return dentry->d_name.len != dlen || memcmp(dentry->d_name.name, compare, dlen); - return dentry->d_op->d_compare(NULL, NULL, dentry->d_name.len, dentry->d_name.name, &qstr); + return dentry->d_op->d_compare(NULL, dentry->d_name.len, dentry->d_name.name, &qstr); } /* diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c index 04baf0dfc40c..814b0c58016c 100644 --- a/fs/jfs/namei.c +++ b/fs/jfs/namei.c @@ -1572,7 +1572,7 @@ static int jfs_ci_hash(const struct dentry *dir, struct qstr *this) return 0; } -static int jfs_ci_compare(const struct dentry *parent, const struct dentry *dentry, +static int jfs_ci_compare(const struct dentry *dentry, unsigned int len, const char *str, const struct qstr *name) { int i, result = 1; diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c index 9add7ab747a5..17de5c13dfae 100644 --- a/fs/ncpfs/dir.c +++ b/fs/ncpfs/dir.c @@ -74,7 +74,7 @@ const struct inode_operations ncp_dir_inode_operations = */ static int ncp_lookup_validate(struct dentry *, unsigned int); static int ncp_hash_dentry(const struct dentry *, struct qstr *); -static int ncp_compare_dentry(const struct dentry *, const struct dentry *, +static int ncp_compare_dentry(const struct dentry *, unsigned int, const char *, const struct qstr *); static int ncp_delete_dentry(const struct dentry *); static void ncp_d_prune(struct dentry *dentry); @@ -154,7 +154,7 @@ ncp_hash_dentry(const struct dentry *dentry, struct qstr *this) * the callers will handle races. */ static int -ncp_compare_dentry(const struct dentry *parent, const struct dentry *dentry, +ncp_compare_dentry(const struct dentry *dentry, unsigned int len, const char *str, const struct qstr *name) { struct inode *pinode; @@ -162,7 +162,7 @@ ncp_compare_dentry(const struct dentry *parent, const struct dentry *dentry, if (len != name->len) return 1; - pinode = d_inode_rcu(parent); + pinode = d_inode_rcu(dentry->d_parent); if (!pinode) return 1; diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c index b59db94d2ff4..30bb00130d0f 100644 --- a/fs/proc/proc_sysctl.c +++ b/fs/proc/proc_sysctl.c @@ -834,7 +834,7 @@ static int sysctl_is_seen(struct ctl_table_header *p) return res; } -static int proc_sys_compare(const struct dentry *parent, const struct dentry *dentry, +static int proc_sys_compare(const struct dentry *dentry, unsigned int len, const char *str, const struct qstr *name) { struct ctl_table_header *head; diff --git a/include/linux/dcache.h b/include/linux/dcache.h index 98044a8d1487..107d9abe7166 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -130,7 +130,7 @@ struct dentry_operations { int (*d_revalidate)(struct dentry *, unsigned int); int (*d_weak_revalidate)(struct dentry *, unsigned int); int (*d_hash)(const struct dentry *, struct qstr *); - int (*d_compare)(const struct dentry *, const struct dentry *, + int (*d_compare)(const struct dentry *, unsigned int, const char *, const struct qstr *); int (*d_delete)(const struct dentry *); int (*d_init)(struct dentry *);