fs/hfsplus/btree.c

Source file repositories/reference/linux-study-clean/fs/hfsplus/btree.c

File Facts

System
Linux kernel
Corpus path
fs/hfsplus/btree.c
Extension
.c
Size
16514 bytes
Lines
668
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

struct hfs_bmap_ctx {
	unsigned int page_idx;
	unsigned int off;
	u16 len;
};

/*
 * Finds the specific page containing the requested byte offset within the map
 * record. Automatically handles the difference between header and map nodes.
 * Returns the struct page pointer, or an ERR_PTR on failure.
 * Note: The caller is responsible for mapping/unmapping the returned page.
 */
static struct page *hfs_bmap_get_map_page(struct hfs_bnode *node,
					  struct hfs_bmap_ctx *ctx,
					  u32 byte_offset)
{
	u16 rec_idx, off16;
	unsigned int page_off;

	if (node->this == HFSPLUS_TREE_HEAD) {
		if (node->type != HFS_NODE_HEADER) {
			pr_err("hfsplus: invalid btree header node\n");
			return ERR_PTR(-EIO);
		}
		rec_idx = HFSPLUS_BTREE_HDR_MAP_REC_INDEX;
	} else {
		if (node->type != HFS_NODE_MAP) {
			pr_err("hfsplus: invalid btree map node\n");
			return ERR_PTR(-EIO);
		}
		rec_idx = HFSPLUS_BTREE_MAP_NODE_REC_INDEX;
	}

	ctx->len = hfs_brec_lenoff(node, rec_idx, &off16);
	if (!ctx->len)
		return ERR_PTR(-ENOENT);

	if (!is_bnode_offset_valid(node, off16))
		return ERR_PTR(-EIO);

	ctx->len = check_and_correct_requested_length(node, off16, ctx->len);

	if (byte_offset >= ctx->len)
		return ERR_PTR(-EINVAL);

	page_off = (u32)off16 + node->page_offset + byte_offset;
	ctx->page_idx = page_off >> PAGE_SHIFT;
	ctx->off = page_off & ~PAGE_MASK;

	return node->page[ctx->page_idx];
}

/**
 * hfs_bmap_test_bit - test a bit in the b-tree map
 * @node: the b-tree node containing the map record
 * @node_bit_idx: the relative bit index within the node's map record
 *
 * Returns true if set, false if clear or on failure.
 */
static bool hfs_bmap_test_bit(struct hfs_bnode *node, u32 node_bit_idx)
{
	struct hfs_bmap_ctx ctx;
	struct page *page;
	u8 *bmap, byte, mask;

	page = hfs_bmap_get_map_page(node, &ctx, node_bit_idx / BITS_PER_BYTE);
	if (IS_ERR(page))
		return false;

	bmap = kmap_local_page(page);
	byte = bmap[ctx.off];
	kunmap_local(bmap);

	mask = 1 << (7 - (node_bit_idx % BITS_PER_BYTE));
	return (byte & mask) != 0;
}


/**
 * hfs_bmap_clear_bit - clear a bit in the b-tree map
 * @node: the b-tree node containing the map record
 * @node_bit_idx: the relative bit index within the node's map record
 *
 * Returns 0 on success, -EINVAL if already clear, or negative error code.
 */
static int hfs_bmap_clear_bit(struct hfs_bnode *node, u32 node_bit_idx)
{
	struct hfs_bmap_ctx ctx;
	struct page *page;
	u8 *bmap, mask;

Annotation

Implementation Notes