fs/iomap/buffered-io.c

Source file repositories/reference/linux-study-clean/fs/iomap/buffered-io.c

File Facts

System
Linux kernel
Corpus path
fs/iomap/buffered-io.c
Extension
.c
Size
61291 bytes
Lines
2069
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 iomap_folio_state {
	spinlock_t		state_lock;
	unsigned int		read_bytes_pending;
	atomic_t		write_bytes_pending;

	/*
	 * Each block has two bits in this bitmap:
	 * Bits [0..blocks_per_folio) has the uptodate status.
	 * Bits [b_p_f...(2*b_p_f))   has the dirty status.
	 */
	unsigned long		state[];
};

static inline bool ifs_is_fully_uptodate(struct folio *folio,
		struct iomap_folio_state *ifs)
{
	struct inode *inode = folio->mapping->host;

	return bitmap_full(ifs->state, i_blocks_per_folio(inode, folio));
}

/*
 * Find the next uptodate block in the folio. end_blk is inclusive.
 * If no uptodate block is found, this will return end_blk + 1.
 */
static unsigned ifs_next_uptodate_block(struct folio *folio,
		unsigned start_blk, unsigned end_blk)
{
	struct iomap_folio_state *ifs = folio->private;

	return find_next_bit(ifs->state, end_blk + 1, start_blk);
}

/*
 * Find the next non-uptodate block in the folio. end_blk is inclusive.
 * If no non-uptodate block is found, this will return end_blk + 1.
 */
static unsigned ifs_next_nonuptodate_block(struct folio *folio,
		unsigned start_blk, unsigned end_blk)
{
	struct iomap_folio_state *ifs = folio->private;

	return find_next_zero_bit(ifs->state, end_blk + 1, start_blk);
}

static bool ifs_set_range_uptodate(struct folio *folio,
		struct iomap_folio_state *ifs, size_t off, size_t len)
{
	struct inode *inode = folio->mapping->host;
	unsigned int first_blk = off >> inode->i_blkbits;
	unsigned int last_blk = (off + len - 1) >> inode->i_blkbits;
	unsigned int nr_blks = last_blk - first_blk + 1;

	bitmap_set(ifs->state, first_blk, nr_blks);
	return ifs_is_fully_uptodate(folio, ifs);
}

static void iomap_set_range_uptodate(struct folio *folio, size_t off,
		size_t len)
{
	struct iomap_folio_state *ifs = folio->private;
	unsigned long flags;
	bool mark_uptodate = true;

	if (folio_test_uptodate(folio))
		return;

	if (ifs) {
		spin_lock_irqsave(&ifs->state_lock, flags);
		/*
		 * If a read with bytes pending is in progress, we must not call
		 * folio_mark_uptodate(). The read completion path
		 * (iomap_read_end()) will call folio_end_read(), which uses XOR
		 * semantics to set the uptodate bit. If we set it here, the XOR
		 * in folio_end_read() will clear it, leaving the folio not
		 * uptodate.
		 */
		mark_uptodate = ifs_set_range_uptodate(folio, ifs, off, len) &&
				!ifs->read_bytes_pending;
		spin_unlock_irqrestore(&ifs->state_lock, flags);
	}

	if (mark_uptodate)
		folio_mark_uptodate(folio);
}

/*
 * Find the next dirty block in the folio. end_blk is inclusive.
 * If no dirty block is found, this will return end_blk + 1.
 */

Annotation

Implementation Notes