fs: change d_hash for rcu-walk
Change d_hash so it may be called from lock-free RCU lookups. See similar patch for d_compare for details. For in-tree filesystems, this is just a mechanical change. Signed-off-by: Nick Piggin <npiggin@kernel.dk>
This commit is contained in:
parent
621e155a35
commit
b1e6a015a5
|
@ -10,7 +10,8 @@ be able to use diff(1).
|
|||
--------------------------- dentry_operations --------------------------
|
||||
prototypes:
|
||||
int (*d_revalidate)(struct dentry *, int);
|
||||
int (*d_hash) (struct dentry *, struct qstr *);
|
||||
int (*d_hash)(const struct dentry *, const struct inode *,
|
||||
struct qstr *);
|
||||
int (*d_compare)(const struct dentry *, const struct inode *,
|
||||
const struct dentry *, const struct inode *,
|
||||
unsigned int, const char *, const struct qstr *);
|
||||
|
@ -22,7 +23,7 @@ prototypes:
|
|||
locking rules:
|
||||
dcache_lock rename_lock ->d_lock may block
|
||||
d_revalidate: no no no yes
|
||||
d_hash no no no yes
|
||||
d_hash no no no no
|
||||
d_compare: no yes no no
|
||||
d_delete: yes no yes no
|
||||
d_release: no no no yes
|
||||
|
|
|
@ -333,3 +333,10 @@ unreferenced dentries, and is now only called when the dentry refcount goes to
|
|||
.d_compare() calling convention and locking rules are significantly
|
||||
changed. Read updated documentation in Documentation/filesystems/vfs.txt (and
|
||||
look at examples of other filesystems) for guidance.
|
||||
|
||||
---
|
||||
[mandatory]
|
||||
|
||||
.d_hash() calling convention and locking rules are significantly
|
||||
changed. Read updated documentation in Documentation/filesystems/vfs.txt (and
|
||||
look at examples of other filesystems) for guidance.
|
||||
|
|
|
@ -847,7 +847,8 @@ defined:
|
|||
|
||||
struct dentry_operations {
|
||||
int (*d_revalidate)(struct dentry *, struct nameidata *);
|
||||
int (*d_hash)(struct dentry *, struct qstr *);
|
||||
int (*d_hash)(const struct dentry *, const struct inode *,
|
||||
struct qstr *);
|
||||
int (*d_compare)(const struct dentry *, const struct inode *,
|
||||
const struct dentry *, const struct inode *,
|
||||
unsigned int, const char *, const struct qstr *);
|
||||
|
@ -864,7 +865,10 @@ struct dentry_operations {
|
|||
|
||||
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
|
||||
to be hashed into.
|
||||
to be hashed into. The inode is the dentry's inode.
|
||||
|
||||
Same locking and synchronisation rules as d_compare regarding
|
||||
what is safe to dereference etc.
|
||||
|
||||
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
|
||||
|
|
|
@ -134,7 +134,7 @@ smb_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
|
|||
qname->hash = full_name_hash(qname->name, qname->len);
|
||||
|
||||
if (dentry->d_op && dentry->d_op->d_hash)
|
||||
if (dentry->d_op->d_hash(dentry, qname) != 0)
|
||||
if (dentry->d_op->d_hash(dentry, inode, qname) != 0)
|
||||
goto end_advance;
|
||||
|
||||
newdent = d_lookup(dentry, qname);
|
||||
|
|
|
@ -274,7 +274,8 @@ smb_dir_open(struct inode *dir, struct file *file)
|
|||
* Dentry operations routines
|
||||
*/
|
||||
static int smb_lookup_validate(struct dentry *, struct nameidata *);
|
||||
static int smb_hash_dentry(struct dentry *, struct qstr *);
|
||||
static int smb_hash_dentry(const struct dentry *, const struct inode *,
|
||||
struct qstr *);
|
||||
static int smb_compare_dentry(const struct dentry *,
|
||||
const struct inode *,
|
||||
const struct dentry *, const struct inode *,
|
||||
|
@ -336,7 +337,8 @@ smb_lookup_validate(struct dentry * dentry, struct nameidata *nd)
|
|||
}
|
||||
|
||||
static int
|
||||
smb_hash_dentry(struct dentry *dir, struct qstr *this)
|
||||
smb_hash_dentry(const struct dentry *dir, const struct inode *inode,
|
||||
struct qstr *this)
|
||||
{
|
||||
unsigned long hash;
|
||||
int i;
|
||||
|
|
|
@ -201,7 +201,8 @@ const struct file_operations adfs_dir_operations = {
|
|||
};
|
||||
|
||||
static int
|
||||
adfs_hash(struct dentry *parent, struct qstr *qstr)
|
||||
adfs_hash(const struct dentry *parent, const struct inode *inode,
|
||||
struct qstr *qstr)
|
||||
{
|
||||
const unsigned int name_len = ADFS_SB(parent->d_sb)->s_namelen;
|
||||
const unsigned char *name;
|
||||
|
|
|
@ -13,13 +13,15 @@
|
|||
typedef int (*toupper_t)(int);
|
||||
|
||||
static int affs_toupper(int ch);
|
||||
static int affs_hash_dentry(struct dentry *, struct qstr *);
|
||||
static int affs_hash_dentry(const struct dentry *,
|
||||
const struct inode *, struct qstr *);
|
||||
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);
|
||||
static int affs_intl_toupper(int ch);
|
||||
static int affs_intl_hash_dentry(struct dentry *, struct qstr *);
|
||||
static int affs_intl_hash_dentry(const struct dentry *,
|
||||
const struct inode *, struct qstr *);
|
||||
static int affs_intl_compare_dentry(const struct dentry *parent,
|
||||
const struct inode *pinode,
|
||||
const struct dentry *dentry, const struct inode *inode,
|
||||
|
@ -64,13 +66,13 @@ affs_get_toupper(struct super_block *sb)
|
|||
* Note: the dentry argument is the parent dentry.
|
||||
*/
|
||||
static inline int
|
||||
__affs_hash_dentry(struct dentry *dentry, struct qstr *qstr, toupper_t toupper)
|
||||
__affs_hash_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);
|
||||
i = affs_check_name(qstr->name, qstr->len);
|
||||
if (i)
|
||||
return i;
|
||||
|
||||
|
@ -84,14 +86,16 @@ __affs_hash_dentry(struct dentry *dentry, struct qstr *qstr, toupper_t toupper)
|
|||
}
|
||||
|
||||
static int
|
||||
affs_hash_dentry(struct dentry *dentry, struct qstr *qstr)
|
||||
affs_hash_dentry(const struct dentry *dentry, const struct inode *inode,
|
||||
struct qstr *qstr)
|
||||
{
|
||||
return __affs_hash_dentry(dentry, qstr, affs_toupper);
|
||||
return __affs_hash_dentry(qstr, affs_toupper);
|
||||
}
|
||||
static int
|
||||
affs_intl_hash_dentry(struct dentry *dentry, struct qstr *qstr)
|
||||
affs_intl_hash_dentry(const struct dentry *dentry, const struct inode *inode,
|
||||
struct qstr *qstr)
|
||||
{
|
||||
return __affs_hash_dentry(dentry, qstr, affs_intl_toupper);
|
||||
return __affs_hash_dentry(qstr, affs_intl_toupper);
|
||||
}
|
||||
|
||||
static inline int __affs_compare_dentry(unsigned int len,
|
||||
|
|
|
@ -700,9 +700,10 @@ const struct dentry_operations cifs_dentry_ops = {
|
|||
/* d_delete: cifs_d_delete, */ /* not needed except for debugging */
|
||||
};
|
||||
|
||||
static int cifs_ci_hash(struct dentry *dentry, struct qstr *q)
|
||||
static int cifs_ci_hash(const struct dentry *dentry, const struct inode *inode,
|
||||
struct qstr *q)
|
||||
{
|
||||
struct nls_table *codepage = CIFS_SB(dentry->d_inode->i_sb)->local_nls;
|
||||
struct nls_table *codepage = CIFS_SB(dentry->d_sb)->local_nls;
|
||||
unsigned long hash;
|
||||
int i;
|
||||
|
||||
|
|
|
@ -79,7 +79,7 @@ cifs_readdir_lookup(struct dentry *parent, struct qstr *name,
|
|||
cFYI(1, "For %s", name->name);
|
||||
|
||||
if (parent->d_op && parent->d_op->d_hash)
|
||||
parent->d_op->d_hash(parent, name);
|
||||
parent->d_op->d_hash(parent, parent->d_inode, name);
|
||||
else
|
||||
name->hash = full_name_hash(name->name, name->len);
|
||||
|
||||
|
|
|
@ -1478,7 +1478,7 @@ struct dentry *d_hash_and_lookup(struct dentry *dir, struct qstr *name)
|
|||
*/
|
||||
name->hash = full_name_hash(name->name, name->len);
|
||||
if (dir->d_op && dir->d_op->d_hash) {
|
||||
if (dir->d_op->d_hash(dir, name) < 0)
|
||||
if (dir->d_op->d_hash(dir, dir->d_inode, name) < 0)
|
||||
goto out;
|
||||
}
|
||||
dentry = d_lookup(dir, name);
|
||||
|
|
|
@ -454,7 +454,7 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode,
|
|||
lower_name.hash = ecryptfs_dentry->d_name.hash;
|
||||
if (lower_dir_dentry->d_op && lower_dir_dentry->d_op->d_hash) {
|
||||
rc = lower_dir_dentry->d_op->d_hash(lower_dir_dentry,
|
||||
&lower_name);
|
||||
lower_dir_dentry->d_inode, &lower_name);
|
||||
if (rc < 0)
|
||||
goto out_d_drop;
|
||||
}
|
||||
|
@ -489,7 +489,7 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode,
|
|||
lower_name.hash = full_name_hash(lower_name.name, lower_name.len);
|
||||
if (lower_dir_dentry->d_op && lower_dir_dentry->d_op->d_hash) {
|
||||
rc = lower_dir_dentry->d_op->d_hash(lower_dir_dentry,
|
||||
&lower_name);
|
||||
lower_dir_dentry->d_inode, &lower_name);
|
||||
if (rc < 0)
|
||||
goto out_d_drop;
|
||||
}
|
||||
|
|
|
@ -148,7 +148,8 @@ 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
|
||||
* return ENOENT or EINVAL as appropriate.
|
||||
*/
|
||||
static int msdos_hash(struct dentry *dentry, struct qstr *qstr)
|
||||
static int msdos_hash(const struct dentry *dentry, const struct inode *inode,
|
||||
struct qstr *qstr)
|
||||
{
|
||||
struct fat_mount_options *options = &MSDOS_SB(dentry->d_sb)->options;
|
||||
unsigned char msdos_name[MSDOS_NAME];
|
||||
|
|
|
@ -103,7 +103,8 @@ static unsigned int vfat_striptail_len(const struct qstr *qstr)
|
|||
* that the existing dentry can be used. The vfat fs routines will
|
||||
* return ENOENT or EINVAL as appropriate.
|
||||
*/
|
||||
static int vfat_hash(struct dentry *dentry, struct qstr *qstr)
|
||||
static int vfat_hash(const struct dentry *dentry, const struct inode *inode,
|
||||
struct qstr *qstr)
|
||||
{
|
||||
qstr->hash = full_name_hash(qstr->name, vfat_striptail_len(qstr));
|
||||
return 0;
|
||||
|
@ -115,9 +116,10 @@ static int vfat_hash(struct dentry *dentry, struct qstr *qstr)
|
|||
* that the existing dentry can be used. The vfat fs routines will
|
||||
* return ENOENT or EINVAL as appropriate.
|
||||
*/
|
||||
static int vfat_hashi(struct dentry *dentry, struct qstr *qstr)
|
||||
static int vfat_hashi(const struct dentry *dentry, const struct inode *inode,
|
||||
struct qstr *qstr)
|
||||
{
|
||||
struct nls_table *t = MSDOS_SB(dentry->d_inode->i_sb)->nls_io;
|
||||
struct nls_table *t = MSDOS_SB(dentry->d_sb)->nls_io;
|
||||
const unsigned char *name;
|
||||
unsigned int len;
|
||||
unsigned long hash;
|
||||
|
|
|
@ -100,7 +100,8 @@ fail:
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int gfs2_dhash(struct dentry *dentry, struct qstr *str)
|
||||
static int gfs2_dhash(const struct dentry *dentry, const struct inode *inode,
|
||||
struct qstr *str)
|
||||
{
|
||||
str->hash = gfs2_disk_hash(str->name, str->len);
|
||||
return 0;
|
||||
|
|
|
@ -213,7 +213,8 @@ extern int hfs_part_find(struct super_block *, sector_t *, sector_t *);
|
|||
/* string.c */
|
||||
extern const struct dentry_operations hfs_dentry_operations;
|
||||
|
||||
extern int hfs_hash_dentry(struct dentry *, struct qstr *);
|
||||
extern int hfs_hash_dentry(const struct dentry *, const struct inode *,
|
||||
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,
|
||||
|
|
|
@ -51,7 +51,8 @@ static unsigned char caseorder[256] = {
|
|||
/*
|
||||
* Hash a string to an integer in a case-independent way
|
||||
*/
|
||||
int hfs_hash_dentry(struct dentry *dentry, struct qstr *this)
|
||||
int hfs_hash_dentry(const struct dentry *dentry, const struct inode *inode,
|
||||
struct qstr *this)
|
||||
{
|
||||
const unsigned char *name = this->name;
|
||||
unsigned int hash, len = this->len;
|
||||
|
|
|
@ -379,7 +379,8 @@ int hfsplus_strcasecmp(const struct hfsplus_unistr *, const struct hfsplus_unist
|
|||
int hfsplus_strcmp(const struct hfsplus_unistr *, const struct hfsplus_unistr *);
|
||||
int hfsplus_uni2asc(struct super_block *, const struct hfsplus_unistr *, char *, int *);
|
||||
int hfsplus_asc2uni(struct super_block *, struct hfsplus_unistr *, const char *, int);
|
||||
int hfsplus_hash_dentry(struct dentry *dentry, struct qstr *str);
|
||||
int hfsplus_hash_dentry(const struct dentry *dentry, const struct inode *inode,
|
||||
struct qstr *str);
|
||||
int hfsplus_compare_dentry(const struct dentry *parent,
|
||||
const struct inode *pinode,
|
||||
const struct dentry *dentry, const struct inode *inode,
|
||||
|
|
|
@ -320,7 +320,8 @@ int hfsplus_asc2uni(struct super_block *sb, struct hfsplus_unistr *ustr,
|
|||
* Composed unicode characters are decomposed and case-folding is performed
|
||||
* if the appropriate bits are (un)set on the superblock.
|
||||
*/
|
||||
int hfsplus_hash_dentry(struct dentry *dentry, struct qstr *str)
|
||||
int hfsplus_hash_dentry(const struct dentry *dentry, const struct inode *inode,
|
||||
struct qstr *str)
|
||||
{
|
||||
struct super_block *sb = dentry->d_sb;
|
||||
const char *astr;
|
||||
|
|
|
@ -12,7 +12,8 @@
|
|||
* Note: the dentry argument is the parent dentry.
|
||||
*/
|
||||
|
||||
static int hpfs_hash_dentry(struct dentry *dentry, struct qstr *qstr)
|
||||
static int hpfs_hash_dentry(const struct dentry *dentry, const struct inode *inode,
|
||||
struct qstr *qstr)
|
||||
{
|
||||
unsigned long hash;
|
||||
int i;
|
||||
|
|
|
@ -26,8 +26,10 @@
|
|||
|
||||
#define BEQUIET
|
||||
|
||||
static int isofs_hashi(struct dentry *parent, struct qstr *qstr);
|
||||
static int isofs_hash(struct dentry *parent, struct qstr *qstr);
|
||||
static int isofs_hashi(const struct dentry *parent, const struct inode *inode,
|
||||
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,
|
||||
const struct inode *pinode,
|
||||
const struct dentry *dentry, const struct inode *inode,
|
||||
|
@ -38,8 +40,10 @@ static int isofs_dentry_cmp(const struct dentry *parent,
|
|||
unsigned int len, const char *str, const struct qstr *name);
|
||||
|
||||
#ifdef CONFIG_JOLIET
|
||||
static int isofs_hashi_ms(struct dentry *parent, struct qstr *qstr);
|
||||
static int isofs_hash_ms(struct dentry *parent, struct qstr *qstr);
|
||||
static int isofs_hashi_ms(const struct dentry *parent, const struct inode *inode,
|
||||
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,
|
||||
const struct inode *pinode,
|
||||
const struct dentry *dentry, const struct inode *inode,
|
||||
|
@ -172,7 +176,7 @@ struct iso9660_options{
|
|||
* Compute the hash for the isofs name corresponding to the dentry.
|
||||
*/
|
||||
static int
|
||||
isofs_hash_common(struct dentry *dentry, struct qstr *qstr, int ms)
|
||||
isofs_hash_common(const struct dentry *dentry, struct qstr *qstr, int ms)
|
||||
{
|
||||
const char *name;
|
||||
int len;
|
||||
|
@ -193,7 +197,7 @@ isofs_hash_common(struct dentry *dentry, struct qstr *qstr, int ms)
|
|||
* Compute the hash for the isofs name corresponding to the dentry.
|
||||
*/
|
||||
static int
|
||||
isofs_hashi_common(struct dentry *dentry, struct qstr *qstr, int ms)
|
||||
isofs_hashi_common(const struct dentry *dentry, struct qstr *qstr, int ms)
|
||||
{
|
||||
const char *name;
|
||||
int len;
|
||||
|
@ -248,13 +252,15 @@ static int isofs_dentry_cmp_common(
|
|||
}
|
||||
|
||||
static int
|
||||
isofs_hash(struct dentry *dentry, struct qstr *qstr)
|
||||
isofs_hash(const struct dentry *dentry, const struct inode *inode,
|
||||
struct qstr *qstr)
|
||||
{
|
||||
return isofs_hash_common(dentry, qstr, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
isofs_hashi(struct dentry *dentry, struct qstr *qstr)
|
||||
isofs_hashi(const struct dentry *dentry, const struct inode *inode,
|
||||
struct qstr *qstr)
|
||||
{
|
||||
return isofs_hashi_common(dentry, qstr, 0);
|
||||
}
|
||||
|
@ -277,13 +283,15 @@ isofs_dentry_cmpi(const struct dentry *parent, const struct inode *pinode,
|
|||
|
||||
#ifdef CONFIG_JOLIET
|
||||
static int
|
||||
isofs_hash_ms(struct dentry *dentry, struct qstr *qstr)
|
||||
isofs_hash_ms(const struct dentry *dentry, const struct inode *inode,
|
||||
struct qstr *qstr)
|
||||
{
|
||||
return isofs_hash_common(dentry, qstr, 1);
|
||||
}
|
||||
|
||||
static int
|
||||
isofs_hashi_ms(struct dentry *dentry, struct qstr *qstr)
|
||||
isofs_hashi_ms(const struct dentry *dentry, const struct inode *inode,
|
||||
struct qstr *qstr)
|
||||
{
|
||||
return isofs_hashi_common(dentry, qstr, 1);
|
||||
}
|
||||
|
|
|
@ -1574,7 +1574,8 @@ const struct file_operations jfs_dir_operations = {
|
|||
.llseek = generic_file_llseek,
|
||||
};
|
||||
|
||||
static int jfs_ci_hash(struct dentry *dir, struct qstr *this)
|
||||
static int jfs_ci_hash(const struct dentry *dir, const struct inode *inode,
|
||||
struct qstr *this)
|
||||
{
|
||||
unsigned long hash;
|
||||
int i;
|
||||
|
|
|
@ -731,7 +731,8 @@ static int do_lookup(struct nameidata *nd, struct qstr *name,
|
|||
* to use its own hash..
|
||||
*/
|
||||
if (nd->path.dentry->d_op && nd->path.dentry->d_op->d_hash) {
|
||||
int err = nd->path.dentry->d_op->d_hash(nd->path.dentry, name);
|
||||
int err = nd->path.dentry->d_op->d_hash(nd->path.dentry,
|
||||
nd->path.dentry->d_inode, name);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
@ -1134,7 +1135,7 @@ static struct dentry *__lookup_hash(struct qstr *name,
|
|||
* to use its own hash..
|
||||
*/
|
||||
if (base->d_op && base->d_op->d_hash) {
|
||||
err = base->d_op->d_hash(base, name);
|
||||
err = base->d_op->d_hash(base, inode, name);
|
||||
dentry = ERR_PTR(err);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
|
|
|
@ -74,7 +74,8 @@ const struct inode_operations ncp_dir_inode_operations =
|
|||
* Dentry operations routines
|
||||
*/
|
||||
static int ncp_lookup_validate(struct dentry *, struct nameidata *);
|
||||
static int ncp_hash_dentry(struct dentry *, struct qstr *);
|
||||
static int ncp_hash_dentry(const struct dentry *, const struct inode *,
|
||||
struct qstr *);
|
||||
static int ncp_compare_dentry(const struct dentry *, const struct inode *,
|
||||
const struct dentry *, const struct inode *,
|
||||
unsigned int, const char *, const struct qstr *);
|
||||
|
@ -129,9 +130,10 @@ static inline int ncp_case_sensitive(const struct inode *i)
|
|||
* is case-sensitive.
|
||||
*/
|
||||
static int
|
||||
ncp_hash_dentry(struct dentry *dentry, struct qstr *this)
|
||||
ncp_hash_dentry(const struct dentry *dentry, const struct inode *inode,
|
||||
struct qstr *this)
|
||||
{
|
||||
if (!ncp_case_sensitive(dentry->d_inode)) {
|
||||
if (!ncp_case_sensitive(inode)) {
|
||||
struct super_block *sb = dentry->d_sb;
|
||||
struct nls_table *t;
|
||||
unsigned long hash;
|
||||
|
@ -597,7 +599,7 @@ ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
|
|||
qname.hash = full_name_hash(qname.name, qname.len);
|
||||
|
||||
if (dentry->d_op && dentry->d_op->d_hash)
|
||||
if (dentry->d_op->d_hash(dentry, &qname) != 0)
|
||||
if (dentry->d_op->d_hash(dentry, dentry->d_inode, &qname) != 0)
|
||||
goto end_advance;
|
||||
|
||||
newdent = d_lookup(dentry, &qname);
|
||||
|
|
|
@ -27,7 +27,8 @@ static int add_nondir(struct dentry *dentry, struct inode *inode)
|
|||
return err;
|
||||
}
|
||||
|
||||
static int sysv_hash(struct dentry *dentry, struct qstr *qstr)
|
||||
static int sysv_hash(const struct dentry *dentry, const struct inode *inode,
|
||||
struct qstr *qstr)
|
||||
{
|
||||
/* Truncate the name in place, avoids having to define a compare
|
||||
function. */
|
||||
|
|
|
@ -133,7 +133,8 @@ enum dentry_d_lock_class
|
|||
|
||||
struct dentry_operations {
|
||||
int (*d_revalidate)(struct dentry *, struct nameidata *);
|
||||
int (*d_hash)(struct dentry *, struct qstr *);
|
||||
int (*d_hash)(const struct dentry *, const struct inode *,
|
||||
struct qstr *);
|
||||
int (*d_compare)(const struct dentry *, const struct inode *,
|
||||
const struct dentry *, const struct inode *,
|
||||
unsigned int, const char *, const struct qstr *);
|
||||
|
|
Loading…
Reference in New Issue