ocfs2: Add functions for extents refcounted.
authorTao Ma <tao.ma@oracle.com>
Tue, 18 Aug 2009 03:28:39 +0000 (11:28 +0800)
committerJoel Becker <joel.becker@oracle.com>
Wed, 23 Sep 2009 03:09:34 +0000 (20:09 -0700)
Add function ocfs2_mark_extent_refcounted which can mark
an extent refcounted.

Signed-off-by: Tao Ma <tao.ma@oracle.com>
fs/ocfs2/alloc.c
fs/ocfs2/alloc.h
fs/ocfs2/ocfs2.h
fs/ocfs2/refcounttree.c

index 9dd68cd..96f8ca6 100644 (file)
@@ -5169,12 +5169,12 @@ out:
  *
  * The caller is responsible for passing down meta_ac if we'll need it.
  */
-static int ocfs2_change_extent_flag(handle_t *handle,
-                                   struct ocfs2_extent_tree *et,
-                                   u32 cpos, u32 len, u32 phys,
-                                   struct ocfs2_alloc_context *meta_ac,
-                                   struct ocfs2_cached_dealloc_ctxt *dealloc,
-                                   int new_flags, int clear_flags)
+int ocfs2_change_extent_flag(handle_t *handle,
+                            struct ocfs2_extent_tree *et,
+                            u32 cpos, u32 len, u32 phys,
+                            struct ocfs2_alloc_context *meta_ac,
+                            struct ocfs2_cached_dealloc_ctxt *dealloc,
+                            int new_flags, int clear_flags)
 {
        int ret, index;
        struct super_block *sb = ocfs2_metadata_cache_get_super(et->et_ci);
index 0610ba1..19d5b88 100644 (file)
@@ -128,6 +128,12 @@ int ocfs2_mark_extent_written(struct inode *inode,
                              handle_t *handle, u32 cpos, u32 len, u32 phys,
                              struct ocfs2_alloc_context *meta_ac,
                              struct ocfs2_cached_dealloc_ctxt *dealloc);
+int ocfs2_change_extent_flag(handle_t *handle,
+                            struct ocfs2_extent_tree *et,
+                            u32 cpos, u32 len, u32 phys,
+                            struct ocfs2_alloc_context *meta_ac,
+                            struct ocfs2_cached_dealloc_ctxt *dealloc,
+                            int new_flags, int clear_flags);
 int ocfs2_remove_extent(handle_t *handle, struct ocfs2_extent_tree *et,
                        u32 cpos, u32 len,
                        struct ocfs2_alloc_context *meta_ac,
index bb53573..eae4046 100644 (file)
@@ -516,6 +516,13 @@ static inline void ocfs2_add_links_count(struct ocfs2_dinode *di, int n)
        ocfs2_set_links_count(di, links);
 }
 
+static inline int ocfs2_refcount_tree(struct ocfs2_super *osb)
+{
+       if (osb->s_feature_incompat & OCFS2_FEATURE_INCOMPAT_REFCOUNT_TREE)
+               return 1;
+       return 0;
+}
+
 /* set / clear functions because cluster events can make these happen
  * in parallel so we want the transitions to be atomic. this also
  * means that any future flags osb_flags must be protected by spinlock
index 2c7974c..f7d19f4 100644 (file)
@@ -2153,3 +2153,42 @@ out:
        brelse(ref_root_bh);
        return ret;
 }
+
+/*
+ * Mark the already-existing extent at cpos as refcounted for len clusters.
+ * This adds the refcount extent flag.
+ *
+ * If the existing extent is larger than the request, initiate a
+ * split. An attempt will be made at merging with adjacent extents.
+ *
+ * The caller is responsible for passing down meta_ac if we'll need it.
+ */
+static int ocfs2_mark_extent_refcounted(struct inode *inode,
+                               struct ocfs2_extent_tree *et,
+                               handle_t *handle, u32 cpos,
+                               u32 len, u32 phys,
+                               struct ocfs2_alloc_context *meta_ac,
+                               struct ocfs2_cached_dealloc_ctxt *dealloc)
+{
+       int ret;
+
+       mlog(0, "Inode %lu refcount tree cpos %u, len %u, phys cluster %u\n",
+            inode->i_ino, cpos, len, phys);
+
+       if (!ocfs2_refcount_tree(OCFS2_SB(inode->i_sb))) {
+               ocfs2_error(inode->i_sb, "Inode %lu want to use refcount "
+                           "tree, but the feature bit is not set in the "
+                           "super block.", inode->i_ino);
+               ret = -EROFS;
+               goto out;
+       }
+
+       ret = ocfs2_change_extent_flag(handle, et, cpos,
+                                      len, phys, meta_ac, dealloc,
+                                      OCFS2_EXT_REFCOUNTED, 0);
+       if (ret)
+               mlog_errno(ret);
+
+out:
+       return ret;
+}