fs/nilfs2/btnode.c

Source file repositories/reference/linux-study-clean/fs/nilfs2/btnode.c

File Facts

System
Linux kernel
Corpus path
fs/nilfs2/btnode.c
Extension
.c
Size
10652 bytes
Lines
357
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

buffer_dirty(bh))) {
		/*
		 * The block buffer at the specified new address was already
		 * in use.  This can happen if it is a virtual block number
		 * and has been reallocated due to corruption of the bitmap
		 * used to manage its allocation state (if not, the buffer
		 * clearing of an abandoned b-tree node is missing somewhere).
		 */
		nilfs_error(inode->i_sb,
			    "state inconsistency probably due to duplicate use of b-tree node block address %llu (ino=%llu)",
			    (unsigned long long)blocknr, inode->i_ino);
		goto failed;
	}
	memset(bh->b_data, 0, i_blocksize(inode));
	bh->b_blocknr = blocknr;
	set_buffer_mapped(bh);
	set_buffer_uptodate(bh);

	folio_unlock(bh->b_folio);
	folio_put(bh->b_folio);
	return bh;

failed:
	folio_unlock(bh->b_folio);
	folio_put(bh->b_folio);
	brelse(bh);
	return ERR_PTR(-EIO);
}

int nilfs_btnode_submit_block(struct address_space *btnc, __u64 blocknr,
			      sector_t pblocknr, blk_opf_t opf,
			      struct buffer_head **pbh, sector_t *submit_ptr)
{
	struct buffer_head *bh;
	struct inode *inode = btnc->host;
	struct folio *folio;
	int err;

	bh = nilfs_grab_buffer(inode, btnc, blocknr, BIT(BH_NILFS_Node));
	if (unlikely(!bh))
		return -ENOMEM;

	err = -EEXIST; /* internal code */
	folio = bh->b_folio;

	if (buffer_uptodate(bh) || buffer_dirty(bh))
		goto found;

	if (pblocknr == 0) {
		pblocknr = blocknr;
		if (inode->i_ino != NILFS_DAT_INO) {
			struct the_nilfs *nilfs = inode->i_sb->s_fs_info;

			/* blocknr is a virtual block number */
			err = nilfs_dat_translate(nilfs->ns_dat, blocknr,
						  &pblocknr);
			if (unlikely(err)) {
				brelse(bh);
				goto out_locked;
			}
		}
	}

	if (opf & REQ_RAHEAD) {
		if (pblocknr != *submit_ptr + 1 || !trylock_buffer(bh)) {
			err = -EBUSY; /* internal code */
			brelse(bh);
			goto out_locked;
		}
	} else { /* opf == REQ_OP_READ */
		lock_buffer(bh);
	}
	if (buffer_uptodate(bh)) {
		unlock_buffer(bh);
		err = -EEXIST; /* internal code */
		goto found;
	}
	set_buffer_mapped(bh);
	bh->b_blocknr = pblocknr; /* set block address for read */
	bh_submit(bh, opf, bh_end_read);
	bh->b_blocknr = blocknr; /* set back to the given block address */
	*submit_ptr = pblocknr;
	err = 0;
found:
	*pbh = bh;

out_locked:
	folio_unlock(folio);
	folio_put(folio);
	return err;

Annotation

Implementation Notes