Skip to content

Commit

Permalink
Merge branch 'work.dcache' of git://git.kernel.org/pub/scm/linux/kern…
Browse files Browse the repository at this point in the history
…el/git/viro/vfs

Pull misc dcache updates from Al Viro:
 "Most of this pile is putting name length into struct name_snapshot and
  making use of it.

  The beginning of this series ("ovl_lookup_real_one(): don't bother
  with strlen()") ought to have been split in two (separate switch of
  name_snapshot to struct qstr from overlayfs reaping the trivial
  benefits of that), but I wanted to avoid a rebase - by the time I'd
  spotted that it was (a) in -next and (b) close to 5.1-final ;-/"

* 'work.dcache' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  audit_compare_dname_path(): switch to const struct qstr *
  audit_update_watch(): switch to const struct qstr *
  inotify_handle_event(): don't bother with strlen()
  fsnotify: switch send_to_group() and ->handle_event to const struct qstr *
  fsnotify(): switch to passing const struct qstr * for file_name
  switch fsnotify_move() to passing const struct qstr * for old_name
  ovl_lookup_real_one(): don't bother with strlen()
  sysv: bury the broken "quietly truncate the long filenames" logics
  nsfs: unobfuscate
  unexport d_alloc_pseudo()
  • Loading branch information
torvalds committed May 8, 2019
2 parents d3511f5 + 795d673 commit d27fb65
Show file tree
Hide file tree
Showing 25 changed files with 62 additions and 79 deletions.
5 changes: 5 additions & 0 deletions Documentation/filesystems/porting
Original file line number Diff line number Diff line change
Expand Up @@ -668,3 +668,8 @@ in your dentry operations instead.
DCACHE_RCUACCESS is gone; having an RCU delay on dentry freeing is the
default. DCACHE_NORCU opts out, and only d_alloc_pseudo() has any
business doing so.
--
[mandatory]
d_alloc_pseudo() is internal-only; uses outside of alloc_file_pseudo() are
very suspect (and won't work in modules). Such uses are very likely to
be misspelled d_alloc_anon().
18 changes: 9 additions & 9 deletions fs/dcache.c
Original file line number Diff line number Diff line change
Expand Up @@ -284,25 +284,23 @@ static inline int dname_external(const struct dentry *dentry)
void take_dentry_name_snapshot(struct name_snapshot *name, struct dentry *dentry)
{
spin_lock(&dentry->d_lock);
name->name = dentry->d_name;
if (unlikely(dname_external(dentry))) {
struct external_name *p = external_name(dentry);
atomic_inc(&p->u.count);
spin_unlock(&dentry->d_lock);
name->name = p->name;
atomic_inc(&external_name(dentry)->u.count);
} else {
memcpy(name->inline_name, dentry->d_iname,
dentry->d_name.len + 1);
spin_unlock(&dentry->d_lock);
name->name = name->inline_name;
name->name.name = name->inline_name;
}
spin_unlock(&dentry->d_lock);
}
EXPORT_SYMBOL(take_dentry_name_snapshot);

void release_dentry_name_snapshot(struct name_snapshot *name)
{
if (unlikely(name->name != name->inline_name)) {
if (unlikely(name->name.name != name->inline_name)) {
struct external_name *p;
p = container_of(name->name, struct external_name, name[0]);
p = container_of(name->name.name, struct external_name, name[0]);
if (unlikely(atomic_dec_and_test(&p->u.count)))
kfree_rcu(p, u.head);
}
Expand Down Expand Up @@ -1742,6 +1740,9 @@ struct dentry *d_alloc_cursor(struct dentry * parent)
* never be anyone's children or parents. Unlike all other
* dentries, these will not have RCU delay between dropping the
* last reference and freeing them.
*
* The only user is alloc_file_pseudo() and that's what should
* be considered a public interface. Don't use directly.
*/
struct dentry *d_alloc_pseudo(struct super_block *sb, const struct qstr *name)
{
Expand All @@ -1750,7 +1751,6 @@ struct dentry *d_alloc_pseudo(struct super_block *sb, const struct qstr *name)
dentry->d_flags |= DCACHE_NORCU;
return dentry;
}
EXPORT_SYMBOL(d_alloc_pseudo);

struct dentry *d_alloc_name(struct dentry *parent, const char *name)
{
Expand Down
2 changes: 1 addition & 1 deletion fs/debugfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -818,7 +818,7 @@ struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry,
goto exit;
}
d_move(old_dentry, dentry);
fsnotify_move(d_inode(old_dir), d_inode(new_dir), old_name.name,
fsnotify_move(d_inode(old_dir), d_inode(new_dir), &old_name.name,
d_is_dir(old_dentry),
NULL, old_dentry);
release_dentry_name_snapshot(&old_name);
Expand Down
1 change: 1 addition & 0 deletions fs/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ extern struct dentry *__d_alloc(struct super_block *, const struct qstr *);
extern int d_set_mounted(struct dentry *dentry);
extern long prune_dcache_sb(struct super_block *sb, struct shrink_control *sc);
extern struct dentry *d_alloc_cursor(struct dentry *);
extern struct dentry * d_alloc_pseudo(struct super_block *, const struct qstr *);

/*
* read_write.c
Expand Down
6 changes: 4 additions & 2 deletions fs/kernfs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -885,6 +885,7 @@ static void kernfs_notify_workfn(struct work_struct *work)
list_for_each_entry(info, &kernfs_root(kn)->supers, node) {
struct kernfs_node *parent;
struct inode *inode;
struct qstr name;

/*
* We want fsnotify_modify() on @kn but as the
Expand All @@ -896,22 +897,23 @@ static void kernfs_notify_workfn(struct work_struct *work)
if (!inode)
continue;

name = (struct qstr)QSTR_INIT(kn->name, strlen(kn->name));
parent = kernfs_get_parent(kn);
if (parent) {
struct inode *p_inode;

p_inode = ilookup(info->sb, parent->id.ino);
if (p_inode) {
fsnotify(p_inode, FS_MODIFY | FS_EVENT_ON_CHILD,
inode, FSNOTIFY_EVENT_INODE, kn->name, 0);
inode, FSNOTIFY_EVENT_INODE, &name, 0);
iput(p_inode);
}

kernfs_put(parent);
}

fsnotify(inode, FS_MODIFY, inode, FSNOTIFY_EVENT_INODE,
kn->name, 0);
&name, 0);
iput(inode);
}

Expand Down
4 changes: 2 additions & 2 deletions fs/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -4498,10 +4498,10 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
inode_unlock(target);
dput(new_dentry);
if (!error) {
fsnotify_move(old_dir, new_dir, old_name.name, is_dir,
fsnotify_move(old_dir, new_dir, &old_name.name, is_dir,
!(flags & RENAME_EXCHANGE) ? target : NULL, old_dentry);
if (flags & RENAME_EXCHANGE) {
fsnotify_move(new_dir, old_dir, old_dentry->d_name.name,
fsnotify_move(new_dir, old_dir, &old_dentry->d_name,
new_is_dir, NULL, new_dentry);
}
}
Expand Down
2 changes: 1 addition & 1 deletion fs/notify/dnotify/dnotify.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ static void dnotify_recalc_inode_mask(struct fsnotify_mark *fsn_mark)
static int dnotify_handle_event(struct fsnotify_group *group,
struct inode *inode,
u32 mask, const void *data, int data_type,
const unsigned char *file_name, u32 cookie,
const struct qstr *file_name, u32 cookie,
struct fsnotify_iter_info *iter_info)
{
struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info);
Expand Down
2 changes: 1 addition & 1 deletion fs/notify/fanotify/fanotify.c
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ static __kernel_fsid_t fanotify_get_fsid(struct fsnotify_iter_info *iter_info)
static int fanotify_handle_event(struct fsnotify_group *group,
struct inode *inode,
u32 mask, const void *data, int data_type,
const unsigned char *file_name, u32 cookie,
const struct qstr *file_name, u32 cookie,
struct fsnotify_iter_info *iter_info)
{
int ret = 0;
Expand Down
8 changes: 4 additions & 4 deletions fs/notify/fsnotify.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,10 +179,10 @@ int __fsnotify_parent(const struct path *path, struct dentry *dentry, __u32 mask
take_dentry_name_snapshot(&name, dentry);
if (path)
ret = fsnotify(p_inode, mask, path, FSNOTIFY_EVENT_PATH,
name.name, 0);
&name.name, 0);
else
ret = fsnotify(p_inode, mask, dentry->d_inode, FSNOTIFY_EVENT_INODE,
name.name, 0);
&name.name, 0);
release_dentry_name_snapshot(&name);
}

Expand All @@ -195,7 +195,7 @@ EXPORT_SYMBOL_GPL(__fsnotify_parent);
static int send_to_group(struct inode *to_tell,
__u32 mask, const void *data,
int data_is, u32 cookie,
const unsigned char *file_name,
const struct qstr *file_name,
struct fsnotify_iter_info *iter_info)
{
struct fsnotify_group *group = NULL;
Expand Down Expand Up @@ -325,7 +325,7 @@ static void fsnotify_iter_next(struct fsnotify_iter_info *iter_info)
* notification event in whatever means they feel necessary.
*/
int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is,
const unsigned char *file_name, u32 cookie)
const struct qstr *file_name, u32 cookie)
{
struct fsnotify_iter_info iter_info = {};
struct super_block *sb = to_tell->i_sb;
Expand Down
2 changes: 1 addition & 1 deletion fs/notify/inotify/inotify.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ extern void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark,
extern int inotify_handle_event(struct fsnotify_group *group,
struct inode *inode,
u32 mask, const void *data, int data_type,
const unsigned char *file_name, u32 cookie,
const struct qstr *file_name, u32 cookie,
struct fsnotify_iter_info *iter_info);

extern const struct fsnotify_ops inotify_fsnotify_ops;
Expand Down
6 changes: 3 additions & 3 deletions fs/notify/inotify/inotify_fsnotify.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ static int inotify_merge(struct list_head *list,
int inotify_handle_event(struct fsnotify_group *group,
struct inode *inode,
u32 mask, const void *data, int data_type,
const unsigned char *file_name, u32 cookie,
const struct qstr *file_name, u32 cookie,
struct fsnotify_iter_info *iter_info)
{
struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info);
Expand All @@ -89,7 +89,7 @@ int inotify_handle_event(struct fsnotify_group *group,
return 0;
}
if (file_name) {
len = strlen(file_name);
len = file_name->len;
alloc_len += len + 1;
}

Expand Down Expand Up @@ -129,7 +129,7 @@ int inotify_handle_event(struct fsnotify_group *group,
event->sync_cookie = cookie;
event->name_len = len;
if (len)
strcpy(event->name, file_name);
strcpy(event->name, file_name->name);

ret = fsnotify_add_event(group, fsn_event, inotify_merge);
if (ret) {
Expand Down
23 changes: 10 additions & 13 deletions fs/nsfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,17 +105,16 @@ static void *__ns_get_path(struct path *path, struct ns_common *ns)
void *ns_get_path_cb(struct path *path, ns_get_path_helper_t *ns_get_cb,
void *private_data)
{
struct ns_common *ns;
void *ret;

again:
ns = ns_get_cb(private_data);
if (!ns)
return ERR_PTR(-ENOENT);
do {
struct ns_common *ns = ns_get_cb(private_data);
if (!ns)
return ERR_PTR(-ENOENT);

ret = __ns_get_path(path, ns);
} while (ret == ERR_PTR(-EAGAIN));

ret = __ns_get_path(path, ns);
if (IS_ERR(ret) && PTR_ERR(ret) == -EAGAIN)
goto again;
return ret;
}

Expand Down Expand Up @@ -154,7 +153,7 @@ int open_related_ns(struct ns_common *ns,
if (fd < 0)
return fd;

while (1) {
do {
struct ns_common *relative;

relative = get_ns(ns);
Expand All @@ -164,10 +163,8 @@ int open_related_ns(struct ns_common *ns,
}

err = __ns_get_path(&path, relative);
if (IS_ERR(err) && PTR_ERR(err) == -EAGAIN)
continue;
break;
}
} while (err == ERR_PTR(-EAGAIN));

if (IS_ERR(err)) {
put_unused_fd(fd);
return PTR_ERR(err);
Expand Down
2 changes: 1 addition & 1 deletion fs/overlayfs/export.c
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ static struct dentry *ovl_lookup_real_one(struct dentry *connected,
* pointer because we hold no lock on the real dentry.
*/
take_dentry_name_snapshot(&name, real);
this = lookup_one_len(name.name, connected, strlen(name.name));
this = lookup_one_len(name.name.name, connected, name.name.len);
err = PTR_ERR(this);
if (IS_ERR(this)) {
goto fail;
Expand Down
15 changes: 0 additions & 15 deletions fs/sysv/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,6 @@ static int add_nondir(struct dentry *dentry, struct inode *inode)
return err;
}

static int sysv_hash(const struct dentry *dentry, struct qstr *qstr)
{
/* Truncate the name in place, avoids having to define a compare
function. */
if (qstr->len > SYSV_NAMELEN) {
qstr->len = SYSV_NAMELEN;
qstr->hash = full_name_hash(dentry, qstr->name, qstr->len);
}
return 0;
}

const struct dentry_operations sysv_dentry_operations = {
.d_hash = sysv_hash,
};

static struct dentry *sysv_lookup(struct inode * dir, struct dentry * dentry, unsigned int flags)
{
struct inode * inode = NULL;
Expand Down
3 changes: 0 additions & 3 deletions fs/sysv/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,6 @@ static int complete_read_super(struct super_block *sb, int silent, int size)

flavour_setup[sbi->s_type](sbi, &sb->s_max_links);

sbi->s_truncate = 1;
sbi->s_ndatazones = sbi->s_nzones - sbi->s_firstdatazone;
sbi->s_inodes_per_block = bsize >> 6;
sbi->s_inodes_per_block_1 = (bsize >> 6)-1;
Expand All @@ -334,8 +333,6 @@ static int complete_read_super(struct super_block *sb, int silent, int size)
sb->s_op = &sysv_sops;
if (sbi->s_forced_ro)
sb->s_flags |= SB_RDONLY;
if (sbi->s_truncate)
sb->s_d_op = &sysv_dentry_operations;
root_inode = sysv_iget(sb, SYSV_ROOT_INO);
if (IS_ERR(root_inode)) {
printk("SysV FS: get root inode failed\n");
Expand Down
3 changes: 0 additions & 3 deletions fs/sysv/sysv.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ struct sysv_sb_info {
struct super_block *s_sb; /* VFS superblock */
int s_type; /* file system type: FSTYPE_{XENIX|SYSV|COH} */
char s_bytesex; /* bytesex (le/be/pdp) */
char s_truncate; /* if 1: names > SYSV_NAMELEN chars are truncated */
/* if 0: they are disallowed (ENAMETOOLONG) */
unsigned int s_inodes_per_block; /* number of inodes per block */
unsigned int s_inodes_per_block_1; /* inodes_per_block - 1 */
unsigned int s_inodes_per_block_bits; /* log2(inodes_per_block) */
Expand Down Expand Up @@ -166,7 +164,6 @@ extern const struct file_operations sysv_file_operations;
extern const struct file_operations sysv_dir_operations;
extern const struct address_space_operations sysv_aops;
extern const struct super_operations sysv_sops;
extern const struct dentry_operations sysv_dentry_operations;


enum {
Expand Down
3 changes: 1 addition & 2 deletions include/linux/dcache.h
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,6 @@ extern void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op
/* allocate/de-allocate */
extern struct dentry * d_alloc(struct dentry *, const struct qstr *);
extern struct dentry * d_alloc_anon(struct super_block *);
extern struct dentry * d_alloc_pseudo(struct super_block *, const struct qstr *);
extern struct dentry * d_alloc_parallel(struct dentry *, const struct qstr *,
wait_queue_head_t *);
extern struct dentry * d_splice_alias(struct inode *, struct dentry *);
Expand Down Expand Up @@ -594,7 +593,7 @@ static inline struct inode *d_real_inode(const struct dentry *dentry)
}

struct name_snapshot {
const unsigned char *name;
struct qstr name;
unsigned char inline_name[DNAME_INLINE_LEN];
};
void take_dentry_name_snapshot(struct name_snapshot *, struct dentry *);
Expand Down
10 changes: 5 additions & 5 deletions include/linux/fsnotify.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ static inline int fsnotify_dirent(struct inode *dir, struct dentry *dentry,
__u32 mask)
{
return fsnotify(dir, mask, d_inode(dentry), FSNOTIFY_EVENT_INODE,
dentry->d_name.name, 0);
&dentry->d_name, 0);
}

/* Notify this dentry's parent about a child's events. */
Expand Down Expand Up @@ -102,7 +102,7 @@ static inline void fsnotify_link_count(struct inode *inode)
* fsnotify_move - file old_name at old_dir was moved to new_name at new_dir
*/
static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
const unsigned char *old_name,
const struct qstr *old_name,
int isdir, struct inode *target,
struct dentry *moved)
{
Expand All @@ -111,7 +111,7 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
__u32 old_dir_mask = FS_MOVED_FROM;
__u32 new_dir_mask = FS_MOVED_TO;
__u32 mask = FS_MOVE_SELF;
const unsigned char *new_name = moved->d_name.name;
const struct qstr *new_name = &moved->d_name;

if (old_dir == new_dir)
old_dir_mask |= FS_DN_RENAME;
Expand Down Expand Up @@ -178,7 +178,7 @@ static inline void fsnotify_nameremove(struct dentry *dentry, int isdir)
take_dentry_name_snapshot(&name, dentry);

fsnotify(d_inode(parent), mask, d_inode(dentry), FSNOTIFY_EVENT_INODE,
name.name, 0);
&name.name, 0);

release_dentry_name_snapshot(&name);
dput(parent);
Expand Down Expand Up @@ -218,7 +218,7 @@ static inline void fsnotify_link(struct inode *dir, struct inode *inode, struct
fsnotify_link_count(inode);
audit_inode_child(dir, new_dentry, AUDIT_TYPE_CHILD_CREATE);

fsnotify(dir, FS_CREATE, inode, FSNOTIFY_EVENT_INODE, new_dentry->d_name.name, 0);
fsnotify(dir, FS_CREATE, inode, FSNOTIFY_EVENT_INODE, &new_dentry->d_name, 0);
}

/*
Expand Down
Loading

0 comments on commit d27fb65

Please sign in to comment.