On Thu, Nov 27, 2008 at 09:23:52AM +0800, Tao Ma wrote:
> ocfs2_xattr_value_update_size only access the first_bh, update the size  
> and then dirty it. Since you now access and dirty the whole bucket, I  
> think maybe you can just remove this function and move the size update 
> here.

        Good point.  Here's an updated version.

diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
index 7e0d62a..aae4fe2 100644
--- a/fs/ocfs2/xattr.c
+++ b/fs/ocfs2/xattr.c
@@ -4586,31 +4586,6 @@ out:
        return ret;
 }
 
-static int ocfs2_xattr_value_update_size(struct inode *inode,
-                                        handle_t *handle,
-                                        struct buffer_head *xe_bh,
-                                        struct ocfs2_xattr_entry *xe,
-                                        u64 new_size)
-{
-       int ret;
-
-       ret = ocfs2_journal_access(handle, inode, xe_bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
-       if (ret < 0) {
-               mlog_errno(ret);
-               goto out;
-       }
-
-       xe->xe_value_size = cpu_to_le64(new_size);
-
-       ret = ocfs2_journal_dirty(handle, xe_bh);
-       if (ret < 0)
-               mlog_errno(ret);
-
-out:
-       return ret;
-}
-
 /*
  * Truncate the specified xe_off entry in xattr bucket.
  * bucket is indicated by header_bh and len is the new length.
@@ -4619,7 +4594,7 @@ out:
  * Copy the new updated xe and xe_value_root to new_xe and new_xv if needed.
  */
 static int ocfs2_xattr_bucket_value_truncate(struct inode *inode,
-                                            struct buffer_head *header_bh,
+                                            struct ocfs2_xattr_bucket *bucket,
                                             int xe_off,
                                             int len,
                                             struct ocfs2_xattr_set_ctxt *ctxt)
@@ -4629,8 +4604,7 @@ static int ocfs2_xattr_bucket_value_truncate(struct inode 
*inode,
        struct buffer_head *value_bh = NULL;
        struct ocfs2_xattr_value_root *xv;
        struct ocfs2_xattr_entry *xe;
-       struct ocfs2_xattr_header *xh =
-                       (struct ocfs2_xattr_header *)header_bh->b_data;
+       struct ocfs2_xattr_header *xh = bucket_xh(bucket);
        size_t blocksize = inode->i_sb->s_blocksize;
 
        xe = &xh->xh_entries[xe_off];
@@ -4644,34 +4618,41 @@ static int ocfs2_xattr_bucket_value_truncate(struct 
inode *inode,
 
        /* We don't allow ocfs2_xattr_value to be stored in different block. */
        BUG_ON(value_blk != (offset + OCFS2_XATTR_ROOT_SIZE - 1) / blocksize);
-       value_blk += header_bh->b_blocknr;
 
-       ret = ocfs2_read_block(inode, value_blk, &value_bh, NULL);
-       if (ret) {
-               mlog_errno(ret);
-               goto out;
-       }
+       value_bh = bucket->bu_bhs[value_blk];
+       BUG_ON(!value_bh);
 
        xv = (struct ocfs2_xattr_value_root *)
                (value_bh->b_data + offset % blocksize);
 
-       mlog(0, "truncate %u in xattr bucket %llu to %d bytes.\n",
-            xe_off, (unsigned long long)header_bh->b_blocknr, len);
-       ret = ocfs2_xattr_value_truncate(inode, value_bh, xv, len, ctxt);
+       ret = ocfs2_xattr_bucket_journal_access(ctxt->handle, bucket,
+                                               OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                mlog_errno(ret);
                goto out;
        }
 
-       ret = ocfs2_xattr_value_update_size(inode, ctxt->handle,
-                                           header_bh, xe, len);
+       /*
+        * From here on out we have to dirty the bucket.  The generic
+        * value calls only modify one of the bucket's bhs, but we need
+        * to send the bucket at once.  So if they error, they *could* have
+        * modified something.  We have to assume they did, and dirty
+        * the whole bucket.  This leaves us in a consistent state.
+        */
+       mlog(0, "truncate %u in xattr bucket %llu to %d bytes.\n",
+            xe_off, (unsigned long long)bucket_blkno(bucket), len);
+       ret = ocfs2_xattr_value_truncate(inode, value_bh, xv, len, ctxt);
        if (ret) {
                mlog_errno(ret);
-               goto out;
+               goto out_dirty;
        }
 
+       xe->xe_value_size = cpu_to_le64(len);
+
+out_dirty:
+       ocfs2_xattr_bucket_journal_dirty(ctxt->handle, bucket);
+
 out:
-       brelse(value_bh);
        return ret;
 }
 
@@ -4687,7 +4668,7 @@ static int ocfs2_xattr_bucket_value_truncate_xs(struct 
inode *inode,
        BUG_ON(!xs->bucket->bu_bhs[0] || !xe || ocfs2_xattr_is_local(xe));
 
        offset = xe - xh->xh_entries;
-       ret = ocfs2_xattr_bucket_value_truncate(inode, xs->bucket->bu_bhs[0],
+       ret = ocfs2_xattr_bucket_value_truncate(inode, xs->bucket,
                                                offset, len, ctxt);
        if (ret)
                mlog_errno(ret);
@@ -5129,8 +5110,7 @@ static int ocfs2_delete_xattr_in_bucket(struct inode 
*inode,
                if (ocfs2_xattr_is_local(xe))
                        continue;
 
-               ret = ocfs2_xattr_bucket_value_truncate(inode,
-                                                       bucket->bu_bhs[0],
+               ret = ocfs2_xattr_bucket_value_truncate(inode, bucket,
                                                        i, 0, &ctxt);
                if (ret) {
                        mlog_errno(ret);
-- 

Life's Little Instruction Book #347

        "Never waste the oppourtunity to tell someone you love them."

Joel Becker
Principal Software Developer
Oracle
E-mail: [EMAIL PROTECTED]
Phone: (650) 506-8127

_______________________________________________
Ocfs2-devel mailing list
[email protected]
http://oss.oracle.com/mailman/listinfo/ocfs2-devel

Reply via email to