ocfs2: Teach ocfs2_xa_loc how to do its own journal work
authorJoel Becker <joel.becker@oracle.com>
Tue, 18 Aug 2009 20:52:38 +0000 (13:52 -0700)
committerJoel Becker <joel.becker@oracle.com>
Fri, 26 Feb 2010 23:41:11 +0000 (15:41 -0800)
We're going to want to make sure our buffers get accessed and dirtied
correctly.  So have the xa_loc do the work.  This includes storing the
inode on ocfs2_xa_loc.

Signed-off-by: Joel Becker <joel.becker@oracle.com>
fs/ocfs2/xattr.c

index e0d0fa2..fbec116 100644 (file)
@@ -142,6 +142,13 @@ struct ocfs2_xattr_search {
 struct ocfs2_xa_loc;
 struct ocfs2_xa_loc_operations {
        /*
+        * Journal functions
+        */
+       int (*xlo_journal_access)(handle_t *handle, struct ocfs2_xa_loc *loc,
+                                 int type);
+       void (*xlo_journal_dirty)(handle_t *handle, struct ocfs2_xa_loc *loc);
+
+       /*
         * Return a pointer to the appropriate buffer in loc->xl_storage
         * at the given offset from loc->xl_header.
         */
@@ -186,6 +193,9 @@ struct ocfs2_xa_loc_operations {
  * tracking the on-disk structure.
  */
 struct ocfs2_xa_loc {
+       /* This xattr belongs to this inode */
+       struct inode *xl_inode;
+
        /* The ocfs2_xattr_header inside the on-disk storage. Not NULL. */
        struct ocfs2_xattr_header *xl_header;
 
@@ -1540,6 +1550,17 @@ static int ocfs2_xa_check_space_helper(int needed_space, int free_start,
        return 0;
 }
 
+static int ocfs2_xa_journal_access(handle_t *handle, struct ocfs2_xa_loc *loc,
+                                  int type)
+{
+       return loc->xl_ops->xlo_journal_access(handle, loc, type);
+}
+
+static void ocfs2_xa_journal_dirty(handle_t *handle, struct ocfs2_xa_loc *loc)
+{
+       loc->xl_ops->xlo_journal_dirty(handle, loc);
+}
+
 /* Give a pointer into the storage for the given offset */
 static void *ocfs2_xa_offset_pointer(struct ocfs2_xa_loc *loc, int offset)
 {
@@ -1629,6 +1650,29 @@ static void ocfs2_xa_fill_value_buf(struct ocfs2_xa_loc *loc,
                                                        name_size);
 }
 
+static int ocfs2_xa_block_journal_access(handle_t *handle,
+                                        struct ocfs2_xa_loc *loc, int type)
+{
+       struct buffer_head *bh = loc->xl_storage;
+       ocfs2_journal_access_func access;
+
+       if (loc->xl_size == (bh->b_size -
+                            offsetof(struct ocfs2_xattr_block,
+                                     xb_attrs.xb_header)))
+               access = ocfs2_journal_access_xb;
+       else
+               access = ocfs2_journal_access_di;
+       return access(handle, INODE_CACHE(loc->xl_inode), bh, type);
+}
+
+static void ocfs2_xa_block_journal_dirty(handle_t *handle,
+                                        struct ocfs2_xa_loc *loc)
+{
+       struct buffer_head *bh = loc->xl_storage;
+
+       ocfs2_journal_dirty(handle, bh);
+}
+
 static void *ocfs2_xa_block_offset_pointer(struct ocfs2_xa_loc *loc,
                                           int offset)
 {
@@ -1755,6 +1799,8 @@ static void ocfs2_xa_block_fill_value_buf(struct ocfs2_xa_loc *loc,
  * storage and unindexed ocfs2_xattr_blocks.
  */
 static const struct ocfs2_xa_loc_operations ocfs2_xa_block_loc_ops = {
+       .xlo_journal_access     = ocfs2_xa_block_journal_access,
+       .xlo_journal_dirty      = ocfs2_xa_block_journal_dirty,
        .xlo_offset_pointer     = ocfs2_xa_block_offset_pointer,
        .xlo_check_space        = ocfs2_xa_block_check_space,
        .xlo_can_reuse          = ocfs2_xa_block_can_reuse,
@@ -1765,6 +1811,22 @@ static const struct ocfs2_xa_loc_operations ocfs2_xa_block_loc_ops = {
        .xlo_fill_value_buf     = ocfs2_xa_block_fill_value_buf,
 };
 
+static int ocfs2_xa_bucket_journal_access(handle_t *handle,
+                                         struct ocfs2_xa_loc *loc, int type)
+{
+       struct ocfs2_xattr_bucket *bucket = loc->xl_storage;
+
+       return ocfs2_xattr_bucket_journal_access(handle, bucket, type);
+}
+
+static void ocfs2_xa_bucket_journal_dirty(handle_t *handle,
+                                         struct ocfs2_xa_loc *loc)
+{
+       struct ocfs2_xattr_bucket *bucket = loc->xl_storage;
+
+       ocfs2_xattr_bucket_journal_dirty(handle, bucket);
+}
+
 static void *ocfs2_xa_bucket_offset_pointer(struct ocfs2_xa_loc *loc,
                                            int offset)
 {
@@ -1772,8 +1834,8 @@ static void *ocfs2_xa_bucket_offset_pointer(struct ocfs2_xa_loc *loc,
        int block, block_offset;
 
        /* The header is at the front of the bucket */
-       block = offset >> bucket->bu_inode->i_sb->s_blocksize_bits;
-       block_offset = offset % bucket->bu_inode->i_sb->s_blocksize;
+       block = offset >> loc->xl_inode->i_sb->s_blocksize_bits;
+       block_offset = offset % loc->xl_inode->i_sb->s_blocksize;
 
        return bucket_block(bucket, block) + block_offset;
 }
@@ -1813,8 +1875,7 @@ static int ocfs2_xa_bucket_check_space(struct ocfs2_xa_loc *loc,
        int free_start = ocfs2_xa_get_free_start(loc);
        int needed_space = ocfs2_xi_entry_usage(xi);
        int size = namevalue_size_xi(xi);
-       struct ocfs2_xattr_bucket *bucket = loc->xl_storage;
-       struct super_block *sb = bucket->bu_inode->i_sb;
+       struct super_block *sb = loc->xl_inode->i_sb;
 
        /*
         * Bucket storage does not reclaim name+value pairs it cannot
@@ -1896,8 +1957,7 @@ static void ocfs2_xa_bucket_add_namevalue(struct ocfs2_xa_loc *loc, int size)
 {
        int free_start = ocfs2_xa_get_free_start(loc);
        struct ocfs2_xattr_header *xh = loc->xl_header;
-       struct ocfs2_xattr_bucket *bucket = loc->xl_storage;
-       struct super_block *sb = bucket->bu_inode->i_sb;
+       struct super_block *sb = loc->xl_inode->i_sb;
        int nameval_offset;
 
        free_start = ocfs2_bucket_align_free_start(sb, free_start, size);
@@ -1912,7 +1972,7 @@ static void ocfs2_xa_bucket_fill_value_buf(struct ocfs2_xa_loc *loc,
                                           struct ocfs2_xattr_value_buf *vb)
 {
        struct ocfs2_xattr_bucket *bucket = loc->xl_storage;
-       struct super_block *sb = bucket->bu_inode->i_sb;
+       struct super_block *sb = loc->xl_inode->i_sb;
        int nameval_offset = le16_to_cpu(loc->xl_entry->xe_name_offset);
        int size = namevalue_size_xe(loc->xl_entry);
        int block_offset = nameval_offset >> sb->s_blocksize_bits;
@@ -1929,6 +1989,8 @@ static void ocfs2_xa_bucket_fill_value_buf(struct ocfs2_xa_loc *loc,
 
 /* Operations for xattrs stored in buckets. */
 static const struct ocfs2_xa_loc_operations ocfs2_xa_bucket_loc_ops = {
+       .xlo_journal_access     = ocfs2_xa_bucket_journal_access,
+       .xlo_journal_dirty      = ocfs2_xa_bucket_journal_dirty,
        .xlo_offset_pointer     = ocfs2_xa_bucket_offset_pointer,
        .xlo_check_space        = ocfs2_xa_bucket_check_space,
        .xlo_can_reuse          = ocfs2_xa_bucket_can_reuse,
@@ -2049,6 +2111,7 @@ static void ocfs2_init_dinode_xa_loc(struct ocfs2_xa_loc *loc,
 {
        struct ocfs2_dinode *di = (struct ocfs2_dinode *)bh->b_data;
 
+       loc->xl_inode = inode;
        loc->xl_ops = &ocfs2_xa_block_loc_ops;
        loc->xl_storage = bh;
        loc->xl_entry = entry;
@@ -2065,6 +2128,7 @@ static void ocfs2_init_dinode_xa_loc(struct ocfs2_xa_loc *loc,
 }
 
 static void ocfs2_init_xattr_block_xa_loc(struct ocfs2_xa_loc *loc,
+                                         struct inode *inode,
                                          struct buffer_head *bh,
                                          struct ocfs2_xattr_entry *entry)
 {
@@ -2073,6 +2137,7 @@ static void ocfs2_init_xattr_block_xa_loc(struct ocfs2_xa_loc *loc,
 
        BUG_ON(le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED);
 
+       loc->xl_inode = inode;
        loc->xl_ops = &ocfs2_xa_block_loc_ops;
        loc->xl_storage = bh;
        loc->xl_header = &(xb->xb_attrs.xb_header);
@@ -2085,6 +2150,7 @@ static void ocfs2_init_xattr_bucket_xa_loc(struct ocfs2_xa_loc *loc,
                                           struct ocfs2_xattr_bucket *bucket,
                                           struct ocfs2_xattr_entry *entry)
 {
+       loc->xl_inode = bucket->bu_inode;
        loc->xl_ops = &ocfs2_xa_bucket_loc_ops;
        loc->xl_storage = bucket;
        loc->xl_header = bucket_xh(bucket);
@@ -2226,21 +2292,18 @@ static int ocfs2_xattr_set_entry(struct inode *inode,
                goto out;
        }
 
-       if (!(flag & OCFS2_INLINE_XATTR_FL)) {
-               ret = vb.vb_access(handle, INODE_CACHE(inode), vb.vb_bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
-               if (ret) {
-                       mlog_errno(ret);
-                       goto out;
-               }
-       }
-
        if (xs->xattr_bh == xs->inode_bh)
                ocfs2_init_dinode_xa_loc(&loc, inode, xs->inode_bh,
                                         xs->not_found ? NULL : xs->here);
        else
-               ocfs2_init_xattr_block_xa_loc(&loc, xs->xattr_bh,
+               ocfs2_init_xattr_block_xa_loc(&loc, inode, xs->xattr_bh,
                                              xs->not_found ? NULL : xs->here);
+       ret = ocfs2_xa_journal_access(handle, &loc,
+                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       if (ret) {
+               mlog_errno(ret);
+               goto out;
+       }
 
        /*
         * Prepare our entry and insert the inline value.  This will
@@ -2258,13 +2321,7 @@ static int ocfs2_xattr_set_entry(struct inode *inode,
        ocfs2_xa_store_inline_value(&loc, xi);
        xs->here = loc.xl_entry;
 
-       if (!(flag & OCFS2_INLINE_XATTR_FL)) {
-               ret = ocfs2_journal_dirty(handle, xs->xattr_bh);
-               if (ret < 0) {
-                       mlog_errno(ret);
-                       goto out;
-               }
-       }
+       ocfs2_xa_journal_dirty(handle, &loc);
 
        if (!(oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL) &&
            (flag & OCFS2_INLINE_XATTR_FL)) {
@@ -5325,15 +5382,15 @@ static int ocfs2_xattr_set_entry_in_bucket(struct inode *inode,
                }
        }
 
-       ret = ocfs2_xattr_bucket_journal_access(handle, xs->bucket,
-                                               OCFS2_JOURNAL_ACCESS_WRITE);
+       ocfs2_init_xattr_bucket_xa_loc(&loc, xs->bucket,
+                                      xs->not_found ? NULL : xs->here);
+       ret = ocfs2_xa_journal_access(handle, &loc,
+                                     OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret < 0) {
                mlog_errno(ret);
                goto out;
        }
 
-       ocfs2_init_xattr_bucket_xa_loc(&loc, xs->bucket,
-                                      xs->not_found ? NULL : xs->here);
        ret = ocfs2_xa_prepare_entry(&loc, xi, name_hash);
        if (ret) {
                if (ret != -ENOSPC)
@@ -5345,7 +5402,7 @@ static int ocfs2_xattr_set_entry_in_bucket(struct inode *inode,
        ocfs2_xa_store_inline_value(&loc, xi);
        xs->here = loc.xl_entry;
 
-       ocfs2_xattr_bucket_journal_dirty(handle, xs->bucket);
+       ocfs2_xa_journal_dirty(handle, &loc);
 
 out:
        return ret;