/* * We expect the block group allocator to already be locked. */ static int ocfs2_block_group_alloc(struct ocfs2_super *osb, struct inode *alloc_inode, struct buffer_head *bh) { int status, credits; struct ocfs2_dinode *fe = (struct ocfs2_dinode *) bh->b_data; struct ocfs2_chain_list *cl; struct ocfs2_alloc_context *ac = NULL; handle_t *handle = NULL; u32 bit_off, num_bits; u16 alloc_rec; u64 bg_blkno; struct buffer_head *bg_bh = NULL; struct ocfs2_group_desc *bg; BUG_ON(ocfs2_is_cluster_bitmap(alloc_inode)); mlog_entry_void(); cl = &fe->id2.i_chain; status = ocfs2_reserve_clusters(osb, le16_to_cpu(cl->cl_cpg), &ac); if (status < 0) { if (status != -ENOSPC) mlog_errno(status); goto bail; } credits = ocfs2_calc_group_alloc_credits(osb->sb, le16_to_cpu(cl->cl_cpg)); handle = ocfs2_start_trans(osb, credits); if (IS_ERR(handle)) { status = PTR_ERR(handle); handle = NULL; mlog_errno(status); goto bail; } status = ocfs2_claim_clusters(osb, handle, ac, le16_to_cpu(cl->cl_cpg), &bit_off, &num_bits); if (status < 0) { if (status != -ENOSPC) mlog_errno(status); goto bail; } alloc_rec = ocfs2_find_smallest_chain(cl); /* setup the group */ bg_blkno = ocfs2_clusters_to_blocks(osb->sb, bit_off); mlog(0, "new descriptor, record %u, at block %llu\n", alloc_rec, (unsigned long long)bg_blkno); bg_bh = sb_getblk(osb->sb, bg_blkno); if (!bg_bh) { status = -EIO; mlog_errno(status); goto bail; } ocfs2_set_new_buffer_uptodate(alloc_inode, bg_bh); status = ocfs2_block_group_fill(handle, alloc_inode, bg_bh, bg_blkno, alloc_rec, cl); if (status < 0) { mlog_errno(status); goto bail; } bg = (struct ocfs2_group_desc *) bg_bh->b_data; status = ocfs2_journal_access(handle, alloc_inode, bh, OCFS2_JOURNAL_ACCESS_WRITE); if (status < 0) { mlog_errno(status); goto bail; } le32_add_cpu(&cl->cl_recs[alloc_rec].c_free, le16_to_cpu(bg->bg_free_bits_count)); le32_add_cpu(&cl->cl_recs[alloc_rec].c_total, le16_to_cpu(bg->bg_bits)); cl->cl_recs[alloc_rec].c_blkno = cpu_to_le64(bg_blkno); if (le16_to_cpu(cl->cl_next_free_rec) < le16_to_cpu(cl->cl_count)) le16_add_cpu(&cl->cl_next_free_rec, 1); le32_add_cpu(&fe->id1.bitmap1.i_used, le16_to_cpu(bg->bg_bits) - le16_to_cpu(bg->bg_free_bits_count)); le32_add_cpu(&fe->id1.bitmap1.i_total, le16_to_cpu(bg->bg_bits)); le32_add_cpu(&fe->i_clusters, le16_to_cpu(cl->cl_cpg)); status = ocfs2_journal_dirty(handle, bh); if (status < 0) { mlog_errno(status); goto bail; } spin_lock(&OCFS2_I(alloc_inode)->ip_lock); OCFS2_I(alloc_inode)->ip_clusters = le32_to_cpu(fe->i_clusters); fe->i_size = cpu_to_le64(ocfs2_clusters_to_bytes(alloc_inode->i_sb, le32_to_cpu(fe->i_clusters))); spin_unlock(&OCFS2_I(alloc_inode)->ip_lock); i_size_write(alloc_inode, le64_to_cpu(fe->i_size)); alloc_inode->i_blocks = ocfs2_inode_sector_count(alloc_inode); status = 0; bail: if (handle) ocfs2_commit_trans(osb, handle); if (ac) ocfs2_free_alloc_context(ac); if (bg_bh) brelse(bg_bh); mlog_exit(status); return status; }
void mess_up_dup_clusters(ocfs2_filesys *fs, enum fsck_type type, uint64_t blkno) { errcode_t err; char *buf = NULL; uint64_t inode1_blkno, inode2_blkno; struct ocfs2_dinode *di1, *di2; struct ocfs2_extent_list *el1, *el2; err = ocfs2_malloc_blocks(fs->fs_io, 2, &buf); if (err) FSWRK_COM_FATAL(progname, err); create_file(fs, blkno, &inode1_blkno); di1 = (struct ocfs2_dinode *)buf; err = ocfs2_read_inode(fs, inode1_blkno, (char *)di1); if (err) FSWRK_COM_FATAL(progname, err); if (ocfs2_support_inline_data(OCFS2_RAW_SB(fs->fs_super))) { if (di1->i_dyn_features & OCFS2_INLINE_DATA_FL) { di1->i_dyn_features &= ~OCFS2_INLINE_DATA_FL; err = ocfs2_write_inode(fs, inode1_blkno, (char *)di1); if (err) FSWRK_COM_FATAL(progname, err); } } if (type != DUP_CLUSTERS_SYSFILE_CLONE) { create_file(fs, blkno, &inode2_blkno); di2 = (struct ocfs2_dinode *)(buf + fs->fs_blocksize); err = ocfs2_read_inode(fs, inode2_blkno, (char *)di2); if (err) FSWRK_COM_FATAL(progname, err); if (ocfs2_support_inline_data(OCFS2_RAW_SB(fs->fs_super))) { if (di2->i_dyn_features & OCFS2_INLINE_DATA_FL) { di2->i_dyn_features &= ~OCFS2_INLINE_DATA_FL; err = ocfs2_write_inode(fs, inode2_blkno, (char *)di2); if (err) FSWRK_COM_FATAL(progname, err); } } err = ocfs2_extend_allocation(fs, inode2_blkno, 1); if (err) FSWRK_COM_FATAL(progname, err); /* Re-read the inode with the allocation */ err = ocfs2_read_inode(fs, inode2_blkno, (char *)di2); if (err) FSWRK_COM_FATAL(progname, err); /* Set i_size to non-zero so that the allocation is valid */ di2->i_size = fs->fs_clustersize; err = ocfs2_write_inode(fs, inode2_blkno, (char *)di2); if (err) FSWRK_COM_FATAL(progname, err); if (type == DUP_CLUSTERS_CLONE) fprintf(stdout, "DUP_CLUSTERS_CLONE: " "Create two inodes #%"PRIu64" and #%"PRIu64 " by allocating same cluster to them.\n", inode1_blkno, inode2_blkno); else fprintf(stdout, "DUP_CLUSTERS_DELETE: " "Create two inodes #%"PRIu64" and #%"PRIu64 " by allocating same cluster to them.\n", inode1_blkno, inode2_blkno); } else { /* Here use journal file*/ err = ocfs2_lookup_system_inode(fs, JOURNAL_SYSTEM_INODE, 0, &inode2_blkno); if (err) FSWRK_COM_FATAL(progname, err); di2 = (struct ocfs2_dinode *)(buf + fs->fs_blocksize); err = ocfs2_read_inode(fs, inode2_blkno, (char *)di2); if (err) FSWRK_COM_FATAL(progname, err); if (di2->id2.i_list.l_tree_depth) FSWRK_FATAL("Journal inode has non-zero tree " "depth. fswreck can't use it for " "DUP_CLUSTERS_SYSFILE_CLONE\n"); fprintf(stdout, "DUP_CLUSTERS_SYSFILE_CLONE: " "Allocate same cluster to journal file " "#%"PRIu64" and regular file #%"PRIu64".\n", inode1_blkno, inode2_blkno); } el1 = &(di1->id2.i_list); el2 = &(di2->id2.i_list); el1->l_next_free_rec = 1; el1->l_recs[0] = el2->l_recs[0]; di1->i_size = ocfs2_clusters_to_bytes(fs, el1->l_recs[0].e_leaf_clusters); di1->i_clusters = di2->i_clusters; err = ocfs2_write_inode(fs, inode1_blkno, (char *)di1); if (err) FSWRK_COM_FATAL(progname, err); ocfs2_free(&buf); }
/* * We expect the block group allocator to already be locked. */ static int ocfs2_block_group_alloc(struct ocfs2_super *osb, struct inode *alloc_inode, struct buffer_head *bh, u64 max_block, u64 *last_alloc_group, int flags) { int status, credits; struct ocfs2_dinode *fe = (struct ocfs2_dinode *) bh->b_data; struct ocfs2_chain_list *cl; struct ocfs2_alloc_context *ac = NULL; handle_t *handle = NULL; u16 alloc_rec; struct buffer_head *bg_bh = NULL; struct ocfs2_group_desc *bg; BUG_ON(ocfs2_is_cluster_bitmap(alloc_inode)); cl = &fe->id2.i_chain; status = ocfs2_reserve_clusters_with_limit(osb, le16_to_cpu(cl->cl_cpg), max_block, flags, &ac); if (status < 0) { if (status != -ENOSPC) mlog_errno(status); goto bail; } credits = ocfs2_calc_group_alloc_credits(osb->sb, le16_to_cpu(cl->cl_cpg)); handle = ocfs2_start_trans(osb, credits); if (IS_ERR(handle)) { status = PTR_ERR(handle); handle = NULL; mlog_errno(status); goto bail; } if (last_alloc_group && *last_alloc_group != 0) { trace_ocfs2_block_group_alloc( (unsigned long long)*last_alloc_group); ac->ac_last_group = *last_alloc_group; } bg_bh = ocfs2_block_group_alloc_contig(osb, handle, alloc_inode, ac, cl); if (IS_ERR(bg_bh) && (PTR_ERR(bg_bh) == -ENOSPC)) bg_bh = ocfs2_block_group_alloc_discontig(handle, alloc_inode, ac, cl); if (IS_ERR(bg_bh)) { status = PTR_ERR(bg_bh); bg_bh = NULL; if (status != -ENOSPC) mlog_errno(status); goto bail; } bg = (struct ocfs2_group_desc *) bg_bh->b_data; status = ocfs2_journal_access_di(handle, INODE_CACHE(alloc_inode), bh, OCFS2_JOURNAL_ACCESS_WRITE); if (status < 0) { mlog_errno(status); goto bail; } alloc_rec = le16_to_cpu(bg->bg_chain); le32_add_cpu(&cl->cl_recs[alloc_rec].c_free, le16_to_cpu(bg->bg_free_bits_count)); le32_add_cpu(&cl->cl_recs[alloc_rec].c_total, le16_to_cpu(bg->bg_bits)); cl->cl_recs[alloc_rec].c_blkno = bg->bg_blkno; if (le16_to_cpu(cl->cl_next_free_rec) < le16_to_cpu(cl->cl_count)) le16_add_cpu(&cl->cl_next_free_rec, 1); le32_add_cpu(&fe->id1.bitmap1.i_used, le16_to_cpu(bg->bg_bits) - le16_to_cpu(bg->bg_free_bits_count)); le32_add_cpu(&fe->id1.bitmap1.i_total, le16_to_cpu(bg->bg_bits)); le32_add_cpu(&fe->i_clusters, le16_to_cpu(cl->cl_cpg)); ocfs2_journal_dirty(handle, bh); spin_lock(&OCFS2_I(alloc_inode)->ip_lock); OCFS2_I(alloc_inode)->ip_clusters = le32_to_cpu(fe->i_clusters); fe->i_size = cpu_to_le64(ocfs2_clusters_to_bytes(alloc_inode->i_sb, le32_to_cpu(fe->i_clusters))); spin_unlock(&OCFS2_I(alloc_inode)->ip_lock); i_size_write(alloc_inode, le64_to_cpu(fe->i_size)); alloc_inode->i_blocks = ocfs2_inode_sector_count(alloc_inode); ocfs2_update_inode_fsync_trans(handle, alloc_inode, 0); status = 0; /* save the new last alloc group so that the caller can cache it. */ if (last_alloc_group) *last_alloc_group = ac->ac_last_group; bail: if (handle) ocfs2_commit_trans(osb, handle); if (ac) ocfs2_free_alloc_context(ac); brelse(bg_bh); if (status) mlog_errno(status); return status; }