Commit e48edee2 authored by Mark Fasheh's avatar 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: default avatarMark Fasheh <mark.fasheh@oracle.com>
parent 6af67d82
This diff is collapsed.
......@@ -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,
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 */
......@@ -50,13 +50,15 @@ static int ocfs2_search_extent_list(struct ocfs2_extent_list *el,
int ret = -1;
int i;
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++) {
rec = &el->l_recs[i];
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) {
ret = i;
......@@ -98,6 +100,15 @@ int ocfs2_get_clusters(struct inode *inode, u32 v_cluster,
eb = (struct ocfs2_extent_block *) eb_bh->b_data;
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);
......@@ -118,7 +129,7 @@ int ocfs2_get_clusters(struct inode *inode, u32 v_cluster,
ocfs2_error(inode->i_sb, "Inode %lu has bad extent "
"record (%u, %u, 0)", inode->i_ino,
le32_to_cpu(rec->e_cpos),
le32_to_cpu(rec->e_clusters));
ocfs2_rec_clusters(el, rec));
ret = -EROFS;
goto out;
}
......@@ -130,7 +141,7 @@ int ocfs2_get_clusters(struct inode *inode, u32 v_cluster,
*p_cluster = *p_cluster + coff;
if (num_clusters)
*num_clusters = le32_to_cpu(rec->e_clusters) - coff;
*num_clusters = ocfs2_rec_clusters(el, rec) - coff;
}
out:
......
......@@ -1127,7 +1127,6 @@ static int ocfs2_check_range_for_holes(struct inode *inode, loff_t pos,
size_t count)
{
int ret = 0;
unsigned int extent_flags;
u32 cpos, clusters, extent_len, phys_cpos;
struct super_block *sb = inode->i_sb;
......@@ -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;
while (clusters) {
ret = ocfs2_get_clusters(inode, cpos, &phys_cpos, &extent_len,
&extent_flags);
ret = ocfs2_get_clusters(inode, cpos, &phys_cpos, &extent_len);
if (ret < 0) {
mlog_errno(ret);
goto out;
}
if (phys_cpos == 0 || (extent_flags & OCFS2_EXT_UNWRITTEN)) {
if (phys_cpos == 0) {
ret = 1;
break;
}
......
......@@ -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 +
one desc. block for each possible delete. */
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;
/* update to the truncate log. */
......
......@@ -155,6 +155,12 @@
#define OCFS2_FL_VISIBLE (0x000100FF) /* User visible 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
*/
......@@ -283,10 +289,21 @@ static unsigned char ocfs2_type_by_mode[S_IFMT >> S_SHIFT] = {
/*
* On disk extent record for OCFS2
* 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 {
/*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 */
/*10*/
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment