[Ocfs2-devel] [PATCH 2/3] Ocfs2: Fix punching hole codes to correctly do CoW during cluster zeroing.

tristan tristan.ye at oracle.com
Thu Feb 4 19:10:11 PST 2010


Tao Ma wrote:
> Hi tristan,
>
> Tristan Ye wrote:
>> Based on the former patch of truncating optimization, bugfix for 
>> refcount on
>> punching holes can be fairly easy and straightforward since most of 
>> work we
>> should take into account for refcounting have been completed already 
>> in func
>> ocfs2_remove_btree_range(), which is also being used by our 
>> truncating codes.
>>
>> The patch just did CoW for reflinks when a hole is being punched 
>> whose start
>> and end offset were within one cluster, which means partial zeroing 
>> for a cluster
>> will be performed soon.
>>
>> The patch has been tested fixing the following bug:
>>
>> http://oss.oracle.com/bugzilla/show_bug.cgi?id=1216
>>
>> Signed-off-by: Tristan Ye <tristan.ye at oracle.com>
>> ---
>>  fs/ocfs2/file.c |   56 
>> +++++++++++++++++++++++++++++++++++++++++++++++++++++-
>>  1 files changed, 54 insertions(+), 2 deletions(-)
>>
>> diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
>> index e0c9d1c..85911a9 100644
>> --- a/fs/ocfs2/file.c
>> +++ b/fs/ocfs2/file.c
>> @@ -1427,12 +1427,17 @@ static int ocfs2_remove_inode_range(struct 
>> inode *inode,
>>                      struct buffer_head *di_bh, u64 byte_start,
>>                      u64 byte_len)
>>  {
>> -    int ret = 0;
>> +    int ret = 0, flags = 0, i;
>>      u32 trunc_start, trunc_len, cpos, phys_cpos, alloc_size;
>>      struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
>>      struct ocfs2_cached_dealloc_ctxt dealloc;
>>      struct address_space *mapping = inode->i_mapping;
>>      struct ocfs2_extent_tree et;
>> +    struct ocfs2_path *path = NULL;
>> +    struct ocfs2_extent_list *el = NULL;
>> +    struct ocfs2_extent_rec *rec = NULL;
>> +    struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
>> +    u64 refcount_loc = le64_to_cpu(di->i_refcount_loc);
>>  
>>      ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(inode), di_bh);
>>      ocfs2_init_dealloc_ctxt(&dealloc);
>> @@ -1458,6 +1463,27 @@ static int ocfs2_remove_inode_range(struct 
>> inode *inode,
>>          goto out;
>>      }
>>  
>> +    /*
>> +     * For reflinks, we may need to CoW 2 clusters which might be
>> +     * partially zero'd later, if hole's start and end offset were
>> +     * within one cluster(means is not exactly aligned to clustersize).
>> +     */
>> +
>> +    if (OCFS2_I(inode)->ip_dyn_features & OCFS2_HAS_REFCOUNT_FL) {
>> +
>> +        ret = ocfs2_cow_file_pos(inode, di_bh, byte_start);
>> +        if (ret) {
>> +            mlog_errno(ret);
>> +            goto out;
>> +        }
>> +
>> +        ret = ocfs2_cow_file_pos(inode, di_bh, byte_start + byte_len);
>> +        if (ret) {
>> +            mlog_errno(ret);
>> +            goto out;
>> +        }
>> +    }
>> +
>>      trunc_start = ocfs2_clusters_for_bytes(osb->sb, byte_start);
>>      trunc_len = (byte_start + byte_len) >> osb->s_clustersize_bits;
>>      if (trunc_len >= trunc_start)
>> @@ -1476,6 +1502,13 @@ static int ocfs2_remove_inode_range(struct 
>> inode *inode,
>>          goto out;
>>      }
>>  
>> +    path = ocfs2_new_path_from_et(&et);
>> +    if (!path) {
>> +        ret = -ENOMEM;
>> +        mlog_errno(ret);
>> +        goto out;
>> +    }
>> +
>>      cpos = trunc_start;
>>      while (trunc_len) {
>>          ret = ocfs2_get_clusters(inode, cpos, &phys_cpos,
>> @@ -1488,11 +1521,28 @@ static int ocfs2_remove_inode_range(struct 
>> inode *inode,
>>          if (alloc_size > trunc_len)
>>              alloc_size = trunc_len;
>>  
>> +        ret = ocfs2_find_path(INODE_CACHE(inode), path, cpos);
>> +        if (ret) {
>> +            mlog_errno(ret);
>> +            goto out;
>> +        }
>> +
>> +        el = path_leaf_el(path);
>> +
>> +        for (i = le16_to_cpu(el->l_next_free_rec) - 1; i >= 0; i--) {
>> +            rec = &el->l_recs[i];
>> +            if (le32_to_cpu(rec->e_cpos) <= cpos)
>> +                break;
>> +        }
>> +
>> +        flags = rec->e_flags;
>> +
> uh, you implement all these while only wanting to get the flags for 
> the record I guess?
> ocfs2_get_clusters have a parameter *extent_flags, just pass it in and 
> It will give you the flags you want.

Oh, You're definitely right...all I want is just a flag, that's a good 
shortcut.


>>          /* Only do work for non-holes */
>>          if (phys_cpos != 0) {
>>              ret = ocfs2_remove_btree_range(inode, &et, cpos,
>>                                 phys_cpos, alloc_size,
>> -                               &dealloc, 0, 0);
>> +                               &dealloc, refcount_loc,
>> +                               flags);
>>              if (ret) {
>>                  mlog_errno(ret);
>>                  goto out;
>
> Regards,
> Tao




More information about the Ocfs2-devel mailing list