mirror of
https://github.com/torvalds/linux.git
synced 2024-11-21 19:41:42 +00:00
fsnotify: pass object pointer and type to fsnotify mark helpers
Instead of passing fsnotify_connp_t, pass the pointer to the marked object. Store the object pointer in the connector and move the definition of fsnotify_connp_t to internal fsnotify subsystem API, so it is no longer used by fsnotify backends. Suggested-by: Jan Kara <jack@suse.cz> Signed-off-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Jan Kara <jack@suse.cz> Message-Id: <20240317184154.1200192-6-amir73il@gmail.com>
This commit is contained in:
parent
b5cae086cc
commit
687c217c6a
@ -1076,7 +1076,7 @@ static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark,
|
||||
}
|
||||
|
||||
static int fanotify_remove_mark(struct fsnotify_group *group,
|
||||
fsnotify_connp_t *connp, __u32 mask,
|
||||
void *obj, unsigned int obj_type, __u32 mask,
|
||||
unsigned int flags, __u32 umask)
|
||||
{
|
||||
struct fsnotify_mark *fsn_mark = NULL;
|
||||
@ -1084,7 +1084,7 @@ static int fanotify_remove_mark(struct fsnotify_group *group,
|
||||
int destroy_mark;
|
||||
|
||||
fsnotify_group_lock(group);
|
||||
fsn_mark = fsnotify_find_mark(connp, group);
|
||||
fsn_mark = fsnotify_find_mark(obj, obj_type, group);
|
||||
if (!fsn_mark) {
|
||||
fsnotify_group_unlock(group);
|
||||
return -ENOENT;
|
||||
@ -1105,30 +1105,6 @@ static int fanotify_remove_mark(struct fsnotify_group *group,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fanotify_remove_vfsmount_mark(struct fsnotify_group *group,
|
||||
struct vfsmount *mnt, __u32 mask,
|
||||
unsigned int flags, __u32 umask)
|
||||
{
|
||||
return fanotify_remove_mark(group, &real_mount(mnt)->mnt_fsnotify_marks,
|
||||
mask, flags, umask);
|
||||
}
|
||||
|
||||
static int fanotify_remove_sb_mark(struct fsnotify_group *group,
|
||||
struct super_block *sb, __u32 mask,
|
||||
unsigned int flags, __u32 umask)
|
||||
{
|
||||
return fanotify_remove_mark(group, &sb->s_fsnotify_marks, mask,
|
||||
flags, umask);
|
||||
}
|
||||
|
||||
static int fanotify_remove_inode_mark(struct fsnotify_group *group,
|
||||
struct inode *inode, __u32 mask,
|
||||
unsigned int flags, __u32 umask)
|
||||
{
|
||||
return fanotify_remove_mark(group, &inode->i_fsnotify_marks, mask,
|
||||
flags, umask);
|
||||
}
|
||||
|
||||
static bool fanotify_mark_update_flags(struct fsnotify_mark *fsn_mark,
|
||||
unsigned int fan_flags)
|
||||
{
|
||||
@ -1249,7 +1225,7 @@ static int fanotify_set_mark_fsid(struct fsnotify_group *group,
|
||||
}
|
||||
|
||||
static struct fsnotify_mark *fanotify_add_new_mark(struct fsnotify_group *group,
|
||||
fsnotify_connp_t *connp,
|
||||
void *obj,
|
||||
unsigned int obj_type,
|
||||
unsigned int fan_flags,
|
||||
struct fan_fsid *fsid)
|
||||
@ -1288,7 +1264,7 @@ static struct fsnotify_mark *fanotify_add_new_mark(struct fsnotify_group *group,
|
||||
fan_mark->fsid.val[0] = fan_mark->fsid.val[1] = 0;
|
||||
}
|
||||
|
||||
ret = fsnotify_add_mark_locked(mark, connp, obj_type, 0);
|
||||
ret = fsnotify_add_mark_locked(mark, obj, obj_type, 0);
|
||||
if (ret)
|
||||
goto out_put_mark;
|
||||
|
||||
@ -1344,7 +1320,7 @@ static int fanotify_may_update_existing_mark(struct fsnotify_mark *fsn_mark,
|
||||
}
|
||||
|
||||
static int fanotify_add_mark(struct fsnotify_group *group,
|
||||
fsnotify_connp_t *connp, unsigned int obj_type,
|
||||
void *obj, unsigned int obj_type,
|
||||
__u32 mask, unsigned int fan_flags,
|
||||
struct fan_fsid *fsid)
|
||||
{
|
||||
@ -1353,9 +1329,9 @@ static int fanotify_add_mark(struct fsnotify_group *group,
|
||||
int ret = 0;
|
||||
|
||||
fsnotify_group_lock(group);
|
||||
fsn_mark = fsnotify_find_mark(connp, group);
|
||||
fsn_mark = fsnotify_find_mark(obj, obj_type, group);
|
||||
if (!fsn_mark) {
|
||||
fsn_mark = fanotify_add_new_mark(group, connp, obj_type,
|
||||
fsn_mark = fanotify_add_new_mark(group, obj, obj_type,
|
||||
fan_flags, fsid);
|
||||
if (IS_ERR(fsn_mark)) {
|
||||
fsnotify_group_unlock(group);
|
||||
@ -1392,30 +1368,6 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int fanotify_add_vfsmount_mark(struct fsnotify_group *group,
|
||||
struct vfsmount *mnt, __u32 mask,
|
||||
unsigned int flags, struct fan_fsid *fsid)
|
||||
{
|
||||
return fanotify_add_mark(group, &real_mount(mnt)->mnt_fsnotify_marks,
|
||||
FSNOTIFY_OBJ_TYPE_VFSMOUNT, mask, flags, fsid);
|
||||
}
|
||||
|
||||
static int fanotify_add_sb_mark(struct fsnotify_group *group,
|
||||
struct super_block *sb, __u32 mask,
|
||||
unsigned int flags, struct fan_fsid *fsid)
|
||||
{
|
||||
return fanotify_add_mark(group, &sb->s_fsnotify_marks,
|
||||
FSNOTIFY_OBJ_TYPE_SB, mask, flags, fsid);
|
||||
}
|
||||
|
||||
static int fanotify_add_inode_mark(struct fsnotify_group *group,
|
||||
struct inode *inode, __u32 mask,
|
||||
unsigned int flags, struct fan_fsid *fsid)
|
||||
{
|
||||
return fanotify_add_mark(group, &inode->i_fsnotify_marks,
|
||||
FSNOTIFY_OBJ_TYPE_INODE, mask, flags, fsid);
|
||||
}
|
||||
|
||||
static struct fsnotify_event *fanotify_alloc_overflow_event(void)
|
||||
{
|
||||
struct fanotify_event *oevent;
|
||||
@ -1738,6 +1690,7 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
|
||||
unsigned int mark_cmd = flags & FANOTIFY_MARK_CMD_BITS;
|
||||
unsigned int ignore = flags & FANOTIFY_MARK_IGNORE_BITS;
|
||||
unsigned int obj_type, fid_mode;
|
||||
void *obj;
|
||||
u32 umask = 0;
|
||||
int ret;
|
||||
|
||||
@ -1896,10 +1849,16 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
|
||||
}
|
||||
|
||||
/* inode held in place by reference to path; group by fget on fd */
|
||||
if (mark_type == FAN_MARK_INODE)
|
||||
if (mark_type == FAN_MARK_INODE) {
|
||||
inode = path.dentry->d_inode;
|
||||
else
|
||||
obj = inode;
|
||||
} else {
|
||||
mnt = path.mnt;
|
||||
if (mark_type == FAN_MARK_MOUNT)
|
||||
obj = mnt;
|
||||
else
|
||||
obj = mnt->mnt_sb;
|
||||
}
|
||||
|
||||
/*
|
||||
* If some other task has this inode open for write we should not add
|
||||
@ -1935,26 +1894,12 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
|
||||
/* create/update an inode mark */
|
||||
switch (mark_cmd) {
|
||||
case FAN_MARK_ADD:
|
||||
if (mark_type == FAN_MARK_MOUNT)
|
||||
ret = fanotify_add_vfsmount_mark(group, mnt, mask,
|
||||
flags, fsid);
|
||||
else if (mark_type == FAN_MARK_FILESYSTEM)
|
||||
ret = fanotify_add_sb_mark(group, mnt->mnt_sb, mask,
|
||||
flags, fsid);
|
||||
else
|
||||
ret = fanotify_add_inode_mark(group, inode, mask,
|
||||
flags, fsid);
|
||||
ret = fanotify_add_mark(group, obj, obj_type, mask, flags,
|
||||
fsid);
|
||||
break;
|
||||
case FAN_MARK_REMOVE:
|
||||
if (mark_type == FAN_MARK_MOUNT)
|
||||
ret = fanotify_remove_vfsmount_mark(group, mnt, mask,
|
||||
flags, umask);
|
||||
else if (mark_type == FAN_MARK_FILESYSTEM)
|
||||
ret = fanotify_remove_sb_mark(group, mnt->mnt_sb, mask,
|
||||
flags, umask);
|
||||
else
|
||||
ret = fanotify_remove_inode_mark(group, inode, mask,
|
||||
flags, umask);
|
||||
ret = fanotify_remove_mark(group, obj, obj_type, mask, flags,
|
||||
umask);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
|
@ -9,22 +9,28 @@
|
||||
|
||||
#include "../mount.h"
|
||||
|
||||
/*
|
||||
* fsnotify_connp_t is what we embed in objects which connector can be attached
|
||||
* to.
|
||||
*/
|
||||
typedef struct fsnotify_mark_connector __rcu *fsnotify_connp_t;
|
||||
|
||||
static inline struct inode *fsnotify_conn_inode(
|
||||
struct fsnotify_mark_connector *conn)
|
||||
{
|
||||
return container_of(conn->obj, struct inode, i_fsnotify_marks);
|
||||
return conn->obj;
|
||||
}
|
||||
|
||||
static inline struct mount *fsnotify_conn_mount(
|
||||
struct fsnotify_mark_connector *conn)
|
||||
{
|
||||
return container_of(conn->obj, struct mount, mnt_fsnotify_marks);
|
||||
return real_mount(conn->obj);
|
||||
}
|
||||
|
||||
static inline struct super_block *fsnotify_conn_sb(
|
||||
struct fsnotify_mark_connector *conn)
|
||||
{
|
||||
return container_of(conn->obj, struct super_block, s_fsnotify_marks);
|
||||
return conn->obj;
|
||||
}
|
||||
|
||||
static inline struct super_block *fsnotify_object_sb(void *obj,
|
||||
@ -45,16 +51,7 @@ static inline struct super_block *fsnotify_object_sb(void *obj,
|
||||
static inline struct super_block *fsnotify_connector_sb(
|
||||
struct fsnotify_mark_connector *conn)
|
||||
{
|
||||
switch (conn->type) {
|
||||
case FSNOTIFY_OBJ_TYPE_INODE:
|
||||
return fsnotify_conn_inode(conn)->i_sb;
|
||||
case FSNOTIFY_OBJ_TYPE_VFSMOUNT:
|
||||
return fsnotify_conn_mount(conn)->mnt.mnt_sb;
|
||||
case FSNOTIFY_OBJ_TYPE_SB:
|
||||
return fsnotify_conn_sb(conn);
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
return fsnotify_object_sb(conn->obj, conn->type);
|
||||
}
|
||||
|
||||
/* destroy all events sitting in this groups notification queue */
|
||||
|
@ -265,6 +265,7 @@ static void *fsnotify_detach_connector_from_object(
|
||||
struct fsnotify_mark_connector *conn,
|
||||
unsigned int *type)
|
||||
{
|
||||
fsnotify_connp_t *connp = fsnotify_object_connp(conn->obj, conn->type);
|
||||
struct inode *inode = NULL;
|
||||
|
||||
*type = conn->type;
|
||||
@ -285,7 +286,7 @@ static void *fsnotify_detach_connector_from_object(
|
||||
}
|
||||
|
||||
fsnotify_put_sb_watchers(conn);
|
||||
rcu_assign_pointer(*(conn->obj), NULL);
|
||||
rcu_assign_pointer(*connp, NULL);
|
||||
conn->obj = NULL;
|
||||
conn->type = FSNOTIFY_OBJ_TYPE_DETACHED;
|
||||
|
||||
@ -560,7 +561,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)
|
||||
void *obj, unsigned int obj_type)
|
||||
{
|
||||
struct fsnotify_mark_connector *conn;
|
||||
|
||||
@ -571,7 +572,7 @@ static int fsnotify_attach_connector_to_object(fsnotify_connp_t *connp,
|
||||
INIT_HLIST_HEAD(&conn->list);
|
||||
conn->flags = 0;
|
||||
conn->type = obj_type;
|
||||
conn->obj = connp;
|
||||
conn->obj = obj;
|
||||
|
||||
/*
|
||||
* cmpxchg() provides the barrier so that readers of *connp can see
|
||||
@ -620,24 +621,25 @@ out:
|
||||
* to which group and for which inodes. These marks are ordered according to
|
||||
* priority, highest number first, and then by the group's location in memory.
|
||||
*/
|
||||
static int fsnotify_add_mark_list(struct fsnotify_mark *mark,
|
||||
fsnotify_connp_t *connp,
|
||||
static int fsnotify_add_mark_list(struct fsnotify_mark *mark, void *obj,
|
||||
unsigned int obj_type, int add_flags)
|
||||
{
|
||||
struct fsnotify_mark *lmark, *last = NULL;
|
||||
struct fsnotify_mark_connector *conn;
|
||||
fsnotify_connp_t *connp;
|
||||
int cmp;
|
||||
int err = 0;
|
||||
|
||||
if (WARN_ON(!fsnotify_valid_obj_type(obj_type)))
|
||||
return -EINVAL;
|
||||
|
||||
connp = fsnotify_object_connp(obj, obj_type);
|
||||
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);
|
||||
err = fsnotify_attach_connector_to_object(connp, obj, obj_type);
|
||||
if (err)
|
||||
return err;
|
||||
goto restart;
|
||||
@ -689,7 +691,7 @@ out_err:
|
||||
* event types should be delivered to which group.
|
||||
*/
|
||||
int fsnotify_add_mark_locked(struct fsnotify_mark *mark,
|
||||
fsnotify_connp_t *connp, unsigned int obj_type,
|
||||
void *obj, unsigned int obj_type,
|
||||
int add_flags)
|
||||
{
|
||||
struct fsnotify_group *group = mark->group;
|
||||
@ -710,7 +712,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);
|
||||
ret = fsnotify_add_mark_list(mark, obj, obj_type, add_flags);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
@ -728,14 +730,14 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int fsnotify_add_mark(struct fsnotify_mark *mark, fsnotify_connp_t *connp,
|
||||
int fsnotify_add_mark(struct fsnotify_mark *mark, void *obj,
|
||||
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);
|
||||
ret = fsnotify_add_mark_locked(mark, obj, obj_type, add_flags);
|
||||
fsnotify_group_unlock(group);
|
||||
return ret;
|
||||
}
|
||||
@ -745,12 +747,16 @@ EXPORT_SYMBOL_GPL(fsnotify_add_mark);
|
||||
* Given a list of marks, find the mark associated with given group. If found
|
||||
* take a reference to that mark and return it, else return NULL.
|
||||
*/
|
||||
struct fsnotify_mark *fsnotify_find_mark(fsnotify_connp_t *connp,
|
||||
struct fsnotify_mark *fsnotify_find_mark(void *obj, unsigned int obj_type,
|
||||
struct fsnotify_group *group)
|
||||
{
|
||||
fsnotify_connp_t *connp = fsnotify_object_connp(obj, obj_type);
|
||||
struct fsnotify_mark_connector *conn;
|
||||
struct fsnotify_mark *mark;
|
||||
|
||||
if (!connp)
|
||||
return NULL;
|
||||
|
||||
conn = fsnotify_grab_connector(connp);
|
||||
if (!conn)
|
||||
return NULL;
|
||||
|
@ -456,13 +456,6 @@ FSNOTIFY_ITER_FUNCS(sb, SB)
|
||||
type < FSNOTIFY_ITER_TYPE_COUNT; \
|
||||
type++)
|
||||
|
||||
/*
|
||||
* fsnotify_connp_t is what we embed in objects which connector can be attached
|
||||
* to. fsnotify_connp_t * is how we refer from connector back to object.
|
||||
*/
|
||||
struct fsnotify_mark_connector;
|
||||
typedef struct fsnotify_mark_connector __rcu *fsnotify_connp_t;
|
||||
|
||||
/*
|
||||
* Inode/vfsmount/sb point to this structure which tracks all marks attached to
|
||||
* the inode/vfsmount/sb. The reference to inode/vfsmount/sb is held by this
|
||||
@ -476,7 +469,7 @@ struct fsnotify_mark_connector {
|
||||
unsigned short flags; /* flags [lock] */
|
||||
union {
|
||||
/* Object pointer [lock] */
|
||||
fsnotify_connp_t *obj;
|
||||
void *obj;
|
||||
/* Used listing heads to free after srcu period expires */
|
||||
struct fsnotify_mark_connector *destroy_next;
|
||||
};
|
||||
@ -763,37 +756,35 @@ extern void fsnotify_recalc_mask(struct fsnotify_mark_connector *conn);
|
||||
extern void fsnotify_init_mark(struct fsnotify_mark *mark,
|
||||
struct fsnotify_group *group);
|
||||
/* Find mark belonging to given group in the list of marks */
|
||||
extern struct fsnotify_mark *fsnotify_find_mark(fsnotify_connp_t *connp,
|
||||
struct fsnotify_group *group);
|
||||
struct fsnotify_mark *fsnotify_find_mark(void *obj, unsigned int obj_type,
|
||||
struct fsnotify_group *group);
|
||||
/* attach the mark to the object */
|
||||
extern int fsnotify_add_mark(struct fsnotify_mark *mark,
|
||||
fsnotify_connp_t *connp, unsigned int obj_type,
|
||||
int add_flags);
|
||||
extern int fsnotify_add_mark_locked(struct fsnotify_mark *mark,
|
||||
fsnotify_connp_t *connp,
|
||||
unsigned int obj_type, int add_flags);
|
||||
int fsnotify_add_mark(struct fsnotify_mark *mark, void *obj,
|
||||
unsigned int obj_type, int add_flags);
|
||||
int fsnotify_add_mark_locked(struct fsnotify_mark *mark, void *obj,
|
||||
unsigned int obj_type, int add_flags);
|
||||
|
||||
/* attach the mark to the inode */
|
||||
static inline int fsnotify_add_inode_mark(struct fsnotify_mark *mark,
|
||||
struct inode *inode,
|
||||
int add_flags)
|
||||
{
|
||||
return fsnotify_add_mark(mark, &inode->i_fsnotify_marks,
|
||||
FSNOTIFY_OBJ_TYPE_INODE, add_flags);
|
||||
return fsnotify_add_mark(mark, inode, FSNOTIFY_OBJ_TYPE_INODE,
|
||||
add_flags);
|
||||
}
|
||||
static inline int fsnotify_add_inode_mark_locked(struct fsnotify_mark *mark,
|
||||
struct inode *inode,
|
||||
int add_flags)
|
||||
{
|
||||
return fsnotify_add_mark_locked(mark, &inode->i_fsnotify_marks,
|
||||
FSNOTIFY_OBJ_TYPE_INODE, add_flags);
|
||||
return fsnotify_add_mark_locked(mark, inode, FSNOTIFY_OBJ_TYPE_INODE,
|
||||
add_flags);
|
||||
}
|
||||
|
||||
static inline struct fsnotify_mark *fsnotify_find_inode_mark(
|
||||
struct inode *inode,
|
||||
struct fsnotify_group *group)
|
||||
{
|
||||
return fsnotify_find_mark(&inode->i_fsnotify_marks, group);
|
||||
return fsnotify_find_mark(inode, FSNOTIFY_OBJ_TYPE_INODE, group);
|
||||
}
|
||||
|
||||
/* given a group and a mark, flag mark to be freed when all references are dropped */
|
||||
|
Loading…
Reference in New Issue
Block a user