Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit da53be12 authored by Linus Torvalds's avatar Linus Torvalds Committed by Al Viro
Browse files

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: default avatarLinus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 642b704c
Loading
Loading
Loading
Loading
+2 −4
Original line number Original line Diff line number Diff line
@@ -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 *);
+8 −11
Original line number Original line Diff line number Diff line
@@ -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.
+2 −4
Original line number Original line Diff line number Diff line
@@ -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;
+8 −18
Original line number Original line Diff line number Diff line
@@ -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);
+3 −6
Original line number Original line Diff line number Diff line
@@ -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))
Loading