提交 e48edee2 编写于 作者: M Mark Fasheh

ocfs2: make room for unwritten extents flag

Due to the size of our group bitmaps, we'll never have a leaf node extent
record with more than 16 bits worth of clusters. Split e_clusters up so that
leaf nodes can get a flags field where we can mark unwritten extents.
Interior nodes whose length references all the child nodes beneath it can't
split their e_clusters field, so we use a union to preserve sizing there.
Signed-off-by: NMark Fasheh <mark.fasheh@oracle.com>
上级 6af67d82
...@@ -218,20 +218,32 @@ enum ocfs2_contig_type { ...@@ -218,20 +218,32 @@ enum ocfs2_contig_type {
CONTIG_RIGHT CONTIG_RIGHT
}; };
/*
* NOTE: ocfs2_block_extent_contig(), ocfs2_extents_adjacent() and
* ocfs2_extent_contig only work properly against leaf nodes!
*/
static int ocfs2_block_extent_contig(struct super_block *sb, static int ocfs2_block_extent_contig(struct super_block *sb,
struct ocfs2_extent_rec *ext, struct ocfs2_extent_rec *ext,
u64 blkno) u64 blkno)
{ {
return blkno == (le64_to_cpu(ext->e_blkno) + u64 blk_end = le64_to_cpu(ext->e_blkno);
ocfs2_clusters_to_blocks(sb,
le32_to_cpu(ext->e_clusters))); blk_end += ocfs2_clusters_to_blocks(sb,
le16_to_cpu(ext->e_leaf_clusters));
return blkno == blk_end;
} }
static int ocfs2_extents_adjacent(struct ocfs2_extent_rec *left, static int ocfs2_extents_adjacent(struct ocfs2_extent_rec *left,
struct ocfs2_extent_rec *right) struct ocfs2_extent_rec *right)
{ {
return (le32_to_cpu(left->e_cpos) + le32_to_cpu(left->e_clusters) == u32 left_range;
le32_to_cpu(right->e_cpos));
left_range = le32_to_cpu(left->e_cpos) +
le16_to_cpu(left->e_leaf_clusters);
return (left_range == le32_to_cpu(right->e_cpos));
} }
static enum ocfs2_contig_type static enum ocfs2_contig_type
...@@ -430,7 +442,7 @@ static inline u32 ocfs2_sum_rightmost_rec(struct ocfs2_extent_list *el) ...@@ -430,7 +442,7 @@ static inline u32 ocfs2_sum_rightmost_rec(struct ocfs2_extent_list *el)
i = le16_to_cpu(el->l_next_free_rec) - 1; i = le16_to_cpu(el->l_next_free_rec) - 1;
return le32_to_cpu(el->l_recs[i].e_cpos) + return le32_to_cpu(el->l_recs[i].e_cpos) +
le32_to_cpu(el->l_recs[i].e_clusters); ocfs2_rec_clusters(el, &el->l_recs[i]);
} }
/* /*
...@@ -442,7 +454,7 @@ static inline u32 ocfs2_sum_rightmost_rec(struct ocfs2_extent_list *el) ...@@ -442,7 +454,7 @@ static inline u32 ocfs2_sum_rightmost_rec(struct ocfs2_extent_list *el)
* for the new last extent block. * for the new last extent block.
* *
* the new branch will be 'empty' in the sense that every block will * the new branch will be 'empty' in the sense that every block will
* contain a single record with e_clusters == 0. * contain a single record with cluster count == 0.
*/ */
static int ocfs2_add_branch(struct ocfs2_super *osb, static int ocfs2_add_branch(struct ocfs2_super *osb,
handle_t *handle, handle_t *handle,
...@@ -532,7 +544,12 @@ static int ocfs2_add_branch(struct ocfs2_super *osb, ...@@ -532,7 +544,12 @@ static int ocfs2_add_branch(struct ocfs2_super *osb,
*/ */
eb_el->l_recs[0].e_cpos = cpu_to_le32(new_cpos); eb_el->l_recs[0].e_cpos = cpu_to_le32(new_cpos);
eb_el->l_recs[0].e_blkno = cpu_to_le64(next_blkno); eb_el->l_recs[0].e_blkno = cpu_to_le64(next_blkno);
eb_el->l_recs[0].e_clusters = cpu_to_le32(0); /*
* eb_el isn't always an interior node, but even leaf
* nodes want a zero'd flags and reserved field so
* this gets the whole 32 bits regardless of use.
*/
eb_el->l_recs[0].e_int_clusters = cpu_to_le32(0);
if (!eb_el->l_tree_depth) if (!eb_el->l_tree_depth)
new_last_eb_blk = le64_to_cpu(eb->h_blkno); new_last_eb_blk = le64_to_cpu(eb->h_blkno);
...@@ -577,7 +594,7 @@ static int ocfs2_add_branch(struct ocfs2_super *osb, ...@@ -577,7 +594,7 @@ static int ocfs2_add_branch(struct ocfs2_super *osb,
i = le16_to_cpu(el->l_next_free_rec); i = le16_to_cpu(el->l_next_free_rec);
el->l_recs[i].e_blkno = cpu_to_le64(next_blkno); el->l_recs[i].e_blkno = cpu_to_le64(next_blkno);
el->l_recs[i].e_cpos = cpu_to_le32(new_cpos); el->l_recs[i].e_cpos = cpu_to_le32(new_cpos);
el->l_recs[i].e_clusters = 0; el->l_recs[i].e_int_clusters = 0;
le16_add_cpu(&el->l_next_free_rec, 1); le16_add_cpu(&el->l_next_free_rec, 1);
/* fe needs a new last extent block pointer, as does the /* fe needs a new last extent block pointer, as does the
...@@ -662,11 +679,8 @@ static int ocfs2_shift_tree_depth(struct ocfs2_super *osb, ...@@ -662,11 +679,8 @@ static int ocfs2_shift_tree_depth(struct ocfs2_super *osb,
/* copy the fe data into the new extent block */ /* copy the fe data into the new extent block */
eb_el->l_tree_depth = fe_el->l_tree_depth; eb_el->l_tree_depth = fe_el->l_tree_depth;
eb_el->l_next_free_rec = fe_el->l_next_free_rec; eb_el->l_next_free_rec = fe_el->l_next_free_rec;
for(i = 0; i < le16_to_cpu(fe_el->l_next_free_rec); i++) { for(i = 0; i < le16_to_cpu(fe_el->l_next_free_rec); i++)
eb_el->l_recs[i].e_cpos = fe_el->l_recs[i].e_cpos; eb_el->l_recs[i] = fe_el->l_recs[i];
eb_el->l_recs[i].e_clusters = fe_el->l_recs[i].e_clusters;
eb_el->l_recs[i].e_blkno = fe_el->l_recs[i].e_blkno;
}
status = ocfs2_journal_dirty(handle, new_eb_bh); status = ocfs2_journal_dirty(handle, new_eb_bh);
if (status < 0) { if (status < 0) {
...@@ -687,12 +701,9 @@ static int ocfs2_shift_tree_depth(struct ocfs2_super *osb, ...@@ -687,12 +701,9 @@ static int ocfs2_shift_tree_depth(struct ocfs2_super *osb,
le16_add_cpu(&fe_el->l_tree_depth, 1); le16_add_cpu(&fe_el->l_tree_depth, 1);
fe_el->l_recs[0].e_cpos = 0; fe_el->l_recs[0].e_cpos = 0;
fe_el->l_recs[0].e_blkno = eb->h_blkno; fe_el->l_recs[0].e_blkno = eb->h_blkno;
fe_el->l_recs[0].e_clusters = cpu_to_le32(new_clusters); fe_el->l_recs[0].e_int_clusters = cpu_to_le32(new_clusters);
for(i = 1; i < le16_to_cpu(fe_el->l_next_free_rec); i++) { for(i = 1; i < le16_to_cpu(fe_el->l_next_free_rec); i++)
fe_el->l_recs[i].e_cpos = 0; memset(&fe_el->l_recs[i], 0, sizeof(struct ocfs2_extent_rec));
fe_el->l_recs[i].e_clusters = 0;
fe_el->l_recs[i].e_blkno = 0;
}
fe_el->l_next_free_rec = cpu_to_le16(1); fe_el->l_next_free_rec = cpu_to_le16(1);
/* If this is our 1st tree depth shift, then last_eb_blk /* If this is our 1st tree depth shift, then last_eb_blk
...@@ -817,9 +828,13 @@ static int ocfs2_find_branch_target(struct ocfs2_super *osb, ...@@ -817,9 +828,13 @@ static int ocfs2_find_branch_target(struct ocfs2_super *osb,
return status; return status;
} }
/*
* This is only valid for leaf nodes, which are the only ones that can
* have empty extents anyway.
*/
static inline int ocfs2_is_empty_extent(struct ocfs2_extent_rec *rec) static inline int ocfs2_is_empty_extent(struct ocfs2_extent_rec *rec)
{ {
return !rec->e_clusters; return !rec->e_leaf_clusters;
} }
/* /*
...@@ -930,6 +945,8 @@ static void ocfs2_create_empty_extent(struct ocfs2_extent_list *el) ...@@ -930,6 +945,8 @@ static void ocfs2_create_empty_extent(struct ocfs2_extent_list *el)
{ {
int next_free = le16_to_cpu(el->l_next_free_rec); int next_free = le16_to_cpu(el->l_next_free_rec);
BUG_ON(le16_to_cpu(el->l_tree_depth) != 0);
if (next_free == 0) if (next_free == 0)
goto set_and_inc; goto set_and_inc;
...@@ -1034,7 +1051,7 @@ static int __ocfs2_find_path(struct inode *inode, ...@@ -1034,7 +1051,7 @@ static int __ocfs2_find_path(struct inode *inode,
* rightmost record. * rightmost record.
*/ */
range = le32_to_cpu(rec->e_cpos) + range = le32_to_cpu(rec->e_cpos) +
le32_to_cpu(rec->e_clusters); ocfs2_rec_clusters(el, rec);
if (cpos >= le32_to_cpu(rec->e_cpos) && cpos < range) if (cpos >= le32_to_cpu(rec->e_cpos) && cpos < range)
break; break;
} }
...@@ -1195,21 +1212,21 @@ static void ocfs2_adjust_adjacent_records(struct ocfs2_extent_rec *left_rec, ...@@ -1195,21 +1212,21 @@ static void ocfs2_adjust_adjacent_records(struct ocfs2_extent_rec *left_rec,
*/ */
left_clusters = le32_to_cpu(right_child_el->l_recs[0].e_cpos); left_clusters = le32_to_cpu(right_child_el->l_recs[0].e_cpos);
left_clusters -= le32_to_cpu(left_rec->e_cpos); left_clusters -= le32_to_cpu(left_rec->e_cpos);
left_rec->e_clusters = cpu_to_le32(left_clusters); left_rec->e_int_clusters = cpu_to_le32(left_clusters);
/* /*
* Calculate the rightmost cluster count boundary before * Calculate the rightmost cluster count boundary before
* moving cpos - we will need to adjust e_clusters after * moving cpos - we will need to adjust clusters after
* updating e_cpos to keep the same highest cluster count. * updating e_cpos to keep the same highest cluster count.
*/ */
right_end = le32_to_cpu(right_rec->e_cpos); right_end = le32_to_cpu(right_rec->e_cpos);
right_end += le32_to_cpu(right_rec->e_clusters); right_end += le32_to_cpu(right_rec->e_int_clusters);
right_rec->e_cpos = left_rec->e_cpos; right_rec->e_cpos = left_rec->e_cpos;
le32_add_cpu(&right_rec->e_cpos, left_clusters); le32_add_cpu(&right_rec->e_cpos, left_clusters);
right_end -= le32_to_cpu(right_rec->e_cpos); right_end -= le32_to_cpu(right_rec->e_cpos);
right_rec->e_clusters = cpu_to_le32(right_end); right_rec->e_int_clusters = cpu_to_le32(right_end);
} }
/* /*
...@@ -1452,6 +1469,8 @@ static int ocfs2_find_cpos_for_left_leaf(struct super_block *sb, ...@@ -1452,6 +1469,8 @@ static int ocfs2_find_cpos_for_left_leaf(struct super_block *sb,
u64 blkno; u64 blkno;
struct ocfs2_extent_list *el; struct ocfs2_extent_list *el;
BUG_ON(path->p_tree_depth == 0);
*cpos = 0; *cpos = 0;
blkno = path_leaf_bh(path)->b_blocknr; blkno = path_leaf_bh(path)->b_blocknr;
...@@ -1486,7 +1505,9 @@ static int ocfs2_find_cpos_for_left_leaf(struct super_block *sb, ...@@ -1486,7 +1505,9 @@ static int ocfs2_find_cpos_for_left_leaf(struct super_block *sb,
} }
*cpos = le32_to_cpu(el->l_recs[j - 1].e_cpos); *cpos = le32_to_cpu(el->l_recs[j - 1].e_cpos);
*cpos = *cpos + le32_to_cpu(el->l_recs[j - 1].e_clusters) - 1; *cpos = *cpos + ocfs2_rec_clusters(el,
&el->l_recs[j - 1]);
*cpos = *cpos - 1;
goto out; goto out;
} }
} }
...@@ -1715,7 +1736,7 @@ static void ocfs2_insert_at_leaf(struct ocfs2_extent_rec *insert_rec, ...@@ -1715,7 +1736,7 @@ static void ocfs2_insert_at_leaf(struct ocfs2_extent_rec *insert_rec,
unsigned int range; unsigned int range;
struct ocfs2_extent_rec *rec; struct ocfs2_extent_rec *rec;
BUG_ON(el->l_tree_depth); BUG_ON(le16_to_cpu(el->l_tree_depth) != 0);
/* /*
* Contiguous insert - either left or right. * Contiguous insert - either left or right.
...@@ -1726,8 +1747,8 @@ static void ocfs2_insert_at_leaf(struct ocfs2_extent_rec *insert_rec, ...@@ -1726,8 +1747,8 @@ static void ocfs2_insert_at_leaf(struct ocfs2_extent_rec *insert_rec,
rec->e_blkno = insert_rec->e_blkno; rec->e_blkno = insert_rec->e_blkno;
rec->e_cpos = insert_rec->e_cpos; rec->e_cpos = insert_rec->e_cpos;
} }
le32_add_cpu(&rec->e_clusters, le16_add_cpu(&rec->e_leaf_clusters,
le32_to_cpu(insert_rec->e_clusters)); le16_to_cpu(insert_rec->e_leaf_clusters));
return; return;
} }
...@@ -1748,7 +1769,8 @@ static void ocfs2_insert_at_leaf(struct ocfs2_extent_rec *insert_rec, ...@@ -1748,7 +1769,8 @@ static void ocfs2_insert_at_leaf(struct ocfs2_extent_rec *insert_rec,
if (insert->ins_appending == APPEND_TAIL) { if (insert->ins_appending == APPEND_TAIL) {
i = le16_to_cpu(el->l_next_free_rec) - 1; i = le16_to_cpu(el->l_next_free_rec) - 1;
rec = &el->l_recs[i]; rec = &el->l_recs[i];
range = le32_to_cpu(rec->e_cpos) + le32_to_cpu(rec->e_clusters); range = le32_to_cpu(rec->e_cpos)
+ le16_to_cpu(rec->e_leaf_clusters);
BUG_ON(le32_to_cpu(insert_rec->e_cpos) < range); BUG_ON(le32_to_cpu(insert_rec->e_cpos) < range);
mlog_bug_on_msg(le16_to_cpu(el->l_next_free_rec) >= mlog_bug_on_msg(le16_to_cpu(el->l_next_free_rec) >=
...@@ -1761,9 +1783,9 @@ static void ocfs2_insert_at_leaf(struct ocfs2_extent_rec *insert_rec, ...@@ -1761,9 +1783,9 @@ static void ocfs2_insert_at_leaf(struct ocfs2_extent_rec *insert_rec,
le16_to_cpu(el->l_count), le16_to_cpu(el->l_count),
le16_to_cpu(el->l_next_free_rec), le16_to_cpu(el->l_next_free_rec),
le32_to_cpu(el->l_recs[i].e_cpos), le32_to_cpu(el->l_recs[i].e_cpos),
le32_to_cpu(el->l_recs[i].e_clusters), le16_to_cpu(el->l_recs[i].e_leaf_clusters),
le32_to_cpu(insert_rec->e_cpos), le32_to_cpu(insert_rec->e_cpos),
le32_to_cpu(insert_rec->e_clusters)); le16_to_cpu(insert_rec->e_leaf_clusters));
i++; i++;
el->l_recs[i] = *insert_rec; el->l_recs[i] = *insert_rec;
le16_add_cpu(&el->l_next_free_rec, 1); le16_add_cpu(&el->l_next_free_rec, 1);
...@@ -1805,6 +1827,12 @@ static int ocfs2_append_rec_to_path(struct inode *inode, handle_t *handle, ...@@ -1805,6 +1827,12 @@ static int ocfs2_append_rec_to_path(struct inode *inode, handle_t *handle,
*ret_left_path = NULL; *ret_left_path = NULL;
/*
* This shouldn't happen for non-trees. The extent rec cluster
* count manipulation below only works for interior nodes.
*/
BUG_ON(right_path->p_tree_depth == 0);
/* /*
* If our appending insert is at the leftmost edge of a leaf, * If our appending insert is at the leftmost edge of a leaf,
* then we might need to update the rightmost records of the * then we might need to update the rightmost records of the
...@@ -1863,6 +1891,8 @@ static int ocfs2_append_rec_to_path(struct inode *inode, handle_t *handle, ...@@ -1863,6 +1891,8 @@ static int ocfs2_append_rec_to_path(struct inode *inode, handle_t *handle,
bh = path_root_bh(right_path); bh = path_root_bh(right_path);
i = 0; i = 0;
while (1) { while (1) {
struct ocfs2_extent_rec *rec;
next_free = le16_to_cpu(el->l_next_free_rec); next_free = le16_to_cpu(el->l_next_free_rec);
if (next_free == 0) { if (next_free == 0) {
ocfs2_error(inode->i_sb, ocfs2_error(inode->i_sb,
...@@ -1872,16 +1902,19 @@ static int ocfs2_append_rec_to_path(struct inode *inode, handle_t *handle, ...@@ -1872,16 +1902,19 @@ static int ocfs2_append_rec_to_path(struct inode *inode, handle_t *handle,
goto out; goto out;
} }
el->l_recs[next_free - 1].e_clusters = insert_rec->e_cpos; rec = &el->l_recs[next_free - 1];
le32_add_cpu(&el->l_recs[next_free - 1].e_clusters,
le32_to_cpu(insert_rec->e_clusters)); rec->e_int_clusters = insert_rec->e_cpos;
le32_add_cpu(&el->l_recs[next_free - 1].e_clusters, le32_add_cpu(&rec->e_int_clusters,
-le32_to_cpu(el->l_recs[next_free - 1].e_cpos)); le16_to_cpu(insert_rec->e_leaf_clusters));
le32_add_cpu(&rec->e_int_clusters,
-le32_to_cpu(rec->e_cpos));
ret = ocfs2_journal_dirty(handle, bh); ret = ocfs2_journal_dirty(handle, bh);
if (ret) if (ret)
mlog_errno(ret); mlog_errno(ret);
/* Don't touch the leaf node */
if (++i >= right_path->p_tree_depth) if (++i >= right_path->p_tree_depth)
break; break;
...@@ -2068,7 +2101,7 @@ static int ocfs2_do_insert_extent(struct inode *inode, ...@@ -2068,7 +2101,7 @@ static int ocfs2_do_insert_extent(struct inode *inode,
out_update_clusters: out_update_clusters:
ocfs2_update_dinode_clusters(inode, di, ocfs2_update_dinode_clusters(inode, di,
le32_to_cpu(insert_rec->e_clusters)); le16_to_cpu(insert_rec->e_leaf_clusters));
ret = ocfs2_journal_dirty(handle, di_bh); ret = ocfs2_journal_dirty(handle, di_bh);
if (ret) if (ret)
...@@ -2089,6 +2122,8 @@ static void ocfs2_figure_contig_type(struct inode *inode, ...@@ -2089,6 +2122,8 @@ static void ocfs2_figure_contig_type(struct inode *inode,
int i; int i;
enum ocfs2_contig_type contig_type = CONTIG_NONE; enum ocfs2_contig_type contig_type = CONTIG_NONE;
BUG_ON(le16_to_cpu(el->l_tree_depth) != 0);
for(i = 0; i < le16_to_cpu(el->l_next_free_rec); i++) { for(i = 0; i < le16_to_cpu(el->l_next_free_rec); i++) {
contig_type = ocfs2_extent_contig(inode, &el->l_recs[i], contig_type = ocfs2_extent_contig(inode, &el->l_recs[i],
insert_rec); insert_rec);
...@@ -2120,7 +2155,7 @@ static void ocfs2_figure_appending_type(struct ocfs2_insert_type *insert, ...@@ -2120,7 +2155,7 @@ static void ocfs2_figure_appending_type(struct ocfs2_insert_type *insert,
insert->ins_appending = APPEND_NONE; insert->ins_appending = APPEND_NONE;
BUG_ON(el->l_tree_depth); BUG_ON(le16_to_cpu(el->l_tree_depth) != 0);
if (!el->l_next_free_rec) if (!el->l_next_free_rec)
goto set_tail_append; goto set_tail_append;
...@@ -2134,7 +2169,8 @@ static void ocfs2_figure_appending_type(struct ocfs2_insert_type *insert, ...@@ -2134,7 +2169,8 @@ static void ocfs2_figure_appending_type(struct ocfs2_insert_type *insert,
i = le16_to_cpu(el->l_next_free_rec) - 1; i = le16_to_cpu(el->l_next_free_rec) - 1;
rec = &el->l_recs[i]; rec = &el->l_recs[i];
if (cpos >= (le32_to_cpu(rec->e_cpos) + le32_to_cpu(rec->e_clusters))) if (cpos >=
(le32_to_cpu(rec->e_cpos) + le16_to_cpu(rec->e_leaf_clusters)))
goto set_tail_append; goto set_tail_append;
return; return;
...@@ -2242,7 +2278,7 @@ static int ocfs2_figure_insert_type(struct inode *inode, ...@@ -2242,7 +2278,7 @@ static int ocfs2_figure_insert_type(struct inode *inode,
* The insert code isn't quite ready to deal with all cases of * The insert code isn't quite ready to deal with all cases of
* left contiguousness. Specifically, if it's an insert into * left contiguousness. Specifically, if it's an insert into
* the 1st record in a leaf, it will require the adjustment of * the 1st record in a leaf, it will require the adjustment of
* e_clusters on the last record of the path directly to it's * cluster count on the last record of the path directly to it's
* left. For now, just catch that case and fool the layers * left. For now, just catch that case and fool the layers
* above us. This works just fine for tree_depth == 0, which * above us. This works just fine for tree_depth == 0, which
* is why we allow that above. * is why we allow that above.
...@@ -2310,9 +2346,10 @@ int ocfs2_insert_extent(struct ocfs2_super *osb, ...@@ -2310,9 +2346,10 @@ int ocfs2_insert_extent(struct ocfs2_super *osb,
(unsigned long long)OCFS2_I(inode)->ip_blkno, cpos, (unsigned long long)OCFS2_I(inode)->ip_blkno, cpos,
OCFS2_I(inode)->ip_clusters); OCFS2_I(inode)->ip_clusters);
memset(&rec, 0, sizeof(rec));
rec.e_cpos = cpu_to_le32(cpos); rec.e_cpos = cpu_to_le32(cpos);
rec.e_blkno = cpu_to_le64(start_blk); rec.e_blkno = cpu_to_le64(start_blk);
rec.e_clusters = cpu_to_le32(new_clusters); rec.e_leaf_clusters = cpu_to_le16(new_clusters);
status = ocfs2_figure_insert_type(inode, fe_bh, &last_eb_bh, &rec, status = ocfs2_figure_insert_type(inode, fe_bh, &last_eb_bh, &rec,
&insert); &insert);
...@@ -2981,7 +3018,7 @@ static int ocfs2_find_new_last_ext_blk(struct inode *inode, ...@@ -2981,7 +3018,7 @@ static int ocfs2_find_new_last_ext_blk(struct inode *inode,
* Check it we'll only be trimming off the end of this * Check it we'll only be trimming off the end of this
* cluster. * cluster.
*/ */
if (le16_to_cpu(rec->e_clusters) > clusters_to_del) if (le16_to_cpu(rec->e_leaf_clusters) > clusters_to_del)
goto out; goto out;
} }
...@@ -3061,11 +3098,11 @@ static int ocfs2_trim_tree(struct inode *inode, struct ocfs2_path *path, ...@@ -3061,11 +3098,11 @@ static int ocfs2_trim_tree(struct inode *inode, struct ocfs2_path *path,
mlog(0, "Extent list before: record %d: (%u, %u, %llu), " mlog(0, "Extent list before: record %d: (%u, %u, %llu), "
"next = %u\n", i, le32_to_cpu(rec->e_cpos), "next = %u\n", i, le32_to_cpu(rec->e_cpos),
le32_to_cpu(rec->e_clusters), ocfs2_rec_clusters(el, rec),
(unsigned long long)le64_to_cpu(rec->e_blkno), (unsigned long long)le64_to_cpu(rec->e_blkno),
le16_to_cpu(el->l_next_free_rec)); le16_to_cpu(el->l_next_free_rec));
BUG_ON(le32_to_cpu(rec->e_clusters) < clusters_to_del); BUG_ON(ocfs2_rec_clusters(el, rec) < clusters_to_del);
if (le16_to_cpu(el->l_tree_depth) == 0) { if (le16_to_cpu(el->l_tree_depth) == 0) {
/* /*
...@@ -3107,13 +3144,13 @@ static int ocfs2_trim_tree(struct inode *inode, struct ocfs2_path *path, ...@@ -3107,13 +3144,13 @@ static int ocfs2_trim_tree(struct inode *inode, struct ocfs2_path *path,
goto find_tail_record; goto find_tail_record;
} }
le32_add_cpu(&rec->e_clusters, -clusters_to_del); le16_add_cpu(&rec->e_leaf_clusters, -clusters_to_del);
/* /*
* We'll use "new_edge" on our way back up the * We'll use "new_edge" on our way back up the
* tree to know what our rightmost cpos is. * tree to know what our rightmost cpos is.
*/ */
new_edge = le32_to_cpu(rec->e_clusters); new_edge = le16_to_cpu(rec->e_leaf_clusters);
new_edge += le32_to_cpu(rec->e_cpos); new_edge += le32_to_cpu(rec->e_cpos);
/* /*
...@@ -3121,12 +3158,12 @@ static int ocfs2_trim_tree(struct inode *inode, struct ocfs2_path *path, ...@@ -3121,12 +3158,12 @@ static int ocfs2_trim_tree(struct inode *inode, struct ocfs2_path *path,
*/ */
*delete_start = le64_to_cpu(rec->e_blkno) *delete_start = le64_to_cpu(rec->e_blkno)
+ ocfs2_clusters_to_blocks(inode->i_sb, + ocfs2_clusters_to_blocks(inode->i_sb,
le32_to_cpu(rec->e_clusters)); le16_to_cpu(rec->e_leaf_clusters));
/* /*
* If it's now empty, remove this record. * If it's now empty, remove this record.
*/ */
if (le32_to_cpu(rec->e_clusters) == 0) { if (le16_to_cpu(rec->e_leaf_clusters) == 0) {
memset(rec, 0, memset(rec, 0,
sizeof(struct ocfs2_extent_rec)); sizeof(struct ocfs2_extent_rec));
le16_add_cpu(&el->l_next_free_rec, -1); le16_add_cpu(&el->l_next_free_rec, -1);
...@@ -3152,15 +3189,15 @@ static int ocfs2_trim_tree(struct inode *inode, struct ocfs2_path *path, ...@@ -3152,15 +3189,15 @@ static int ocfs2_trim_tree(struct inode *inode, struct ocfs2_path *path,
if (new_edge == 0) if (new_edge == 0)
goto delete; goto delete;
rec->e_clusters = cpu_to_le32(new_edge); rec->e_int_clusters = cpu_to_le32(new_edge);
le32_add_cpu(&rec->e_clusters, le32_add_cpu(&rec->e_int_clusters,
-le32_to_cpu(rec->e_cpos)); -le32_to_cpu(rec->e_cpos));
/* /*
* A deleted child record should have been * A deleted child record should have been
* caught above. * caught above.
*/ */
BUG_ON(le32_to_cpu(rec->e_clusters) == 0); BUG_ON(le32_to_cpu(rec->e_int_clusters) == 0);
} }
delete: delete:
...@@ -3173,7 +3210,7 @@ static int ocfs2_trim_tree(struct inode *inode, struct ocfs2_path *path, ...@@ -3173,7 +3210,7 @@ static int ocfs2_trim_tree(struct inode *inode, struct ocfs2_path *path,
mlog(0, "extent list container %llu, after: record %d: " mlog(0, "extent list container %llu, after: record %d: "
"(%u, %u, %llu), next = %u.\n", "(%u, %u, %llu), next = %u.\n",
(unsigned long long)bh->b_blocknr, i, (unsigned long long)bh->b_blocknr, i,
le32_to_cpu(rec->e_cpos), le32_to_cpu(rec->e_clusters), le32_to_cpu(rec->e_cpos), ocfs2_rec_clusters(el, rec),
(unsigned long long)le64_to_cpu(rec->e_blkno), (unsigned long long)le64_to_cpu(rec->e_blkno),
le16_to_cpu(el->l_next_free_rec)); le16_to_cpu(el->l_next_free_rec));
...@@ -3195,7 +3232,7 @@ static int ocfs2_trim_tree(struct inode *inode, struct ocfs2_path *path, ...@@ -3195,7 +3232,7 @@ static int ocfs2_trim_tree(struct inode *inode, struct ocfs2_path *path,
ocfs2_remove_from_cache(inode, bh); ocfs2_remove_from_cache(inode, bh);
BUG_ON(le32_to_cpu(el->l_recs[0].e_clusters)); BUG_ON(ocfs2_rec_clusters(el, &el->l_recs[0]));
BUG_ON(le32_to_cpu(el->l_recs[0].e_cpos)); BUG_ON(le32_to_cpu(el->l_recs[0].e_cpos));
BUG_ON(le64_to_cpu(el->l_recs[0].e_blkno)); BUG_ON(le64_to_cpu(el->l_recs[0].e_blkno));
...@@ -3283,7 +3320,7 @@ static int ocfs2_do_truncate(struct ocfs2_super *osb, ...@@ -3283,7 +3320,7 @@ static int ocfs2_do_truncate(struct ocfs2_super *osb,
* Lower levels depend on this never happening, but it's best * Lower levels depend on this never happening, but it's best
* to check it up here before changing the tree. * to check it up here before changing the tree.
*/ */
if (el->l_tree_depth && ocfs2_is_empty_extent(&el->l_recs[0])) { if (el->l_tree_depth && el->l_recs[0].e_int_clusters == 0) {
ocfs2_error(inode->i_sb, ocfs2_error(inode->i_sb,
"Inode %lu has an empty extent record, depth %u\n", "Inode %lu has an empty extent record, depth %u\n",
inode->i_ino, le16_to_cpu(el->l_tree_depth)); inode->i_ino, le16_to_cpu(el->l_tree_depth));
...@@ -3644,13 +3681,13 @@ int ocfs2_commit_truncate(struct ocfs2_super *osb, ...@@ -3644,13 +3681,13 @@ int ocfs2_commit_truncate(struct ocfs2_super *osb,
i = le16_to_cpu(el->l_next_free_rec) - 1; i = le16_to_cpu(el->l_next_free_rec) - 1;
range = le32_to_cpu(el->l_recs[i].e_cpos) + range = le32_to_cpu(el->l_recs[i].e_cpos) +
le32_to_cpu(el->l_recs[i].e_clusters); ocfs2_rec_clusters(el, &el->l_recs[i]);
if (i == 0 && ocfs2_is_empty_extent(&el->l_recs[i])) { if (i == 0 && ocfs2_is_empty_extent(&el->l_recs[i])) {
clusters_to_del = 0; clusters_to_del = 0;
} else if (le32_to_cpu(el->l_recs[i].e_cpos) >= new_highest_cpos) { } else if (le32_to_cpu(el->l_recs[i].e_cpos) >= new_highest_cpos) {
clusters_to_del = le32_to_cpu(el->l_recs[i].e_clusters); clusters_to_del = ocfs2_rec_clusters(el, &el->l_recs[i]);
} else if (range > new_highest_cpos) { } else if (range > new_highest_cpos) {
clusters_to_del = (le32_to_cpu(el->l_recs[i].e_clusters) + clusters_to_del = (ocfs2_rec_clusters(el, &el->l_recs[i]) +
le32_to_cpu(el->l_recs[i].e_cpos)) - le32_to_cpu(el->l_recs[i].e_cpos)) -
new_highest_cpos; new_highest_cpos;
} else { } else {
......
...@@ -85,4 +85,23 @@ int ocfs2_commit_truncate(struct ocfs2_super *osb, ...@@ -85,4 +85,23 @@ int ocfs2_commit_truncate(struct ocfs2_super *osb,
int ocfs2_find_leaf(struct inode *inode, struct ocfs2_extent_list *root_el, int ocfs2_find_leaf(struct inode *inode, struct ocfs2_extent_list *root_el,
u32 cpos, struct buffer_head **leaf_bh); u32 cpos, struct buffer_head **leaf_bh);
/*
* Helper function to look at the # of clusters in an extent record.
*/
static inline unsigned int ocfs2_rec_clusters(struct ocfs2_extent_list *el,
struct ocfs2_extent_rec *rec)
{
/*
* Cluster count in extent records is slightly different
* between interior nodes and leaf nodes. This is to support
* unwritten extents which need a flags field in leaf node
* records, thus shrinking the available space for a clusters
* field.
*/
if (el->l_tree_depth)
return le32_to_cpu(rec->e_int_clusters);
else
return le16_to_cpu(rec->e_leaf_clusters);
}
#endif /* OCFS2_ALLOC_H */ #endif /* OCFS2_ALLOC_H */
...@@ -50,13 +50,15 @@ static int ocfs2_search_extent_list(struct ocfs2_extent_list *el, ...@@ -50,13 +50,15 @@ static int ocfs2_search_extent_list(struct ocfs2_extent_list *el,
int ret = -1; int ret = -1;
int i; int i;
struct ocfs2_extent_rec *rec; struct ocfs2_extent_rec *rec;
u32 rec_end, rec_start; u32 rec_end, rec_start, clusters;
for(i = 0; i < le16_to_cpu(el->l_next_free_rec); i++) { for(i = 0; i < le16_to_cpu(el->l_next_free_rec); i++) {
rec = &el->l_recs[i]; rec = &el->l_recs[i];
rec_start = le32_to_cpu(rec->e_cpos); rec_start = le32_to_cpu(rec->e_cpos);
rec_end = rec_start + le32_to_cpu(rec->e_clusters); clusters = ocfs2_rec_clusters(el, rec);
rec_end = rec_start + clusters;
if (v_cluster >= rec_start && v_cluster < rec_end) { if (v_cluster >= rec_start && v_cluster < rec_end) {
ret = i; ret = i;
...@@ -98,6 +100,15 @@ int ocfs2_get_clusters(struct inode *inode, u32 v_cluster, ...@@ -98,6 +100,15 @@ int ocfs2_get_clusters(struct inode *inode, u32 v_cluster,
eb = (struct ocfs2_extent_block *) eb_bh->b_data; eb = (struct ocfs2_extent_block *) eb_bh->b_data;
el = &eb->h_list; el = &eb->h_list;
if (el->l_tree_depth) {
ocfs2_error(inode->i_sb,
"Inode %lu has non zero tree depth in "
"leaf block %llu\n", inode->i_ino,
(unsigned long long)eb_bh->b_blocknr);
ret = -EROFS;
goto out;
}
} }
i = ocfs2_search_extent_list(el, v_cluster); i = ocfs2_search_extent_list(el, v_cluster);
...@@ -118,7 +129,7 @@ int ocfs2_get_clusters(struct inode *inode, u32 v_cluster, ...@@ -118,7 +129,7 @@ int ocfs2_get_clusters(struct inode *inode, u32 v_cluster,
ocfs2_error(inode->i_sb, "Inode %lu has bad extent " ocfs2_error(inode->i_sb, "Inode %lu has bad extent "
"record (%u, %u, 0)", inode->i_ino, "record (%u, %u, 0)", inode->i_ino,
le32_to_cpu(rec->e_cpos), le32_to_cpu(rec->e_cpos),
le32_to_cpu(rec->e_clusters)); ocfs2_rec_clusters(el, rec));
ret = -EROFS; ret = -EROFS;
goto out; goto out;
} }
...@@ -130,7 +141,7 @@ int ocfs2_get_clusters(struct inode *inode, u32 v_cluster, ...@@ -130,7 +141,7 @@ int ocfs2_get_clusters(struct inode *inode, u32 v_cluster,
*p_cluster = *p_cluster + coff; *p_cluster = *p_cluster + coff;
if (num_clusters) if (num_clusters)
*num_clusters = le32_to_cpu(rec->e_clusters) - coff; *num_clusters = ocfs2_rec_clusters(el, rec) - coff;
} }
out: out:
......
...@@ -1127,7 +1127,6 @@ static int ocfs2_check_range_for_holes(struct inode *inode, loff_t pos, ...@@ -1127,7 +1127,6 @@ static int ocfs2_check_range_for_holes(struct inode *inode, loff_t pos,
size_t count) size_t count)
{ {
int ret = 0; int ret = 0;
unsigned int extent_flags;
u32 cpos, clusters, extent_len, phys_cpos; u32 cpos, clusters, extent_len, phys_cpos;
struct super_block *sb = inode->i_sb; struct super_block *sb = inode->i_sb;
...@@ -1135,14 +1134,13 @@ static int ocfs2_check_range_for_holes(struct inode *inode, loff_t pos, ...@@ -1135,14 +1134,13 @@ static int ocfs2_check_range_for_holes(struct inode *inode, loff_t pos,
clusters = ocfs2_clusters_for_bytes(sb, pos + count) - cpos; clusters = ocfs2_clusters_for_bytes(sb, pos + count) - cpos;
while (clusters) { while (clusters) {
ret = ocfs2_get_clusters(inode, cpos, &phys_cpos, &extent_len, ret = ocfs2_get_clusters(inode, cpos, &phys_cpos, &extent_len);
&extent_flags);
if (ret < 0) { if (ret < 0) {
mlog_errno(ret); mlog_errno(ret);
goto out; goto out;
} }
if (phys_cpos == 0 || (extent_flags & OCFS2_EXT_UNWRITTEN)) { if (phys_cpos == 0) {
ret = 1; ret = 1;
break; break;
} }
......
...@@ -390,7 +390,7 @@ static inline int ocfs2_calc_tree_trunc_credits(struct super_block *sb, ...@@ -390,7 +390,7 @@ static inline int ocfs2_calc_tree_trunc_credits(struct super_block *sb,
/* We may be deleting metadata blocks, so metadata alloc dinode + /* We may be deleting metadata blocks, so metadata alloc dinode +
one desc. block for each possible delete. */ one desc. block for each possible delete. */
if (tree_depth && next_free == 1 && if (tree_depth && next_free == 1 &&
le32_to_cpu(last_el->l_recs[i].e_clusters) == clusters_to_del) ocfs2_rec_clusters(last_el, &last_el->l_recs[i]) == clusters_to_del)
credits += 1 + tree_depth; credits += 1 + tree_depth;
/* update to the truncate log. */ /* update to the truncate log. */
......
...@@ -155,6 +155,12 @@ ...@@ -155,6 +155,12 @@
#define OCFS2_FL_VISIBLE (0x000100FF) /* User visible flags */ #define OCFS2_FL_VISIBLE (0x000100FF) /* User visible flags */
#define OCFS2_FL_MODIFIABLE (0x000100FF) /* User modifiable flags */ #define OCFS2_FL_MODIFIABLE (0x000100FF) /* User modifiable flags */
/*
* Extent record flags (e_node.leaf.flags)
*/
#define OCFS2_EXT_UNWRITTEN (0x01) /* Extent is allocated but
* unwritten */
/* /*
* ioctl commands * ioctl commands
*/ */
...@@ -283,10 +289,21 @@ static unsigned char ocfs2_type_by_mode[S_IFMT >> S_SHIFT] = { ...@@ -283,10 +289,21 @@ static unsigned char ocfs2_type_by_mode[S_IFMT >> S_SHIFT] = {
/* /*
* On disk extent record for OCFS2 * On disk extent record for OCFS2
* It describes a range of clusters on disk. * It describes a range of clusters on disk.
*
* Length fields are divided into interior and leaf node versions.
* This leaves room for a flags field (OCFS2_EXT_*) in the leaf nodes.
*/ */
struct ocfs2_extent_rec { struct ocfs2_extent_rec {
/*00*/ __le32 e_cpos; /* Offset into the file, in clusters */ /*00*/ __le32 e_cpos; /* Offset into the file, in clusters */
__le32 e_clusters; /* Clusters covered by this extent */ union {
__le32 e_int_clusters; /* Clusters covered by all children */
struct {
__le16 e_leaf_clusters; /* Clusters covered by this
extent */
__u8 e_reserved1;
__u8 e_flags; /* Extent flags */
};
};
__le64 e_blkno; /* Physical disk offset, in blocks */ __le64 e_blkno; /* Physical disk offset, in blocks */
/*10*/ /*10*/
}; };
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册