fs/notify/mark.c

Source file repositories/reference/linux-study-clean/fs/notify/mark.c

File Facts

System
Linux kernel
Corpus path
fs/notify/mark.c
Extension
.c
Size
35416 bytes
Lines
1195
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

struct fsnotify_inode_mark_connector {
	struct fsnotify_mark_connector common;
	struct list_head conns_list;
};

static struct inode *fsnotify_get_living_inode(struct fsnotify_sb_info *sbinfo)
{
	struct fsnotify_inode_mark_connector *iconn;
	struct inode *inode;

	spin_lock(&sbinfo->list_lock);
	/* Find the first non-evicting inode */
	list_for_each_entry(iconn, &sbinfo->inode_conn_list, conns_list) {
		/* All connectors on the list are still attached to an inode */
		inode = iconn->common.obj;
		/*
		 * For connectors without FSNOTIFY_CONN_FLAG_HAS_IREF
		 * (evictable marks) corresponding inode may well have 0
		 * refcount and can be undergoing eviction. OTOH list_lock
		 * protects us from the connector getting detached and inode
		 * freed. So we can poke around the inode safely.
		 */
		spin_lock(&inode->i_lock);
		if (likely(
		    !(inode_state_read(inode) & (I_FREEING | I_WILL_FREE)))) {
			__iget(inode);
			spin_unlock(&inode->i_lock);
			spin_unlock(&sbinfo->list_lock);
			return inode;
		}
		spin_unlock(&inode->i_lock);
	}
	spin_unlock(&sbinfo->list_lock);

	return NULL;
}

/**
 * fsnotify_unmount_inodes - an sb is unmounting. Handle any watched inodes.
 * @sbinfo: fsnotify info for superblock being unmounted.
 *
 * Walk all inode connectors for the superblock and free all associated marks.
 */
void fsnotify_unmount_inodes(struct fsnotify_sb_info *sbinfo)
{
	struct inode *inode;

	while ((inode = fsnotify_get_living_inode(sbinfo))) {
		fsnotify_inode(inode, FS_UNMOUNT);
		fsnotify_clear_marks_by_inode(inode);
		iput(inode);
		cond_resched();
	}
}

static void fsnotify_init_connector(struct fsnotify_mark_connector *conn,
				    void *obj, unsigned int obj_type)
{
	spin_lock_init(&conn->lock);
	INIT_HLIST_HEAD(&conn->list);
	conn->flags = 0;
	conn->prio = 0;
	conn->type = obj_type;
	conn->obj = obj;
}

static struct fsnotify_mark_connector *
fsnotify_alloc_inode_connector(struct inode *inode)
{
	struct fsnotify_inode_mark_connector *iconn;
	struct fsnotify_sb_info *sbinfo = fsnotify_sb_info(inode->i_sb);

	iconn = kmem_cache_alloc(fsnotify_inode_mark_connector_cachep,
				 GFP_KERNEL);
	if (!iconn)
		return NULL;

	fsnotify_init_connector(&iconn->common, inode, FSNOTIFY_OBJ_TYPE_INODE);
	spin_lock(&sbinfo->list_lock);
	list_add(&iconn->conns_list, &sbinfo->inode_conn_list);
	spin_unlock(&sbinfo->list_lock);

	return &iconn->common;
}

static void fsnotify_untrack_connector(struct fsnotify_mark_connector *conn)
{
	struct fsnotify_inode_mark_connector *iconn;
	struct fsnotify_sb_info *sbinfo;

Annotation

Implementation Notes