/* * More or less lifted from ext3. I'll leave their description below: * * "For ext3 allocations, we must not reuse any blocks which are * allocated in the bitmap buffer's "last committed data" copy. This * prevents deletes from freeing up the page for reuse until we have * committed the delete transaction. * * If we didn't do this, then deleting something and reallocating it as * data would allow the old block to be overwritten before the * transaction committed (because we force data to disk before commit). * This would lead to corruption if we crashed between overwriting the * data and committing the delete. * * @@@ We may want to make this allocation behaviour conditional on * data-writes at some point, and disable it for metadata allocations or * sync-data inodes." * * Note: OCFS2 already does this differently for metadata vs data * allocations, as those bitmaps are seperate and undo access is never * called on a metadata group descriptor. */ static int ocfs2_test_bg_bit_allocatable(struct buffer_head *bg_bh, int nr) { struct ocfs2_group_desc *bg = (struct ocfs2_group_desc *) bg_bh->b_data; if (ocfs2_test_bit(nr, (unsigned long *)bg->bg_bitmap)) return 0; if (!buffer_jbd(bg_bh) || !bh2jh(bg_bh)->b_committed_data) return 1; bg = (struct ocfs2_group_desc *) bh2jh(bg_bh)->b_committed_data; return !ocfs2_test_bit(nr, (unsigned long *)bg->bg_bitmap); }
static void ocfs2_probe_alloc_group(struct inode *inode, struct buffer_head *bh, int *goal_bit, u32 move_len, u32 max_hop, u32 *phys_cpos) { int i, used, last_free_bits = 0, base_bit = *goal_bit; struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data; u32 base_cpos = ocfs2_blocks_to_clusters(inode->i_sb, le64_to_cpu(gd->bg_blkno)); for (i = base_bit; i < le16_to_cpu(gd->bg_bits); i++) { used = ocfs2_test_bit(i, (unsigned long *)gd->bg_bitmap); if (used) { if ((i - base_bit) > max_hop) { *phys_cpos = 0; break; } if (last_free_bits) last_free_bits = 0; continue; } else last_free_bits++; if (last_free_bits == move_len) { *goal_bit = i; *phys_cpos = base_cpos + i; break; } } mlog(0, "found phys_cpos: %u to fit the wanted moving.\n", *phys_cpos); }
/* * Like ocfs2_hamming_encode(), this can handle hunks. nr is the bit * offset of the current hunk. If bit to be fixed is not part of the * current hunk, this does nothing. * * If you only have one hunk, use ocfs2_hamming_fix_block(). */ void ocfs2_hamming_fix(void *data, unsigned int d, unsigned int nr, unsigned int fix) { unsigned int i, b; BUG_ON(!d); /* * If the bit to fix has an hweight of 1, it's a parity bit. One * busted parity bit is its own error. Nothing to do here. */ if (hweight32(fix) == 1) return; /* * nr + d is the bit right past the data hunk we're looking at. * If fix after that, nothing to do */ if (fix >= calc_code_bit(nr + d, NULL)) return; /* * nr is the offset in the data hunk we're starting at. Let's * start b at the offset in the code buffer. See hamming_encode() * for a more detailed description of 'b'. */ b = calc_code_bit(nr, NULL); /* If the fix is before this hunk, nothing to do */ if (fix < b) return; for (i = 0; i < d; i++, b++) { /* Skip past parity bits */ while (hweight32(b) == 1) b++; /* * i is the offset in this data hunk. * nr + i is the offset in the total data buffer. * b is the offset in the total code buffer. * * Thus, when b == fix, bit i in the current hunk needs * fixing. */ if (b == fix) { if (ocfs2_test_bit(i, data)) ocfs2_clear_bit(i, data); else ocfs2_set_bit(i, data); break; } } }
/* * More or less lifted from ext3. I'll leave their description below: * * "For ext3 allocations, we must not reuse any blocks which are * allocated in the bitmap buffer's "last committed data" copy. This * prevents deletes from freeing up the page for reuse until we have * committed the delete transaction. * * If we didn't do this, then deleting something and reallocating it as * data would allow the old block to be overwritten before the * transaction committed (because we force data to disk before commit). * This would lead to corruption if we crashed between overwriting the * data and committing the delete. * * @@@ We may want to make this allocation behaviour conditional on * data-writes at some point, and disable it for metadata allocations or * sync-data inodes." * * Note: OCFS2 already does this differently for metadata vs data * allocations, as those bitmaps are separate and undo access is never * called on a metadata group descriptor. */ static int ocfs2_test_bg_bit_allocatable(struct buffer_head *bg_bh, int nr) { struct ocfs2_group_desc *bg = (struct ocfs2_group_desc *) bg_bh->b_data; int ret; if (ocfs2_test_bit(nr, (unsigned long *)bg->bg_bitmap)) return 0; if (!buffer_jbd(bg_bh)) return 1; jbd_lock_bh_state(bg_bh); bg = (struct ocfs2_group_desc *) bh2jh(bg_bh)->b_committed_data; if (bg) ret = !ocfs2_test_bit(nr, (unsigned long *)bg->bg_bitmap); else ret = 1; jbd_unlock_bh_state(bg_bh); return ret; }
uint64_t ocfs2_image_get_blockno(ocfs2_filesys *ofs, uint64_t blkno) { struct ocfs2_image_state *ost = ofs->ost; uint64_t ret_blk; int bitmap_blk; int i, bit; bit = blkno % OCFS2_IMAGE_BITS_IN_BLOCK; bitmap_blk = blkno / OCFS2_IMAGE_BITS_IN_BLOCK; if (ocfs2_test_bit(bit, ost->ost_bmparr[bitmap_blk].arr_map)) { ret_blk = ost->ost_bmparr[bitmap_blk].arr_set_bit_cnt + 1; /* add bits set in this block before the block no */ for (i = 0; i < bit; i++) if (ocfs2_test_bit(i, ost->ost_bmparr[bitmap_blk].arr_map)) ret_blk++; } else ret_blk = -1; return ret_blk; }
int ocfs2_image_test_bit(ocfs2_filesys *ofs, uint64_t blkno) { struct ocfs2_image_state *ost = ofs->ost; int bitmap_blk; int bit; bit = blkno % OCFS2_IMAGE_BITS_IN_BLOCK; bitmap_blk = blkno / OCFS2_IMAGE_BITS_IN_BLOCK; if (ocfs2_test_bit(bit, ost->ost_bmparr[bitmap_blk].arr_map)) return 1; else return 0; }
/* turn this on and uncomment below to aid debugging window shifts. */ static void ocfs2_verify_zero_bits(unsigned long *bitmap, unsigned int start, unsigned int count) { unsigned int tmp = count; while(tmp--) { if (ocfs2_test_bit(start + tmp, bitmap)) { printk("ocfs2_verify_zero_bits: start = %u, count = " "%u\n", start, count); printk("ocfs2_verify_zero_bits: bit %u is set!", start + tmp); BUG(); } } }
static int ocfs2_info_freefrag_scan_chain(struct ocfs2_super *osb, struct inode *gb_inode, struct ocfs2_dinode *gb_dinode, struct ocfs2_chain_rec *rec, struct ocfs2_info_freefrag *ffg, u32 chunks_in_group) { int status = 0, used; u64 blkno; struct buffer_head *bh = NULL; struct ocfs2_group_desc *bg = NULL; unsigned int max_bits, num_clusters; unsigned int offset = 0, cluster, chunk; unsigned int chunk_free, last_chunksize = 0; if (!le32_to_cpu(rec->c_free)) goto bail; do { if (!bg) blkno = le64_to_cpu(rec->c_blkno); else blkno = le64_to_cpu(bg->bg_next_group); if (bh) { brelse(bh); bh = NULL; } if (o2info_coherent(&ffg->iff_req)) status = ocfs2_read_group_descriptor(gb_inode, gb_dinode, blkno, &bh); else status = ocfs2_read_blocks_sync(osb, blkno, 1, &bh); if (status < 0) { mlog(ML_ERROR, "Can't read the group descriptor # " "%llu from device.", (unsigned long long)blkno); status = -EIO; goto bail; } bg = (struct ocfs2_group_desc *)bh->b_data; if (!le16_to_cpu(bg->bg_free_bits_count)) continue; max_bits = le16_to_cpu(bg->bg_bits); offset = 0; for (chunk = 0; chunk < chunks_in_group; chunk++) { /* * last chunk may be not an entire one. */ if ((offset + ffg->iff_chunksize) > max_bits) num_clusters = max_bits - offset; else num_clusters = ffg->iff_chunksize; chunk_free = 0; for (cluster = 0; cluster < num_clusters; cluster++) { used = ocfs2_test_bit(offset, (unsigned long *)bg->bg_bitmap); /* * - chunk_free counts free clusters in #N chunk. * - last_chunksize records the size(in) clusters * for the last real free chunk being counted. */ if (!used) { last_chunksize++; chunk_free++; } if (used && last_chunksize) { ocfs2_info_update_ffg(ffg, last_chunksize); last_chunksize = 0; } offset++; } if (chunk_free == ffg->iff_chunksize) ffg->iff_ffs.ffs_free_chunks++; } /* * need to update the info for last free chunk. */ if (last_chunksize) ocfs2_info_update_ffg(ffg, last_chunksize); } while (le64_to_cpu(bg->bg_next_group)); bail: brelse(bh); return status; }
/* * This routine loads bitmap blocks from an o2image image file into memory. * This process happens during file open. bitmap blocks reside towards * the end of the imagefile. */ errcode_t ocfs2_image_load_bitmap(ocfs2_filesys *ofs) { struct ocfs2_image_state *ost; struct ocfs2_image_hdr *hdr; uint64_t blk_off, bits_set; int i, j, fd; ssize_t count; errcode_t ret; char *blk; ret = ocfs2_malloc0(sizeof(struct ocfs2_image_state), &ofs->ost); if (ret) return ret; ost = ofs->ost; ret = ocfs2_malloc_block(ofs->fs_io, &blk); if (ret) return ret; /* read ocfs2 image header */ ret = io_read_block(ofs->fs_io, 0, 1, blk); if (ret) goto out; hdr = (struct ocfs2_image_hdr *)blk; ocfs2_image_swap_header(hdr); ret = OCFS2_ET_BAD_MAGIC; if (hdr->hdr_magic != OCFS2_IMAGE_MAGIC) goto out; if (memcmp(hdr->hdr_magic_desc, OCFS2_IMAGE_DESC, sizeof(OCFS2_IMAGE_DESC))) goto out; ret = OCFS2_ET_OCFS_REV; if (hdr->hdr_version > OCFS2_IMAGE_VERSION) goto out; ost->ost_fsblkcnt = hdr->hdr_fsblkcnt; ost->ost_fsblksz = hdr->hdr_fsblksz; ost->ost_imgblkcnt = hdr->hdr_imgblkcnt; ost->ost_bmpblksz = hdr->hdr_bmpblksz; ret = ocfs2_image_alloc_bitmap(ofs); if (ret) return ret; /* load bitmap blocks ocfs2 image state */ bits_set = 0; fd = io_get_fd(ofs->fs_io); blk_off = (ost->ost_imgblkcnt + 1) * ost->ost_fsblksz; for (i = 0; i < ost->ost_bmpblks; i++) { ost->ost_bmparr[i].arr_set_bit_cnt = bits_set; /* * we don't use io_read_block as ocfs2 image bitmap block size * could be different from filesystem block size */ count = pread64(fd, ost->ost_bmparr[i].arr_map, ost->ost_bmpblksz, blk_off); if (count < 0) { ret = OCFS2_ET_IO; goto out; } /* add bits set in this bitmap */ for (j = 0; j < (ost->ost_bmpblksz * 8); j++) if (ocfs2_test_bit(j, ost->ost_bmparr[i].arr_map)) bits_set++; blk_off += ost->ost_bmpblksz; } out: if (blk) ocfs2_free(&blk); return ret; }