summaryrefslogtreecommitdiff
path: root/fs/ocfs2/alloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ocfs2/alloc.c')
-rw-r--r--fs/ocfs2/alloc.c85
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,