fs/gfs2/lops.c

Source file repositories/reference/linux-study-clean/fs/gfs2/lops.c

File Facts

System
Linux kernel
Corpus path
fs/gfs2/lops.c
Extension
.c
Size
29025 bytes
Lines
1118
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: implementation source
Status
source 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

if (!__get_log_header(sdp, kaddr + offset, 0, &lh)) {
			if (lh.lh_sequence >= head->lh_sequence)
				*head = lh;
			else {
				ret = true;
				break;
			}
		}
	}
	kunmap_local(kaddr);
	return ret;
}

/**
 * gfs2_jhead_process_page - Search/cleanup a page
 * @jd: The journal descriptor
 * @index: Index of the page to look into
 * @head: The journal head to start from
 * @done: If set, perform only cleanup, else search and set if found.
 *
 * Find the folio with 'index' in the journal's mapping. Search the folio for
 * the journal head if requested (cleanup == false). Release refs on the
 * folio so the page cache can reclaim it. We grabbed a
 * reference on this folio twice, first when we did a filemap_grab_folio()
 * to obtain the folio to add it to the bio and second when we do a
 * filemap_get_folio() here to get the folio to wait on while I/O on it is being
 * completed.
 * This function is also used to free up a folio we might've grabbed but not
 * used. Maybe we added it to a bio, but not submitted it for I/O. Or we
 * submitted the I/O, but we already found the jhead so we only need to drop
 * our references to the folio.
 */

static void gfs2_jhead_process_page(struct gfs2_jdesc *jd, unsigned long index,
				    struct gfs2_log_header_host *head,
				    bool *done)
{
	struct folio *folio;

	folio = filemap_get_folio(jd->jd_inode->i_mapping, index);

	folio_wait_locked(folio);
	if (!folio_test_uptodate(folio))
		*done = true;

	if (!*done)
		*done = gfs2_jhead_folio_search(jd, head, folio);

	/* filemap_get_folio() and the earlier filemap_grab_folio() */
	folio_put_refs(folio, 2);
}

static struct bio *gfs2_chain_bio(struct bio *prev, unsigned int nr_iovecs,
				  sector_t sector, blk_opf_t opf)
{
	struct bio *new;

	new = bio_alloc(prev->bi_bdev, nr_iovecs, opf, GFP_NOIO);
	bio_clone_blkg_association(new, prev);
	new->bi_iter.bi_sector = sector;
	bio_chain(new, prev);
	submit_bio(prev);
	return new;
}

/**
 * gfs2_find_jhead - find the head of a log
 * @jd: The journal descriptor
 * @head: The log descriptor for the head of the log is returned here
 *
 * Do a search of a journal by reading it in large chunks using bios and find
 * the valid log entry with the highest sequence number.  (i.e. the log head)
 *
 * Returns: 0 on success, errno otherwise
 */
int gfs2_find_jhead(struct gfs2_jdesc *jd, struct gfs2_log_header_host *head)
{
	struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
	struct address_space *mapping = jd->jd_inode->i_mapping;
	unsigned int block = 0, blocks_submitted = 0, blocks_read = 0;
	unsigned int bsize = sdp->sd_sb.sb_bsize, off;
	unsigned int bsize_shift = sdp->sd_sb.sb_bsize_shift;
	unsigned int shift = PAGE_SHIFT - bsize_shift;
	unsigned int max_blocks = 2 * 1024 * 1024 >> bsize_shift;
	struct gfs2_journal_extent *je;
	int ret = 0;
	struct bio *bio = NULL;
	struct folio *folio = NULL;
	bool done = false;
	errseq_t since;

Annotation

Implementation Notes