Loading fs/mount.h +4 −1 Original line number Diff line number Diff line Loading @@ -19,7 +19,6 @@ struct mount { #endif struct list_head mnt_mounts; /* list of children, anchored here */ struct list_head mnt_child; /* and going through their mnt_child */ /* yet to be moved - fsnotify ones go here */ const char *mnt_devname; /* Name of device e.g. /dev/dsk/hda1 */ struct list_head mnt_list; struct list_head mnt_expire; /* link in fs-specific expiry list */ Loading @@ -28,6 +27,10 @@ struct mount { struct list_head mnt_slave; /* slave list entry */ struct mount *mnt_master; /* slave is on master->mnt_slave_list */ struct mnt_namespace *mnt_ns; /* containing namespace */ #ifdef CONFIG_FSNOTIFY struct hlist_head mnt_fsnotify_marks; __u32 mnt_fsnotify_mask; #endif int mnt_id; /* mount identifier */ int mnt_group_id; /* peer group identifier */ int mnt_expiry_mark; /* true if marked for expiry */ Loading fs/namespace.c +22 −23 Original line number Diff line number Diff line Loading @@ -173,54 +173,53 @@ unsigned int mnt_get_count(struct mount *mnt) static struct mount *alloc_vfsmnt(const char *name) { struct mount *p = kmem_cache_zalloc(mnt_cache, GFP_KERNEL); if (p) { struct vfsmount *mnt = &p->mnt; struct mount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL); if (mnt) { int err; err = mnt_alloc_id(p); err = mnt_alloc_id(mnt); if (err) goto out_free_cache; if (name) { p->mnt_devname = kstrdup(name, GFP_KERNEL); if (!p->mnt_devname) mnt->mnt_devname = kstrdup(name, GFP_KERNEL); if (!mnt->mnt_devname) goto out_free_id; } #ifdef CONFIG_SMP p->mnt_pcp = alloc_percpu(struct mnt_pcp); if (!p->mnt_pcp) mnt->mnt_pcp = alloc_percpu(struct mnt_pcp); if (!mnt->mnt_pcp) goto out_free_devname; this_cpu_add(p->mnt_pcp->mnt_count, 1); this_cpu_add(mnt->mnt_pcp->mnt_count, 1); #else p->mnt_count = 1; p->mnt_writers = 0; mnt->mnt_count = 1; mnt->mnt_writers = 0; #endif INIT_LIST_HEAD(&p->mnt_hash); INIT_LIST_HEAD(&p->mnt_child); INIT_LIST_HEAD(&p->mnt_mounts); INIT_LIST_HEAD(&p->mnt_list); INIT_LIST_HEAD(&p->mnt_expire); INIT_LIST_HEAD(&p->mnt_share); INIT_LIST_HEAD(&p->mnt_slave_list); INIT_LIST_HEAD(&p->mnt_slave); INIT_LIST_HEAD(&mnt->mnt_hash); INIT_LIST_HEAD(&mnt->mnt_child); INIT_LIST_HEAD(&mnt->mnt_mounts); INIT_LIST_HEAD(&mnt->mnt_list); INIT_LIST_HEAD(&mnt->mnt_expire); INIT_LIST_HEAD(&mnt->mnt_share); INIT_LIST_HEAD(&mnt->mnt_slave_list); INIT_LIST_HEAD(&mnt->mnt_slave); #ifdef CONFIG_FSNOTIFY INIT_HLIST_HEAD(&mnt->mnt_fsnotify_marks); #endif } return p; return mnt; #ifdef CONFIG_SMP out_free_devname: kfree(p->mnt_devname); kfree(mnt->mnt_devname); #endif out_free_id: mnt_free_id(p); mnt_free_id(mnt); out_free_cache: kmem_cache_free(mnt_cache, p); kmem_cache_free(mnt_cache, mnt); return NULL; } Loading fs/notify/fanotify/fanotify_user.c +4 −2 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ #include <asm/ioctls.h> #include "../../mount.h" #define FANOTIFY_DEFAULT_MAX_EVENTS 16384 #define FANOTIFY_DEFAULT_MAX_MARKS 8192 #define FANOTIFY_DEFAULT_MAX_LISTENERS 128 Loading Loading @@ -546,7 +548,7 @@ static int fanotify_remove_vfsmount_mark(struct fsnotify_group *group, removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags); fsnotify_put_mark(fsn_mark); if (removed & mnt->mnt_fsnotify_mask) if (removed & real_mount(mnt)->mnt_fsnotify_mask) fsnotify_recalc_vfsmount_mask(mnt); return 0; Loading Loading @@ -623,7 +625,7 @@ static int fanotify_add_vfsmount_mark(struct fsnotify_group *group, } added = fanotify_mark_add_to_mask(fsn_mark, mask, flags); if (added & ~mnt->mnt_fsnotify_mask) if (added & ~real_mount(mnt)->mnt_fsnotify_mask) fsnotify_recalc_vfsmount_mask(mnt); err: fsnotify_put_mark(fsn_mark); Loading fs/notify/fsnotify.c +5 −4 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ #include <linux/fsnotify_backend.h> #include "fsnotify.h" #include "../mount.h" /* * Clear all of the marks on an inode when it is being evicted from core Loading Loading @@ -205,13 +206,13 @@ int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, struct fsnotify_mark *inode_mark = NULL, *vfsmount_mark = NULL; struct fsnotify_group *inode_group, *vfsmount_group; struct fsnotify_event *event = NULL; struct vfsmount *mnt; struct mount *mnt; int idx, ret = 0; /* global tests shouldn't care about events on child only the specific event */ __u32 test_mask = (mask & ~FS_EVENT_ON_CHILD); if (data_is == FSNOTIFY_EVENT_PATH) mnt = ((struct path *)data)->mnt; mnt = real_mount(((struct path *)data)->mnt); else mnt = NULL; Loading Loading @@ -262,11 +263,11 @@ int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, /* we didn't use the vfsmount_mark */ vfsmount_group = NULL; } else if (vfsmount_group > inode_group) { ret = send_to_group(to_tell, mnt, NULL, vfsmount_mark, mask, data, ret = send_to_group(to_tell, &mnt->mnt, NULL, vfsmount_mark, mask, data, data_is, cookie, file_name, &event); inode_group = NULL; } else { ret = send_to_group(to_tell, mnt, inode_mark, vfsmount_mark, ret = send_to_group(to_tell, &mnt->mnt, inode_mark, vfsmount_mark, mask, data, data_is, cookie, file_name, &event); } Loading fs/notify/vfsmount_mark.c +12 −7 Original line number Diff line number Diff line Loading @@ -28,15 +28,17 @@ #include <linux/fsnotify_backend.h> #include "fsnotify.h" #include "../mount.h" void fsnotify_clear_marks_by_mount(struct vfsmount *mnt) { struct fsnotify_mark *mark, *lmark; struct hlist_node *pos, *n; struct mount *m = real_mount(mnt); LIST_HEAD(free_list); spin_lock(&mnt->mnt_root->d_lock); hlist_for_each_entry_safe(mark, pos, n, &mnt->mnt_fsnotify_marks, m.m_list) { hlist_for_each_entry_safe(mark, pos, n, &m->mnt_fsnotify_marks, m.m_list) { list_add(&mark->m.free_m_list, &free_list); hlist_del_init_rcu(&mark->m.m_list); fsnotify_get_mark(mark); Loading @@ -59,15 +61,16 @@ void fsnotify_clear_vfsmount_marks_by_group(struct fsnotify_group *group) */ static void fsnotify_recalc_vfsmount_mask_locked(struct vfsmount *mnt) { struct mount *m = real_mount(mnt); struct fsnotify_mark *mark; struct hlist_node *pos; __u32 new_mask = 0; assert_spin_locked(&mnt->mnt_root->d_lock); hlist_for_each_entry(mark, pos, &mnt->mnt_fsnotify_marks, m.m_list) hlist_for_each_entry(mark, pos, &m->mnt_fsnotify_marks, m.m_list) new_mask |= mark->mask; mnt->mnt_fsnotify_mask = new_mask; m->mnt_fsnotify_mask = new_mask; } /* Loading Loading @@ -101,12 +104,13 @@ void fsnotify_destroy_vfsmount_mark(struct fsnotify_mark *mark) static struct fsnotify_mark *fsnotify_find_vfsmount_mark_locked(struct fsnotify_group *group, struct vfsmount *mnt) { struct mount *m = real_mount(mnt); struct fsnotify_mark *mark; struct hlist_node *pos; assert_spin_locked(&mnt->mnt_root->d_lock); hlist_for_each_entry(mark, pos, &mnt->mnt_fsnotify_marks, m.m_list) { hlist_for_each_entry(mark, pos, &m->mnt_fsnotify_marks, m.m_list) { if (mark->group == group) { fsnotify_get_mark(mark); return mark; Loading Loading @@ -140,6 +144,7 @@ int fsnotify_add_vfsmount_mark(struct fsnotify_mark *mark, struct fsnotify_group *group, struct vfsmount *mnt, int allow_dups) { struct mount *m = real_mount(mnt); struct fsnotify_mark *lmark; struct hlist_node *node, *last = NULL; int ret = 0; Loading @@ -154,13 +159,13 @@ int fsnotify_add_vfsmount_mark(struct fsnotify_mark *mark, mark->m.mnt = mnt; /* is mark the first mark? */ if (hlist_empty(&mnt->mnt_fsnotify_marks)) { hlist_add_head_rcu(&mark->m.m_list, &mnt->mnt_fsnotify_marks); if (hlist_empty(&m->mnt_fsnotify_marks)) { hlist_add_head_rcu(&mark->m.m_list, &m->mnt_fsnotify_marks); goto out; } /* should mark be in the middle of the current list? */ hlist_for_each_entry(lmark, node, &mnt->mnt_fsnotify_marks, m.m_list) { hlist_for_each_entry(lmark, node, &m->mnt_fsnotify_marks, m.m_list) { last = node; if ((lmark->group == group) && !allow_dups) { Loading Loading
fs/mount.h +4 −1 Original line number Diff line number Diff line Loading @@ -19,7 +19,6 @@ struct mount { #endif struct list_head mnt_mounts; /* list of children, anchored here */ struct list_head mnt_child; /* and going through their mnt_child */ /* yet to be moved - fsnotify ones go here */ const char *mnt_devname; /* Name of device e.g. /dev/dsk/hda1 */ struct list_head mnt_list; struct list_head mnt_expire; /* link in fs-specific expiry list */ Loading @@ -28,6 +27,10 @@ struct mount { struct list_head mnt_slave; /* slave list entry */ struct mount *mnt_master; /* slave is on master->mnt_slave_list */ struct mnt_namespace *mnt_ns; /* containing namespace */ #ifdef CONFIG_FSNOTIFY struct hlist_head mnt_fsnotify_marks; __u32 mnt_fsnotify_mask; #endif int mnt_id; /* mount identifier */ int mnt_group_id; /* peer group identifier */ int mnt_expiry_mark; /* true if marked for expiry */ Loading
fs/namespace.c +22 −23 Original line number Diff line number Diff line Loading @@ -173,54 +173,53 @@ unsigned int mnt_get_count(struct mount *mnt) static struct mount *alloc_vfsmnt(const char *name) { struct mount *p = kmem_cache_zalloc(mnt_cache, GFP_KERNEL); if (p) { struct vfsmount *mnt = &p->mnt; struct mount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL); if (mnt) { int err; err = mnt_alloc_id(p); err = mnt_alloc_id(mnt); if (err) goto out_free_cache; if (name) { p->mnt_devname = kstrdup(name, GFP_KERNEL); if (!p->mnt_devname) mnt->mnt_devname = kstrdup(name, GFP_KERNEL); if (!mnt->mnt_devname) goto out_free_id; } #ifdef CONFIG_SMP p->mnt_pcp = alloc_percpu(struct mnt_pcp); if (!p->mnt_pcp) mnt->mnt_pcp = alloc_percpu(struct mnt_pcp); if (!mnt->mnt_pcp) goto out_free_devname; this_cpu_add(p->mnt_pcp->mnt_count, 1); this_cpu_add(mnt->mnt_pcp->mnt_count, 1); #else p->mnt_count = 1; p->mnt_writers = 0; mnt->mnt_count = 1; mnt->mnt_writers = 0; #endif INIT_LIST_HEAD(&p->mnt_hash); INIT_LIST_HEAD(&p->mnt_child); INIT_LIST_HEAD(&p->mnt_mounts); INIT_LIST_HEAD(&p->mnt_list); INIT_LIST_HEAD(&p->mnt_expire); INIT_LIST_HEAD(&p->mnt_share); INIT_LIST_HEAD(&p->mnt_slave_list); INIT_LIST_HEAD(&p->mnt_slave); INIT_LIST_HEAD(&mnt->mnt_hash); INIT_LIST_HEAD(&mnt->mnt_child); INIT_LIST_HEAD(&mnt->mnt_mounts); INIT_LIST_HEAD(&mnt->mnt_list); INIT_LIST_HEAD(&mnt->mnt_expire); INIT_LIST_HEAD(&mnt->mnt_share); INIT_LIST_HEAD(&mnt->mnt_slave_list); INIT_LIST_HEAD(&mnt->mnt_slave); #ifdef CONFIG_FSNOTIFY INIT_HLIST_HEAD(&mnt->mnt_fsnotify_marks); #endif } return p; return mnt; #ifdef CONFIG_SMP out_free_devname: kfree(p->mnt_devname); kfree(mnt->mnt_devname); #endif out_free_id: mnt_free_id(p); mnt_free_id(mnt); out_free_cache: kmem_cache_free(mnt_cache, p); kmem_cache_free(mnt_cache, mnt); return NULL; } Loading
fs/notify/fanotify/fanotify_user.c +4 −2 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ #include <asm/ioctls.h> #include "../../mount.h" #define FANOTIFY_DEFAULT_MAX_EVENTS 16384 #define FANOTIFY_DEFAULT_MAX_MARKS 8192 #define FANOTIFY_DEFAULT_MAX_LISTENERS 128 Loading Loading @@ -546,7 +548,7 @@ static int fanotify_remove_vfsmount_mark(struct fsnotify_group *group, removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags); fsnotify_put_mark(fsn_mark); if (removed & mnt->mnt_fsnotify_mask) if (removed & real_mount(mnt)->mnt_fsnotify_mask) fsnotify_recalc_vfsmount_mask(mnt); return 0; Loading Loading @@ -623,7 +625,7 @@ static int fanotify_add_vfsmount_mark(struct fsnotify_group *group, } added = fanotify_mark_add_to_mask(fsn_mark, mask, flags); if (added & ~mnt->mnt_fsnotify_mask) if (added & ~real_mount(mnt)->mnt_fsnotify_mask) fsnotify_recalc_vfsmount_mask(mnt); err: fsnotify_put_mark(fsn_mark); Loading
fs/notify/fsnotify.c +5 −4 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ #include <linux/fsnotify_backend.h> #include "fsnotify.h" #include "../mount.h" /* * Clear all of the marks on an inode when it is being evicted from core Loading Loading @@ -205,13 +206,13 @@ int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, struct fsnotify_mark *inode_mark = NULL, *vfsmount_mark = NULL; struct fsnotify_group *inode_group, *vfsmount_group; struct fsnotify_event *event = NULL; struct vfsmount *mnt; struct mount *mnt; int idx, ret = 0; /* global tests shouldn't care about events on child only the specific event */ __u32 test_mask = (mask & ~FS_EVENT_ON_CHILD); if (data_is == FSNOTIFY_EVENT_PATH) mnt = ((struct path *)data)->mnt; mnt = real_mount(((struct path *)data)->mnt); else mnt = NULL; Loading Loading @@ -262,11 +263,11 @@ int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, /* we didn't use the vfsmount_mark */ vfsmount_group = NULL; } else if (vfsmount_group > inode_group) { ret = send_to_group(to_tell, mnt, NULL, vfsmount_mark, mask, data, ret = send_to_group(to_tell, &mnt->mnt, NULL, vfsmount_mark, mask, data, data_is, cookie, file_name, &event); inode_group = NULL; } else { ret = send_to_group(to_tell, mnt, inode_mark, vfsmount_mark, ret = send_to_group(to_tell, &mnt->mnt, inode_mark, vfsmount_mark, mask, data, data_is, cookie, file_name, &event); } Loading
fs/notify/vfsmount_mark.c +12 −7 Original line number Diff line number Diff line Loading @@ -28,15 +28,17 @@ #include <linux/fsnotify_backend.h> #include "fsnotify.h" #include "../mount.h" void fsnotify_clear_marks_by_mount(struct vfsmount *mnt) { struct fsnotify_mark *mark, *lmark; struct hlist_node *pos, *n; struct mount *m = real_mount(mnt); LIST_HEAD(free_list); spin_lock(&mnt->mnt_root->d_lock); hlist_for_each_entry_safe(mark, pos, n, &mnt->mnt_fsnotify_marks, m.m_list) { hlist_for_each_entry_safe(mark, pos, n, &m->mnt_fsnotify_marks, m.m_list) { list_add(&mark->m.free_m_list, &free_list); hlist_del_init_rcu(&mark->m.m_list); fsnotify_get_mark(mark); Loading @@ -59,15 +61,16 @@ void fsnotify_clear_vfsmount_marks_by_group(struct fsnotify_group *group) */ static void fsnotify_recalc_vfsmount_mask_locked(struct vfsmount *mnt) { struct mount *m = real_mount(mnt); struct fsnotify_mark *mark; struct hlist_node *pos; __u32 new_mask = 0; assert_spin_locked(&mnt->mnt_root->d_lock); hlist_for_each_entry(mark, pos, &mnt->mnt_fsnotify_marks, m.m_list) hlist_for_each_entry(mark, pos, &m->mnt_fsnotify_marks, m.m_list) new_mask |= mark->mask; mnt->mnt_fsnotify_mask = new_mask; m->mnt_fsnotify_mask = new_mask; } /* Loading Loading @@ -101,12 +104,13 @@ void fsnotify_destroy_vfsmount_mark(struct fsnotify_mark *mark) static struct fsnotify_mark *fsnotify_find_vfsmount_mark_locked(struct fsnotify_group *group, struct vfsmount *mnt) { struct mount *m = real_mount(mnt); struct fsnotify_mark *mark; struct hlist_node *pos; assert_spin_locked(&mnt->mnt_root->d_lock); hlist_for_each_entry(mark, pos, &mnt->mnt_fsnotify_marks, m.m_list) { hlist_for_each_entry(mark, pos, &m->mnt_fsnotify_marks, m.m_list) { if (mark->group == group) { fsnotify_get_mark(mark); return mark; Loading Loading @@ -140,6 +144,7 @@ int fsnotify_add_vfsmount_mark(struct fsnotify_mark *mark, struct fsnotify_group *group, struct vfsmount *mnt, int allow_dups) { struct mount *m = real_mount(mnt); struct fsnotify_mark *lmark; struct hlist_node *node, *last = NULL; int ret = 0; Loading @@ -154,13 +159,13 @@ int fsnotify_add_vfsmount_mark(struct fsnotify_mark *mark, mark->m.mnt = mnt; /* is mark the first mark? */ if (hlist_empty(&mnt->mnt_fsnotify_marks)) { hlist_add_head_rcu(&mark->m.m_list, &mnt->mnt_fsnotify_marks); if (hlist_empty(&m->mnt_fsnotify_marks)) { hlist_add_head_rcu(&mark->m.m_list, &m->mnt_fsnotify_marks); goto out; } /* should mark be in the middle of the current list? */ hlist_for_each_entry(lmark, node, &mnt->mnt_fsnotify_marks, m.m_list) { hlist_for_each_entry(lmark, node, &m->mnt_fsnotify_marks, m.m_list) { last = node; if ((lmark->group == group) && !allow_dups) { Loading