diff options
Diffstat (limited to 'fs/ocfs2/alloc.c')
| -rw-r--r-- | fs/ocfs2/alloc.c | 85 |
1 files changed, 52 insertions, 33 deletions
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index 4414743b638e..6e5fd3f12a84 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c @@ -10,6 +10,7 @@ #include <linux/fs.h> #include <linux/types.h> #include <linux/slab.h> +#include <linux/string.h> #include <linux/highmem.h> #include <linux/swap.h> #include <linux/quotaops.h> @@ -685,7 +686,7 @@ static struct ocfs2_path *ocfs2_new_path(struct buffer_head *root_bh, BUG_ON(le16_to_cpu(root_el->l_tree_depth) >= OCFS2_MAX_PATH_DEPTH); - path = kzalloc(sizeof(*path), GFP_NOFS); + path = kzalloc_obj(*path, GFP_NOFS); if (path) { path->p_tree_depth = le16_to_cpu(root_el->l_tree_depth); get_bh(root_bh); @@ -916,11 +917,32 @@ static int ocfs2_validate_extent_block(struct super_block *sb, goto bail; } - if (le32_to_cpu(eb->h_fs_generation) != OCFS2_SB(sb)->fs_generation) + if (le32_to_cpu(eb->h_fs_generation) != OCFS2_SB(sb)->fs_generation) { rc = ocfs2_error(sb, "Extent block #%llu has an invalid h_fs_generation of #%u\n", (unsigned long long)bh->b_blocknr, le32_to_cpu(eb->h_fs_generation)); + goto bail; + } + + if (le16_to_cpu(eb->h_list.l_count) != ocfs2_extent_recs_per_eb(sb)) { + rc = ocfs2_error(sb, + "Extent block #%llu has invalid l_count %u (expected %u)\n", + (unsigned long long)bh->b_blocknr, + le16_to_cpu(eb->h_list.l_count), + ocfs2_extent_recs_per_eb(sb)); + goto bail; + } + + if (le16_to_cpu(eb->h_list.l_next_free_rec) > le16_to_cpu(eb->h_list.l_count)) { + rc = ocfs2_error(sb, + "Extent block #%llu has invalid l_next_free_rec %u (l_count %u)\n", + (unsigned long long)bh->b_blocknr, + le16_to_cpu(eb->h_list.l_next_free_rec), + le16_to_cpu(eb->h_list.l_count)); + goto bail; + } + bail: return rc; } @@ -1037,7 +1059,7 @@ static int ocfs2_create_new_meta_bhs(handle_t *handle, memset(bhs[i]->b_data, 0, osb->sb->s_blocksize); eb = (struct ocfs2_extent_block *) bhs[i]->b_data; /* Ok, setup the minimal stuff here. */ - strcpy(eb->h_signature, OCFS2_EXTENT_BLOCK_SIGNATURE); + strscpy(eb->h_signature, OCFS2_EXTENT_BLOCK_SIGNATURE); eb->h_blkno = cpu_to_le64(first_blkno); eb->h_fs_generation = cpu_to_le32(osb->fs_generation); eb->h_suballoc_slot = @@ -1201,8 +1223,7 @@ static int ocfs2_add_branch(handle_t *handle, } /* allocate the number of new eb blocks we need */ - new_eb_bhs = kcalloc(new_blocks, sizeof(struct buffer_head *), - GFP_KERNEL); + new_eb_bhs = kzalloc_objs(struct buffer_head *, new_blocks); if (!new_eb_bhs) { status = -ENOMEM; mlog_errno(status); @@ -1803,14 +1824,23 @@ static int __ocfs2_find_path(struct ocfs2_caching_info *ci, el = root_el; while (el->l_tree_depth) { - if (le16_to_cpu(el->l_next_free_rec) == 0) { + if (unlikely(le16_to_cpu(el->l_tree_depth) >= OCFS2_MAX_PATH_DEPTH)) { ocfs2_error(ocfs2_metadata_cache_get_super(ci), - "Owner %llu has empty extent list at depth %u\n", + "Owner %llu has invalid tree depth %u in extent list\n", (unsigned long long)ocfs2_metadata_cache_owner(ci), le16_to_cpu(el->l_tree_depth)); ret = -EROFS; goto out; - + } + if (!el->l_next_free_rec || !el->l_count) { + ocfs2_error(ocfs2_metadata_cache_get_super(ci), + "Owner %llu has empty extent list at depth %u\n" + "(next free=%u count=%u)\n", + (unsigned long long)ocfs2_metadata_cache_owner(ci), + le16_to_cpu(el->l_tree_depth), + le16_to_cpu(el->l_next_free_rec), le16_to_cpu(el->l_count)); + ret = -EROFS; + goto out; } for(i = 0; i < le16_to_cpu(el->l_next_free_rec) - 1; i++) { @@ -1848,18 +1878,6 @@ static int __ocfs2_find_path(struct ocfs2_caching_info *ci, eb = (struct ocfs2_extent_block *) bh->b_data; el = &eb->h_list; - if (le16_to_cpu(el->l_next_free_rec) > - le16_to_cpu(el->l_count)) { - ocfs2_error(ocfs2_metadata_cache_get_super(ci), - "Owner %llu has bad count in extent list at block %llu (next free=%u, count=%u)\n", - (unsigned long long)ocfs2_metadata_cache_owner(ci), - (unsigned long long)bh->b_blocknr, - le16_to_cpu(el->l_next_free_rec), - le16_to_cpu(el->l_count)); - ret = -EROFS; - goto out; - } - if (func) func(data, bh); } @@ -3646,7 +3664,6 @@ static int ocfs2_merge_rec_left(struct ocfs2_path *right_path, * So we use the new rightmost path. */ ocfs2_mv_path(right_path, left_path); - left_path = NULL; } else ocfs2_complete_edge_insert(handle, left_path, right_path, subtree_index); @@ -6156,7 +6173,7 @@ static int ocfs2_get_truncate_log_info(struct ocfs2_super *osb, struct buffer_head *bh = NULL; struct ocfs2_dinode *di; struct ocfs2_truncate_log *tl; - unsigned int tl_count; + unsigned int tl_count, tl_used; inode = ocfs2_get_system_file_inode(osb, TRUNCATE_LOG_SYSTEM_INODE, @@ -6177,8 +6194,10 @@ static int ocfs2_get_truncate_log_info(struct ocfs2_super *osb, di = (struct ocfs2_dinode *)bh->b_data; tl = &di->id2.i_dealloc; tl_count = le16_to_cpu(tl->tl_count); + tl_used = le16_to_cpu(tl->tl_used); if (unlikely(tl_count > ocfs2_truncate_recs_per_inode(osb->sb) || - tl_count == 0)) { + tl_count == 0 || + tl_used > tl_count)) { status = -EFSCORRUPTED; iput(inode); brelse(bh); @@ -6482,7 +6501,7 @@ int ocfs2_cache_cluster_dealloc(struct ocfs2_cached_dealloc_ctxt *ctxt, int ret = 0; struct ocfs2_cached_block_free *item; - item = kzalloc(sizeof(*item), GFP_NOFS); + item = kzalloc_obj(*item, GFP_NOFS); if (item == NULL) { ret = -ENOMEM; mlog_errno(ret); @@ -6608,7 +6627,7 @@ ocfs2_find_per_slot_free_list(int type, fl = fl->f_next_suballocator; } - fl = kmalloc(sizeof(*fl), GFP_NOFS); + fl = kmalloc_obj(*fl, GFP_NOFS); if (fl) { fl->f_inode_type = type; fl->f_slot = slot; @@ -6736,7 +6755,7 @@ static int ocfs2_reuse_blk_from_dealloc(handle_t *handle, /* We can't guarantee that buffer head is still cached, so * polutlate the extent block again. */ - strcpy(eb->h_signature, OCFS2_EXTENT_BLOCK_SIGNATURE); + strscpy(eb->h_signature, OCFS2_EXTENT_BLOCK_SIGNATURE); eb->h_blkno = cpu_to_le64(bf->free_blk); eb->h_fs_generation = cpu_to_le32(osb->fs_generation); eb->h_suballoc_slot = cpu_to_le16(real_slot); @@ -6783,7 +6802,7 @@ int ocfs2_cache_block_dealloc(struct ocfs2_cached_dealloc_ctxt *ctxt, goto out; } - item = kzalloc(sizeof(*item), GFP_NOFS); + item = kzalloc_obj(*item, GFP_NOFS); if (item == NULL) { ret = -ENOMEM; mlog_errno(ret); @@ -6884,7 +6903,7 @@ static void ocfs2_zero_cluster_folios(struct inode *inode, loff_t start, ocfs2_map_and_dirty_folio(inode, handle, from, to, folio, 1, &phys); - start = folio_next_index(folio) << PAGE_SHIFT; + start = folio_next_pos(folio); } out: if (folios) @@ -6910,6 +6929,7 @@ static int ocfs2_grab_folios(struct inode *inode, loff_t start, loff_t end, if (IS_ERR(folios[numfolios])) { ret = PTR_ERR(folios[numfolios]); mlog_errno(ret); + folios[numfolios] = NULL; goto out; } @@ -6919,8 +6939,7 @@ static int ocfs2_grab_folios(struct inode *inode, loff_t start, loff_t end, out: if (ret != 0) { - if (folios) - ocfs2_unlock_and_free_folios(folios, numfolios); + ocfs2_unlock_and_free_folios(folios, numfolios); numfolios = 0; } @@ -6973,8 +6992,8 @@ int ocfs2_zero_range_for_truncate(struct inode *inode, handle_t *handle, if (range_start >= range_end) return 0; - folios = kcalloc(ocfs2_pages_per_cluster(sb), - sizeof(struct folio *), GFP_NOFS); + folios = kzalloc_objs(struct folio *, ocfs2_pages_per_cluster(sb), + GFP_NOFS); if (folios == NULL) { ret = -ENOMEM; mlog_errno(ret); @@ -7308,7 +7327,7 @@ start: * to check it up here before changing the tree. */ if (root_el->l_tree_depth && rec->e_int_clusters == 0) { - mlog(ML_ERROR, "Inode %lu has an empty " + mlog(ML_ERROR, "Inode %llu has an empty " "extent record, depth %u\n", inode->i_ino, le16_to_cpu(root_el->l_tree_depth)); status = ocfs2_remove_rightmost_empty_extent(osb, |
