summaryrefslogtreecommitdiff
path: root/fs/notify
diff options
context:
space:
mode:
Diffstat (limited to 'fs/notify')
-rw-r--r--fs/notify/fanotify/fanotify.c19
-rw-r--r--fs/notify/fanotify/fanotify.h10
-rw-r--r--fs/notify/fanotify/fanotify_user.c18
-rw-r--r--fs/notify/mark.c52
4 files changed, 37 insertions, 62 deletions
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index 9dac7f6e72d2..aff1ab3c32aa 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -838,9 +838,8 @@ out:
}
/*
- * Get cached fsid of the filesystem containing the object from any connector.
- * All connectors are supposed to have the same fsid, but we do not verify that
- * here.
+ * Get cached fsid of the filesystem containing the object from any mark.
+ * All marks are supposed to have the same fsid, but we do not verify that here.
*/
static __kernel_fsid_t fanotify_get_fsid(struct fsnotify_iter_info *iter_info)
{
@@ -849,17 +848,9 @@ static __kernel_fsid_t fanotify_get_fsid(struct fsnotify_iter_info *iter_info)
__kernel_fsid_t fsid = {};
fsnotify_foreach_iter_mark_type(iter_info, mark, type) {
- struct fsnotify_mark_connector *conn;
-
- conn = READ_ONCE(mark->connector);
- /* Mark is just getting destroyed or created? */
- if (!conn)
- continue;
- if (!(conn->flags & FSNOTIFY_CONN_FLAG_HAS_FSID))
+ if (!(mark->flags & FSNOTIFY_MARK_FLAG_HAS_FSID))
continue;
- /* Pairs with smp_wmb() in fsnotify_add_mark_list() */
- smp_rmb();
- fsid = conn->fsid;
+ fsid = FANOTIFY_MARK(mark)->fsid;
if (WARN_ON_ONCE(!fsid.val[0] && !fsid.val[1]))
continue;
return fsid;
@@ -1068,7 +1059,7 @@ static void fanotify_freeing_mark(struct fsnotify_mark *mark,
static void fanotify_free_mark(struct fsnotify_mark *fsn_mark)
{
- kmem_cache_free(fanotify_mark_cache, fsn_mark);
+ kmem_cache_free(fanotify_mark_cache, FANOTIFY_MARK(fsn_mark));
}
const struct fsnotify_ops fanotify_fsnotify_ops = {
diff --git a/fs/notify/fanotify/fanotify.h b/fs/notify/fanotify/fanotify.h
index 6936671e148d..f3b9ef60f0c0 100644
--- a/fs/notify/fanotify/fanotify.h
+++ b/fs/notify/fanotify/fanotify.h
@@ -489,6 +489,16 @@ static inline unsigned int fanotify_event_hash_bucket(
return event->hash & FANOTIFY_HTABLE_MASK;
}
+struct fanotify_mark {
+ struct fsnotify_mark fsn_mark;
+ __kernel_fsid_t fsid;
+};
+
+static inline struct fanotify_mark *FANOTIFY_MARK(struct fsnotify_mark *mark)
+{
+ return container_of(mark, struct fanotify_mark, fsn_mark);
+}
+
static inline unsigned int fanotify_mark_user_flags(struct fsnotify_mark *mark)
{
unsigned int mflags = 0;
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index 4d765c72496f..e3d836d4d156 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -1199,6 +1199,7 @@ static struct fsnotify_mark *fanotify_add_new_mark(struct fsnotify_group *group,
__kernel_fsid_t *fsid)
{
struct ucounts *ucounts = group->fanotify_data.ucounts;
+ struct fanotify_mark *fan_mark;
struct fsnotify_mark *mark;
int ret;
@@ -1211,17 +1212,26 @@ static struct fsnotify_mark *fanotify_add_new_mark(struct fsnotify_group *group,
!inc_ucount(ucounts->ns, ucounts->uid, UCOUNT_FANOTIFY_MARKS))
return ERR_PTR(-ENOSPC);
- mark = kmem_cache_alloc(fanotify_mark_cache, GFP_KERNEL);
- if (!mark) {
+ fan_mark = kmem_cache_alloc(fanotify_mark_cache, GFP_KERNEL);
+ if (!fan_mark) {
ret = -ENOMEM;
goto out_dec_ucounts;
}
+ mark = &fan_mark->fsn_mark;
fsnotify_init_mark(mark, group);
if (fan_flags & FAN_MARK_EVICTABLE)
mark->flags |= FSNOTIFY_MARK_FLAG_NO_IREF;
- ret = fsnotify_add_mark_locked(mark, connp, obj_type, 0, fsid);
+ /* Cache fsid of filesystem containing the marked object */
+ if (fsid) {
+ fan_mark->fsid = *fsid;
+ mark->flags |= FSNOTIFY_MARK_FLAG_HAS_FSID;
+ } else {
+ fan_mark->fsid.val[0] = fan_mark->fsid.val[1] = 0;
+ }
+
+ ret = fsnotify_add_mark_locked(mark, connp, obj_type, 0);
if (ret) {
fsnotify_put_mark(mark);
goto out_dec_ucounts;
@@ -1935,7 +1945,7 @@ static int __init fanotify_user_setup(void)
BUILD_BUG_ON(HWEIGHT32(FANOTIFY_INIT_FLAGS) != 12);
BUILD_BUG_ON(HWEIGHT32(FANOTIFY_MARK_FLAGS) != 11);
- fanotify_mark_cache = KMEM_CACHE(fsnotify_mark,
+ fanotify_mark_cache = KMEM_CACHE(fanotify_mark,
SLAB_PANIC|SLAB_ACCOUNT);
fanotify_fid_event_cachep = KMEM_CACHE(fanotify_fid_event,
SLAB_PANIC);
diff --git a/fs/notify/mark.c b/fs/notify/mark.c
index c74ef947447d..d6944ff86ffa 100644
--- a/fs/notify/mark.c
+++ b/fs/notify/mark.c
@@ -537,8 +537,7 @@ int fsnotify_compare_groups(struct fsnotify_group *a, struct fsnotify_group *b)
}
static int fsnotify_attach_connector_to_object(fsnotify_connp_t *connp,
- unsigned int obj_type,
- __kernel_fsid_t *fsid)
+ unsigned int obj_type)
{
struct fsnotify_mark_connector *conn;
@@ -550,14 +549,7 @@ static int fsnotify_attach_connector_to_object(fsnotify_connp_t *connp,
conn->flags = 0;
conn->type = obj_type;
conn->obj = connp;
- /* Cache fsid of filesystem containing the object */
- if (fsid) {
- conn->fsid = *fsid;
- conn->flags = FSNOTIFY_CONN_FLAG_HAS_FSID;
- } else {
- conn->fsid.val[0] = conn->fsid.val[1] = 0;
- conn->flags = 0;
- }
+ conn->flags = 0;
fsnotify_get_sb_connectors(conn);
/*
@@ -608,8 +600,7 @@ out:
*/
static int fsnotify_add_mark_list(struct fsnotify_mark *mark,
fsnotify_connp_t *connp,
- unsigned int obj_type,
- int add_flags, __kernel_fsid_t *fsid)
+ unsigned int obj_type, int add_flags)
{
struct fsnotify_mark *lmark, *last = NULL;
struct fsnotify_mark_connector *conn;
@@ -619,41 +610,15 @@ static int fsnotify_add_mark_list(struct fsnotify_mark *mark,
if (WARN_ON(!fsnotify_valid_obj_type(obj_type)))
return -EINVAL;
- /* Backend is expected to check for zero fsid (e.g. tmpfs) */
- if (fsid && WARN_ON_ONCE(!fsid->val[0] && !fsid->val[1]))
- return -ENODEV;
-
restart:
spin_lock(&mark->lock);
conn = fsnotify_grab_connector(connp);
if (!conn) {
spin_unlock(&mark->lock);
- err = fsnotify_attach_connector_to_object(connp, obj_type,
- fsid);
+ err = fsnotify_attach_connector_to_object(connp, obj_type);
if (err)
return err;
goto restart;
- } else if (fsid && !(conn->flags & FSNOTIFY_CONN_FLAG_HAS_FSID)) {
- conn->fsid = *fsid;
- /* Pairs with smp_rmb() in fanotify_get_fsid() */
- smp_wmb();
- conn->flags |= FSNOTIFY_CONN_FLAG_HAS_FSID;
- } else if (fsid && (conn->flags & FSNOTIFY_CONN_FLAG_HAS_FSID) &&
- (fsid->val[0] != conn->fsid.val[0] ||
- fsid->val[1] != conn->fsid.val[1])) {
- /*
- * Backend is expected to check for non uniform fsid
- * (e.g. btrfs), but maybe we missed something?
- * Only allow setting conn->fsid once to non zero fsid.
- * inotify and non-fid fanotify groups do not set nor test
- * conn->fsid.
- */
- pr_warn_ratelimited("%s: fsid mismatch on object of type %u: "
- "%x.%x != %x.%x\n", __func__, conn->type,
- fsid->val[0], fsid->val[1],
- conn->fsid.val[0], conn->fsid.val[1]);
- err = -EXDEV;
- goto out_err;
}
/* is mark the first mark? */
@@ -703,7 +668,7 @@ out_err:
*/
int fsnotify_add_mark_locked(struct fsnotify_mark *mark,
fsnotify_connp_t *connp, unsigned int obj_type,
- int add_flags, __kernel_fsid_t *fsid)
+ int add_flags)
{
struct fsnotify_group *group = mark->group;
int ret = 0;
@@ -723,7 +688,7 @@ int fsnotify_add_mark_locked(struct fsnotify_mark *mark,
fsnotify_get_mark(mark); /* for g_list */
spin_unlock(&mark->lock);
- ret = fsnotify_add_mark_list(mark, connp, obj_type, add_flags, fsid);
+ ret = fsnotify_add_mark_list(mark, connp, obj_type, add_flags);
if (ret)
goto err;
@@ -742,14 +707,13 @@ err:
}
int fsnotify_add_mark(struct fsnotify_mark *mark, fsnotify_connp_t *connp,
- unsigned int obj_type, int add_flags,
- __kernel_fsid_t *fsid)
+ unsigned int obj_type, int add_flags)
{
int ret;
struct fsnotify_group *group = mark->group;
fsnotify_group_lock(group);
- ret = fsnotify_add_mark_locked(mark, connp, obj_type, add_flags, fsid);
+ ret = fsnotify_add_mark_locked(mark, connp, obj_type, add_flags);
fsnotify_group_unlock(group);
return ret;
}