Skip to content

Commit

Permalink
Merge branch 'fsnotify' of git://git.kernel.org/pub/scm/linux/kernel/…
Browse files Browse the repository at this point in the history
…git/jack/linux-fs

Pull fsnotify updates from Jan Kara:
 "The branch contains mainly a rework of fsnotify infrastructure fixing
  a shortcoming that we have waited for response to fanotify permission
  events with SRCU read lock held and when the process consuming events
  was slow to respond the kernel has stalled.

  It also contains several cleanups of unnecessary indirections in
  fsnotify framework and a bugfix from Amir fixing leakage of kernel
  internal errno to userspace"

* 'fsnotify' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs: (37 commits)
  fanotify: don't expose EOPENSTALE to userspace
  fsnotify: remove a stray unlock
  fsnotify: Move ->free_mark callback to fsnotify_ops
  fsnotify: Add group pointer in fsnotify_init_mark()
  fsnotify: Drop inode_mark.c
  fsnotify: Remove fsnotify_find_{inode|vfsmount}_mark()
  fsnotify: Remove fsnotify_detach_group_marks()
  fsnotify: Rename fsnotify_clear_marks_by_group_flags()
  fsnotify: Inline fsnotify_clear_{inode|vfsmount}_mark_group()
  fsnotify: Remove fsnotify_recalc_{inode|vfsmount}_mask()
  fsnotify: Remove fsnotify_set_mark_{,ignored_}mask_locked()
  fanotify: Release SRCU lock when waiting for userspace response
  fsnotify: Pass fsnotify_iter_info into handle_event handler
  fsnotify: Provide framework for dropping SRCU lock in ->handle_event
  fsnotify: Remove special handling of mark destruction on group shutdown
  fsnotify: Detach mark from object list when last reference is dropped
  fsnotify: Move queueing of mark for destruction into fsnotify_put_mark()
  inotify: Do not drop mark reference under idr_lock
  fsnotify: Free fsnotify_mark_connector when there is no mark attached
  fsnotify: Lock object list with connector lock
  ...
  • Loading branch information
torvalds committed May 3, 2017
2 parents 7b66f13 + 4ff33aa commit 5133cd7
Show file tree
Hide file tree
Showing 24 changed files with 815 additions and 771 deletions.
3 changes: 0 additions & 3 deletions fs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -371,9 +371,6 @@ void inode_init_once(struct inode *inode)
INIT_LIST_HEAD(&inode->i_lru);
address_space_init_once(&inode->i_data);
i_size_ordered_init(inode);
#ifdef CONFIG_FSNOTIFY
INIT_HLIST_HEAD(&inode->i_fsnotify_marks);
#endif
}
EXPORT_SYMBOL(inode_init_once);

Expand Down
2 changes: 1 addition & 1 deletion fs/mount.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ struct mount {
struct mountpoint *mnt_mp; /* where is it mounted */
struct hlist_node mnt_mp_list; /* list mounts with the same mountpoint */
#ifdef CONFIG_FSNOTIFY
struct hlist_head mnt_fsnotify_marks;
struct fsnotify_mark_connector __rcu *mnt_fsnotify_marks;
__u32 mnt_fsnotify_mask;
#endif
int mnt_id; /* mount identifier */
Expand Down
3 changes: 0 additions & 3 deletions fs/namespace.c
Original file line number Diff line number Diff line change
Expand Up @@ -236,9 +236,6 @@ static struct mount *alloc_vfsmnt(const char *name)
INIT_LIST_HEAD(&mnt->mnt_slave_list);
INIT_LIST_HEAD(&mnt->mnt_slave);
INIT_HLIST_NODE(&mnt->mnt_mp_list);
#ifdef CONFIG_FSNOTIFY
INIT_HLIST_HEAD(&mnt->mnt_fsnotify_marks);
#endif
init_fs_pin(&mnt->mnt_umount, drop_mountpoint);
}
return mnt;
Expand Down
4 changes: 2 additions & 2 deletions fs/notify/Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
obj-$(CONFIG_FSNOTIFY) += fsnotify.o notification.o group.o inode_mark.o \
mark.o vfsmount_mark.o fdinfo.o
obj-$(CONFIG_FSNOTIFY) += fsnotify.o notification.o group.o mark.o \
fdinfo.o

obj-y += dnotify/
obj-y += inotify/
Expand Down
25 changes: 11 additions & 14 deletions fs/notify/dnotify/dnotify.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,25 +52,21 @@ struct dnotify_mark {
*/
static void dnotify_recalc_inode_mask(struct fsnotify_mark *fsn_mark)
{
__u32 new_mask, old_mask;
__u32 new_mask = 0;
struct dnotify_struct *dn;
struct dnotify_mark *dn_mark = container_of(fsn_mark,
struct dnotify_mark,
fsn_mark);

assert_spin_locked(&fsn_mark->lock);

old_mask = fsn_mark->mask;
new_mask = 0;
for (dn = dn_mark->dn; dn != NULL; dn = dn->dn_next)
new_mask |= (dn->dn_mask & ~FS_DN_MULTISHOT);
fsnotify_set_mark_mask_locked(fsn_mark, new_mask);

if (old_mask == new_mask)
if (fsn_mark->mask == new_mask)
return;
fsn_mark->mask = new_mask;

if (fsn_mark->inode)
fsnotify_recalc_inode_mask(fsn_mark->inode);
fsnotify_recalc_mask(fsn_mark->connector);
}

/*
Expand All @@ -86,7 +82,8 @@ static int dnotify_handle_event(struct fsnotify_group *group,
struct fsnotify_mark *inode_mark,
struct fsnotify_mark *vfsmount_mark,
u32 mask, const void *data, int data_type,
const unsigned char *file_name, u32 cookie)
const unsigned char *file_name, u32 cookie,
struct fsnotify_iter_info *iter_info)
{
struct dnotify_mark *dn_mark;
struct dnotify_struct *dn;
Expand Down Expand Up @@ -138,6 +135,7 @@ static void dnotify_free_mark(struct fsnotify_mark *fsn_mark)

static struct fsnotify_ops dnotify_fsnotify_ops = {
.handle_event = dnotify_handle_event,
.free_mark = dnotify_free_mark,
};

/*
Expand All @@ -160,7 +158,7 @@ void dnotify_flush(struct file *filp, fl_owner_t id)
if (!S_ISDIR(inode->i_mode))
return;

fsn_mark = fsnotify_find_inode_mark(dnotify_group, inode);
fsn_mark = fsnotify_find_mark(&inode->i_fsnotify_marks, dnotify_group);
if (!fsn_mark)
return;
dn_mark = container_of(fsn_mark, struct dnotify_mark, fsn_mark);
Expand Down Expand Up @@ -308,21 +306,20 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg)

/* set up the new_fsn_mark and new_dn_mark */
new_fsn_mark = &new_dn_mark->fsn_mark;
fsnotify_init_mark(new_fsn_mark, dnotify_free_mark);
fsnotify_init_mark(new_fsn_mark, dnotify_group);
new_fsn_mark->mask = mask;
new_dn_mark->dn = NULL;

/* this is needed to prevent the fcntl/close race described below */
mutex_lock(&dnotify_group->mark_mutex);

/* add the new_fsn_mark or find an old one. */
fsn_mark = fsnotify_find_inode_mark(dnotify_group, inode);
fsn_mark = fsnotify_find_mark(&inode->i_fsnotify_marks, dnotify_group);
if (fsn_mark) {
dn_mark = container_of(fsn_mark, struct dnotify_mark, fsn_mark);
spin_lock(&fsn_mark->lock);
} else {
fsnotify_add_mark_locked(new_fsn_mark, dnotify_group, inode,
NULL, 0);
fsnotify_add_mark_locked(new_fsn_mark, inode, NULL, 0);
spin_lock(&new_fsn_mark->lock);
fsn_mark = new_fsn_mark;
dn_mark = new_dn_mark;
Expand Down
26 changes: 23 additions & 3 deletions fs/notify/fanotify/fanotify.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,26 @@ static int fanotify_merge(struct list_head *list, struct fsnotify_event *event)

#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
static int fanotify_get_response(struct fsnotify_group *group,
struct fanotify_perm_event_info *event)
struct fanotify_perm_event_info *event,
struct fsnotify_iter_info *iter_info)
{
int ret;

pr_debug("%s: group=%p event=%p\n", __func__, group, event);

/*
* fsnotify_prepare_user_wait() fails if we race with mark deletion.
* Just let the operation pass in that case.
*/
if (!fsnotify_prepare_user_wait(iter_info)) {
event->response = FAN_ALLOW;
goto out;
}

wait_event(group->fanotify_data.access_waitq, event->response);

fsnotify_finish_user_wait(iter_info);
out:
/* userspace responded, convert to something usable */
switch (event->response) {
case FAN_ALLOW:
Expand Down Expand Up @@ -174,7 +186,8 @@ static int fanotify_handle_event(struct fsnotify_group *group,
struct fsnotify_mark *inode_mark,
struct fsnotify_mark *fanotify_mark,
u32 mask, const void *data, int data_type,
const unsigned char *file_name, u32 cookie)
const unsigned char *file_name, u32 cookie,
struct fsnotify_iter_info *iter_info)
{
int ret = 0;
struct fanotify_event_info *event;
Expand Down Expand Up @@ -215,7 +228,8 @@ static int fanotify_handle_event(struct fsnotify_group *group,

#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
if (mask & FAN_ALL_PERM_EVENTS) {
ret = fanotify_get_response(group, FANOTIFY_PE(fsn_event));
ret = fanotify_get_response(group, FANOTIFY_PE(fsn_event),
iter_info);
fsnotify_destroy_event(group, fsn_event);
}
#endif
Expand Down Expand Up @@ -248,8 +262,14 @@ static void fanotify_free_event(struct fsnotify_event *fsn_event)
kmem_cache_free(fanotify_event_cachep, event);
}

static void fanotify_free_mark(struct fsnotify_mark *fsn_mark)
{
kmem_cache_free(fanotify_mark_cache, fsn_mark);
}

const struct fsnotify_ops fanotify_fsnotify_ops = {
.handle_event = fanotify_handle_event,
.free_group_priv = fanotify_free_group_priv,
.free_event = fanotify_free_event,
.free_mark = fanotify_free_mark,
};
1 change: 1 addition & 0 deletions fs/notify/fanotify/fanotify.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <linux/path.h>
#include <linux/slab.h>

extern struct kmem_cache *fanotify_mark_cache;
extern struct kmem_cache *fanotify_event_cachep;
extern struct kmem_cache *fanotify_perm_event_cachep;

Expand Down
Loading

0 comments on commit 5133cd7

Please sign in to comment.