mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 04:31:50 +00:00
kernfs: add a revision to identify directory node changes
Add a revision counter to kernfs directory nodes so it can be used to detect if a directory node has changed during negative dentry revalidation. There's an assumption that sizeof(unsigned long) <= sizeof(pointer) on all architectures and as far as I know that assumption holds. So adding a revision counter to the struct kernfs_elem_dir variant of the kernfs_node type union won't increase the size of the kernfs_node struct. This is because struct kernfs_elem_dir is at least sizeof(pointer) smaller than the largest union variant. It's tempting to make the revision counter a u64 but that would increase the size of kernfs_node on archs where sizeof(pointer) is smaller than the revision counter. Reviewed-by: Miklos Szeredi <mszeredi@redhat.com> Signed-off-by: Ian Kent <raven@themaw.net> Link: https://lore.kernel.org/r/162642769895.63632.8356662784964509867.stgit@web.messagingengine.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
bdac4d8abb
commit
895adbec30
@ -372,6 +372,7 @@ static int kernfs_link_sibling(struct kernfs_node *kn)
|
|||||||
/* successfully added, account subdir number */
|
/* successfully added, account subdir number */
|
||||||
if (kernfs_type(kn) == KERNFS_DIR)
|
if (kernfs_type(kn) == KERNFS_DIR)
|
||||||
kn->parent->dir.subdirs++;
|
kn->parent->dir.subdirs++;
|
||||||
|
kernfs_inc_rev(kn->parent);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -394,6 +395,7 @@ static bool kernfs_unlink_sibling(struct kernfs_node *kn)
|
|||||||
|
|
||||||
if (kernfs_type(kn) == KERNFS_DIR)
|
if (kernfs_type(kn) == KERNFS_DIR)
|
||||||
kn->parent->dir.subdirs--;
|
kn->parent->dir.subdirs--;
|
||||||
|
kernfs_inc_rev(kn->parent);
|
||||||
|
|
||||||
rb_erase(&kn->rb, &kn->parent->dir.children);
|
rb_erase(&kn->rb, &kn->parent->dir.children);
|
||||||
RB_CLEAR_NODE(&kn->rb);
|
RB_CLEAR_NODE(&kn->rb);
|
||||||
|
@ -81,6 +81,25 @@ static inline struct kernfs_node *kernfs_dentry_node(struct dentry *dentry)
|
|||||||
return d_inode(dentry)->i_private;
|
return d_inode(dentry)->i_private;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void kernfs_set_rev(struct kernfs_node *parent,
|
||||||
|
struct dentry *dentry)
|
||||||
|
{
|
||||||
|
dentry->d_time = parent->dir.rev;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void kernfs_inc_rev(struct kernfs_node *parent)
|
||||||
|
{
|
||||||
|
parent->dir.rev++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool kernfs_dir_changed(struct kernfs_node *parent,
|
||||||
|
struct dentry *dentry)
|
||||||
|
{
|
||||||
|
if (parent->dir.rev != dentry->d_time)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
extern const struct super_operations kernfs_sops;
|
extern const struct super_operations kernfs_sops;
|
||||||
extern struct kmem_cache *kernfs_node_cache, *kernfs_iattrs_cache;
|
extern struct kmem_cache *kernfs_node_cache, *kernfs_iattrs_cache;
|
||||||
|
|
||||||
|
@ -98,6 +98,11 @@ struct kernfs_elem_dir {
|
|||||||
* better directly in kernfs_node but is here to save space.
|
* better directly in kernfs_node but is here to save space.
|
||||||
*/
|
*/
|
||||||
struct kernfs_root *root;
|
struct kernfs_root *root;
|
||||||
|
/*
|
||||||
|
* Monotonic revision counter, used to identify if a directory
|
||||||
|
* node has changed during negative dentry revalidation.
|
||||||
|
*/
|
||||||
|
unsigned long rev;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct kernfs_elem_symlink {
|
struct kernfs_elem_symlink {
|
||||||
|
Loading…
Reference in New Issue
Block a user