fsnotify: count s_fsnotify_inode_refs for attached connectors

Instead of incrementing s_fsnotify_inode_refs when detaching connector
from inode, increment it earlier when attaching connector to inode.
Next patch is going to use s_fsnotify_inode_refs to count all objects
with attached connectors.

Link: https://lore.kernel.org/r/20210810151220.285179-3-amir73il@gmail.com
Reviewed-by: Matthew Bobrowski <repnop@google.com>
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Jan Kara <jack@suse.cz>
This commit is contained in:
Amir Goldstein 2021-08-10 18:12:18 +03:00 committed by Jan Kara
parent 09ddbe69c9
commit 11fa333b58

View File

@ -169,6 +169,21 @@ static void fsnotify_connector_destroy_workfn(struct work_struct *work)
} }
} }
static void fsnotify_get_inode_ref(struct inode *inode)
{
ihold(inode);
atomic_long_inc(&inode->i_sb->s_fsnotify_inode_refs);
}
static void fsnotify_put_inode_ref(struct inode *inode)
{
struct super_block *sb = inode->i_sb;
iput(inode);
if (atomic_long_dec_and_test(&sb->s_fsnotify_inode_refs))
wake_up_var(&sb->s_fsnotify_inode_refs);
}
static void *fsnotify_detach_connector_from_object( static void *fsnotify_detach_connector_from_object(
struct fsnotify_mark_connector *conn, struct fsnotify_mark_connector *conn,
unsigned int *type) unsigned int *type)
@ -182,7 +197,6 @@ static void *fsnotify_detach_connector_from_object(
if (conn->type == FSNOTIFY_OBJ_TYPE_INODE) { if (conn->type == FSNOTIFY_OBJ_TYPE_INODE) {
inode = fsnotify_conn_inode(conn); inode = fsnotify_conn_inode(conn);
inode->i_fsnotify_mask = 0; inode->i_fsnotify_mask = 0;
atomic_long_inc(&inode->i_sb->s_fsnotify_inode_refs);
} else if (conn->type == FSNOTIFY_OBJ_TYPE_VFSMOUNT) { } else if (conn->type == FSNOTIFY_OBJ_TYPE_VFSMOUNT) {
fsnotify_conn_mount(conn)->mnt_fsnotify_mask = 0; fsnotify_conn_mount(conn)->mnt_fsnotify_mask = 0;
} else if (conn->type == FSNOTIFY_OBJ_TYPE_SB) { } else if (conn->type == FSNOTIFY_OBJ_TYPE_SB) {
@ -209,19 +223,12 @@ static void fsnotify_final_mark_destroy(struct fsnotify_mark *mark)
/* Drop object reference originally held by a connector */ /* Drop object reference originally held by a connector */
static void fsnotify_drop_object(unsigned int type, void *objp) static void fsnotify_drop_object(unsigned int type, void *objp)
{ {
struct inode *inode;
struct super_block *sb;
if (!objp) if (!objp)
return; return;
/* Currently only inode references are passed to be dropped */ /* Currently only inode references are passed to be dropped */
if (WARN_ON_ONCE(type != FSNOTIFY_OBJ_TYPE_INODE)) if (WARN_ON_ONCE(type != FSNOTIFY_OBJ_TYPE_INODE))
return; return;
inode = objp; fsnotify_put_inode_ref(objp);
sb = inode->i_sb;
iput(inode);
if (atomic_long_dec_and_test(&sb->s_fsnotify_inode_refs))
wake_up_var(&sb->s_fsnotify_inode_refs);
} }
void fsnotify_put_mark(struct fsnotify_mark *mark) void fsnotify_put_mark(struct fsnotify_mark *mark)
@ -495,7 +502,7 @@ static int fsnotify_attach_connector_to_object(fsnotify_connp_t *connp,
} }
if (conn->type == FSNOTIFY_OBJ_TYPE_INODE) { if (conn->type == FSNOTIFY_OBJ_TYPE_INODE) {
inode = fsnotify_conn_inode(conn); inode = fsnotify_conn_inode(conn);
ihold(inode); fsnotify_get_inode_ref(inode);
} }
/* /*
@ -505,7 +512,7 @@ static int fsnotify_attach_connector_to_object(fsnotify_connp_t *connp,
if (cmpxchg(connp, NULL, conn)) { if (cmpxchg(connp, NULL, conn)) {
/* Someone else created list structure for us */ /* Someone else created list structure for us */
if (inode) if (inode)
iput(inode); fsnotify_put_inode_ref(inode);
kmem_cache_free(fsnotify_mark_connector_cachep, conn); kmem_cache_free(fsnotify_mark_connector_cachep, conn);
} }