fs/gfs2/rgrp.c

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

File Facts

System
Linux kernel
Corpus path
fs/gfs2/rgrp.c
Extension
.c
Size
74975 bytes
Lines
2770
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 gfs2_rbm {
	struct gfs2_rgrpd *rgd;
	u32 offset;		/* The offset is bitmap relative */
	int bii;		/* Bitmap index */
};

static inline struct gfs2_bitmap *rbm_bi(const struct gfs2_rbm *rbm)
{
	return rbm->rgd->rd_bits + rbm->bii;
}

static inline u64 gfs2_rbm_to_block(const struct gfs2_rbm *rbm)
{
	BUG_ON(rbm->offset >= rbm->rgd->rd_data);
	return rbm->rgd->rd_data0 + (rbm_bi(rbm)->bi_start * GFS2_NBBY) +
		rbm->offset;
}

/*
 * These routines are used by the resource group routines (rgrp.c)
 * to keep track of block allocation.  Each block is represented by two
 * bits.  So, each byte represents GFS2_NBBY (i.e. 4) blocks.
 *
 * 0 = Free
 * 1 = Used (not metadata)
 * 2 = Unlinked (still in use) inode
 * 3 = Used (metadata)
 */

struct gfs2_extent {
	struct gfs2_rbm rbm;
	u32 len;
};

static const char valid_change[16] = {
	        /* current */
	/* n */ 0, 1, 1, 1,
	/* e */ 1, 0, 0, 0,
	/* w */ 0, 0, 0, 1,
	        1, 0, 0, 0
};

static int gfs2_rbm_find(struct gfs2_rbm *rbm, u8 state, u32 *minext,
			 struct gfs2_blkreserv *rs, bool nowrap);


/**
 * gfs2_setbit - Set a bit in the bitmaps
 * @rbm: The position of the bit to set
 * @do_clone: Also set the clone bitmap, if it exists
 * @new_state: the new state of the block
 *
 */

static inline void gfs2_setbit(const struct gfs2_rbm *rbm, bool do_clone,
			       unsigned char new_state)
{
	unsigned char *byte1, *byte2, *end, cur_state;
	struct gfs2_bitmap *bi = rbm_bi(rbm);
	unsigned int buflen = bi->bi_bytes;
	const unsigned int bit = (rbm->offset % GFS2_NBBY) * GFS2_BIT_SIZE;

	byte1 = bi->bi_bh->b_data + bi->bi_offset + (rbm->offset / GFS2_NBBY);
	end = bi->bi_bh->b_data + bi->bi_offset + buflen;

	BUG_ON(byte1 >= end);

	cur_state = (*byte1 >> bit) & GFS2_BIT_MASK;

	if (unlikely(!valid_change[new_state * 4 + cur_state])) {
		struct gfs2_sbd *sdp = rbm->rgd->rd_sbd;

		fs_warn(sdp, "buf_blk = 0x%x old_state=%d, new_state=%d\n",
			rbm->offset, cur_state, new_state);
		fs_warn(sdp, "rgrp=0x%llx bi_start=0x%x biblk: 0x%llx\n",
			(unsigned long long)rbm->rgd->rd_addr, bi->bi_start,
			(unsigned long long)bi->bi_bh->b_blocknr);
		fs_warn(sdp, "bi_offset=0x%x bi_bytes=0x%x block=0x%llx\n",
			bi->bi_offset, bi->bi_bytes,
			(unsigned long long)gfs2_rbm_to_block(rbm));
		dump_stack();
		gfs2_consist_rgrpd(rbm->rgd);
		return;
	}
	*byte1 ^= (cur_state ^ new_state) << bit;

	if (do_clone && bi->bi_clone) {
		byte2 = bi->bi_clone + bi->bi_offset + (rbm->offset / GFS2_NBBY);
		cur_state = (*byte2 >> bit) & GFS2_BIT_MASK;
		*byte2 ^= (cur_state ^ new_state) << bit;

Annotation

Implementation Notes