]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - fs/ocfs2/suballoc.c
ocfs2: Prefix the extent tree operations structure.
[karo-tx-linux.git] / fs / ocfs2 / suballoc.c
index 6df4dbf67d185f6844ee96fd37bd34db387771a7..f1871ca8381522a9760c24bab752b3114a293127 100644 (file)
 
 #include "buffer_head_io.h"
 
+#define NOT_ALLOC_NEW_GROUP            0
+#define ALLOC_NEW_GROUP                        1
+
+#define OCFS2_MAX_INODES_TO_STEAL      1024
+
 static inline void ocfs2_debug_bg(struct ocfs2_group_desc *bg);
 static inline void ocfs2_debug_suballoc_inode(struct ocfs2_dinode *fe);
 static inline u16 ocfs2_find_victim_chain(struct ocfs2_chain_list *cl);
@@ -101,14 +106,12 @@ static inline int ocfs2_block_group_reasonably_empty(struct ocfs2_group_desc *bg
 static inline u32 ocfs2_desc_bitmap_to_cluster_off(struct inode *inode,
                                                   u64 bg_blkno,
                                                   u16 bg_bit_off);
-static inline u64 ocfs2_which_cluster_group(struct inode *inode,
-                                           u32 cluster);
 static inline void ocfs2_block_to_cluster_group(struct inode *inode,
                                                u64 data_blkno,
                                                u64 *bg_blkno,
                                                u16 *bg_bit_off);
 
-void ocfs2_free_alloc_context(struct ocfs2_alloc_context *ac)
+void ocfs2_free_ac_resource(struct ocfs2_alloc_context *ac)
 {
        struct inode *inode = ac->ac_inode;
 
@@ -119,9 +122,17 @@ void ocfs2_free_alloc_context(struct ocfs2_alloc_context *ac)
                mutex_unlock(&inode->i_mutex);
 
                iput(inode);
+               ac->ac_inode = NULL;
        }
-       if (ac->ac_bh)
+       if (ac->ac_bh) {
                brelse(ac->ac_bh);
+               ac->ac_bh = NULL;
+       }
+}
+
+void ocfs2_free_alloc_context(struct ocfs2_alloc_context *ac)
+{
+       ocfs2_free_ac_resource(ac);
        kfree(ac);
 }
 
@@ -131,9 +142,9 @@ static u32 ocfs2_bits_per_group(struct ocfs2_chain_list *cl)
 }
 
 /* somewhat more expensive than our other checks, so use sparingly. */
-static int ocfs2_check_group_descriptor(struct super_block *sb,
-                                       struct ocfs2_dinode *di,
-                                       struct ocfs2_group_desc *gd)
+int ocfs2_check_group_descriptor(struct super_block *sb,
+                                struct ocfs2_dinode *di,
+                                struct ocfs2_group_desc *gd)
 {
        unsigned int max_bits;
 
@@ -393,7 +404,8 @@ bail:
 static int ocfs2_reserve_suballoc_bits(struct ocfs2_super *osb,
                                       struct ocfs2_alloc_context *ac,
                                       int type,
-                                      u32 slot)
+                                      u32 slot,
+                                      int alloc_new_group)
 {
        int status;
        u32 bits_wanted = ac->ac_bits_wanted;
@@ -422,6 +434,7 @@ static int ocfs2_reserve_suballoc_bits(struct ocfs2_super *osb,
        }
 
        ac->ac_inode = alloc_inode;
+       ac->ac_alloc_slot = slot;
 
        fe = (struct ocfs2_dinode *) bh->b_data;
        if (!OCFS2_IS_VALID_DINODE(fe)) {
@@ -448,6 +461,14 @@ static int ocfs2_reserve_suballoc_bits(struct ocfs2_super *osb,
                        goto bail;
                }
 
+               if (alloc_new_group != ALLOC_NEW_GROUP) {
+                       mlog(0, "Alloc File %u Full: wanted=%u, free_bits=%u, "
+                            "and we don't alloc a new group for it.\n",
+                            slot, bits_wanted, free_bits);
+                       status = -ENOSPC;
+                       goto bail;
+               }
+
                status = ocfs2_block_group_alloc(osb, alloc_inode, bh);
                if (status < 0) {
                        if (status != -ENOSPC)
@@ -472,9 +493,9 @@ bail:
        return status;
 }
 
-int ocfs2_reserve_new_metadata(struct ocfs2_super *osb,
-                              struct ocfs2_dinode *fe,
-                              struct ocfs2_alloc_context **ac)
+int ocfs2_reserve_new_metadata_blocks(struct ocfs2_super *osb,
+                                     int blocks,
+                                     struct ocfs2_alloc_context **ac)
 {
        int status;
        u32 slot;
@@ -486,13 +507,14 @@ int ocfs2_reserve_new_metadata(struct ocfs2_super *osb,
                goto bail;
        }
 
-       (*ac)->ac_bits_wanted = ocfs2_extend_meta_needed(fe);
+       (*ac)->ac_bits_wanted = blocks;
        (*ac)->ac_which = OCFS2_AC_USE_META;
        slot = osb->slot_num;
        (*ac)->ac_group_search = ocfs2_block_group_search;
 
        status = ocfs2_reserve_suballoc_bits(osb, (*ac),
-                                            EXTENT_ALLOC_SYSTEM_INODE, slot);
+                                            EXTENT_ALLOC_SYSTEM_INODE,
+                                            slot, ALLOC_NEW_GROUP);
        if (status < 0) {
                if (status != -ENOSPC)
                        mlog_errno(status);
@@ -510,10 +532,51 @@ bail:
        return status;
 }
 
+int ocfs2_reserve_new_metadata(struct ocfs2_super *osb,
+                              struct ocfs2_extent_list *root_el,
+                              struct ocfs2_alloc_context **ac)
+{
+       return ocfs2_reserve_new_metadata_blocks(osb,
+                                       ocfs2_extend_meta_needed(root_el),
+                                       ac);
+}
+
+static int ocfs2_steal_inode_from_other_nodes(struct ocfs2_super *osb,
+                                             struct ocfs2_alloc_context *ac)
+{
+       int i, status = -ENOSPC;
+       s16 slot = ocfs2_get_inode_steal_slot(osb);
+
+       /* Start to steal inodes from the first slot after ours. */
+       if (slot == OCFS2_INVALID_SLOT)
+               slot = osb->slot_num + 1;
+
+       for (i = 0; i < osb->max_slots; i++, slot++) {
+               if (slot == osb->max_slots)
+                       slot = 0;
+
+               if (slot == osb->slot_num)
+                       continue;
+
+               status = ocfs2_reserve_suballoc_bits(osb, ac,
+                                                    INODE_ALLOC_SYSTEM_INODE,
+                                                    slot, NOT_ALLOC_NEW_GROUP);
+               if (status >= 0) {
+                       ocfs2_set_inode_steal_slot(osb, slot);
+                       break;
+               }
+
+               ocfs2_free_ac_resource(ac);
+       }
+
+       return status;
+}
+
 int ocfs2_reserve_new_inode(struct ocfs2_super *osb,
                            struct ocfs2_alloc_context **ac)
 {
        int status;
+       s16 slot = ocfs2_get_inode_steal_slot(osb);
 
        *ac = kzalloc(sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
        if (!(*ac)) {
@@ -527,9 +590,43 @@ int ocfs2_reserve_new_inode(struct ocfs2_super *osb,
 
        (*ac)->ac_group_search = ocfs2_block_group_search;
 
+       /*
+        * slot is set when we successfully steal inode from other nodes.
+        * It is reset in 3 places:
+        * 1. when we flush the truncate log
+        * 2. when we complete local alloc recovery.
+        * 3. when we successfully allocate from our own slot.
+        * After it is set, we will go on stealing inodes until we find the
+        * need to check our slots to see whether there is some space for us.
+        */
+       if (slot != OCFS2_INVALID_SLOT &&
+           atomic_read(&osb->s_num_inodes_stolen) < OCFS2_MAX_INODES_TO_STEAL)
+               goto inode_steal;
+
+       atomic_set(&osb->s_num_inodes_stolen, 0);
        status = ocfs2_reserve_suballoc_bits(osb, *ac,
                                             INODE_ALLOC_SYSTEM_INODE,
-                                            osb->slot_num);
+                                            osb->slot_num, ALLOC_NEW_GROUP);
+       if (status >= 0) {
+               status = 0;
+
+               /*
+                * Some inodes must be freed by us, so try to allocate
+                * from our own next time.
+                */
+               if (slot != OCFS2_INVALID_SLOT)
+                       ocfs2_init_inode_steal_slot(osb);
+               goto bail;
+       } else if (status < 0 && status != -ENOSPC) {
+               mlog_errno(status);
+               goto bail;
+       }
+
+       ocfs2_free_ac_resource(*ac);
+
+inode_steal:
+       status = ocfs2_steal_inode_from_other_nodes(osb, *ac);
+       atomic_inc(&osb->s_num_inodes_stolen);
        if (status < 0) {
                if (status != -ENOSPC)
                        mlog_errno(status);
@@ -559,7 +656,8 @@ int ocfs2_reserve_cluster_bitmap_bits(struct ocfs2_super *osb,
 
        status = ocfs2_reserve_suballoc_bits(osb, ac,
                                             GLOBAL_BITMAP_SYSTEM_INODE,
-                                            OCFS2_INVALID_SLOT);
+                                            OCFS2_INVALID_SLOT,
+                                            ALLOC_NEW_GROUP);
        if (status < 0 && status != -ENOSPC) {
                mlog_errno(status);
                goto bail;
@@ -597,15 +695,6 @@ int ocfs2_reserve_clusters(struct ocfs2_super *osb,
                if ((status < 0) && (status != -ENOSPC)) {
                        mlog_errno(status);
                        goto bail;
-               } else if (status == -ENOSPC) {
-                       /* reserve_local_bits will return enospc with
-                        * the local alloc inode still locked, so we
-                        * can change this safely here. */
-                       mlog(0, "Disabling local alloc\n");
-                       /* We set to OCFS2_LA_DISABLED so that umount
-                        * can clean up what's left of the local
-                        * allocation */
-                       osb->local_alloc_state = OCFS2_LA_DISABLED;
                }
        }
 
@@ -648,7 +737,7 @@ bail:
  * sync-data inodes."
  *
  * Note: OCFS2 already does this differently for metadata vs data
- * allocations, as those bitmaps are seperate and undo access is never
+ * allocations, as those bitmaps are separate and undo access is never
  * called on a metadata group descriptor.
  */
 static int ocfs2_test_bg_bit_allocatable(struct buffer_head *bg_bh,
@@ -916,6 +1005,7 @@ static int ocfs2_cluster_group_search(struct inode *inode,
        int search = -ENOSPC;
        int ret;
        struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *) group_bh->b_data;
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
        u16 tmp_off, tmp_found;
        unsigned int max_bits, gd_cluster_off;
 
@@ -956,6 +1046,12 @@ static int ocfs2_cluster_group_search(struct inode *inode,
                        *bit_off = tmp_off;
                        *bits_found = tmp_found;
                        search = 0; /* success */
+               } else if (tmp_found) {
+                       /*
+                        * Don't show bits which we'll be returning
+                        * for allocation to the local alloc bitmap.
+                        */
+                       ocfs2_local_alloc_seen_free_bits(osb, tmp_found);
                }
        }
 
@@ -1114,9 +1210,8 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
        status = -ENOSPC;
        /* for now, the chain search is a bit simplistic. We just use
         * the 1st group with any empty bits. */
-       while ((status = ac->ac_group_search(alloc_inode, group_bh,
-                                            bits_wanted, min_bits, bit_off,
-                                            &tmp_bits)) == -ENOSPC) {
+       while ((status = ac->ac_group_search(alloc_inode, group_bh, bits_wanted,
+                                            min_bits, bit_off, &tmp_bits)) == -ENOSPC) {
                if (!bg->bg_next_group)
                        break;
 
@@ -1443,8 +1538,7 @@ static inline u32 ocfs2_desc_bitmap_to_cluster_off(struct inode *inode,
 
 /* given a cluster offset, calculate which block group it belongs to
  * and return that block offset. */
-static inline u64 ocfs2_which_cluster_group(struct inode *inode,
-                                           u32 cluster)
+u64 ocfs2_which_cluster_group(struct inode *inode, u32 cluster)
 {
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
        u32 group_no;
@@ -1519,8 +1613,9 @@ int __ocfs2_claim_clusters(struct ocfs2_super *osb,
                if (min_clusters > (osb->bitmap_cpg - 1)) {
                        /* The only paths asking for contiguousness
                         * should know about this already. */
-                       mlog(ML_ERROR, "minimum allocation requested exceeds "
-                                      "group bitmap size!");
+                       mlog(ML_ERROR, "minimum allocation requested %u exceeds "
+                            "group bitmap size %u!\n", min_clusters,
+                            osb->bitmap_cpg);
                        status = -ENOSPC;
                        goto bail;
                }
@@ -1749,9 +1844,15 @@ int ocfs2_free_clusters(handle_t *handle,
        status = ocfs2_free_suballoc_bits(handle, bitmap_inode, bitmap_bh,
                                          bg_start_bit, bg_blkno,
                                          num_clusters);
-       if (status < 0)
+       if (status < 0) {
                mlog_errno(status);
+               goto out;
+       }
+
+       ocfs2_local_alloc_seen_free_bits(OCFS2_SB(bitmap_inode->i_sb),
+                                        num_clusters);
 
+out:
        mlog_exit(status);
        return status;
 }
@@ -1802,3 +1903,86 @@ static inline void ocfs2_debug_suballoc_inode(struct ocfs2_dinode *fe)
                       (unsigned long long)fe->id2.i_chain.cl_recs[i].c_blkno);
        }
 }
+
+/*
+ * For a given allocation, determine which allocators will need to be
+ * accessed, and lock them, reserving the appropriate number of bits.
+ *
+ * Sparse file systems call this from ocfs2_write_begin_nolock()
+ * and ocfs2_allocate_unwritten_extents().
+ *
+ * File systems which don't support holes call this from
+ * ocfs2_extend_allocation().
+ */
+int ocfs2_lock_allocators(struct inode *inode, struct buffer_head *root_bh,
+                         struct ocfs2_extent_list *root_el,
+                         u32 clusters_to_add, u32 extents_to_split,
+                         struct ocfs2_alloc_context **data_ac,
+                         struct ocfs2_alloc_context **meta_ac,
+                         enum ocfs2_extent_tree_type type, void *private)
+{
+       int ret = 0, num_free_extents;
+       unsigned int max_recs_needed = clusters_to_add + 2 * extents_to_split;
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+
+       *meta_ac = NULL;
+       if (data_ac)
+               *data_ac = NULL;
+
+       BUG_ON(clusters_to_add != 0 && data_ac == NULL);
+
+       num_free_extents = ocfs2_num_free_extents(osb, inode, root_bh,
+                                                 type, private);
+       if (num_free_extents < 0) {
+               ret = num_free_extents;
+               mlog_errno(ret);
+               goto out;
+       }
+
+       /*
+        * Sparse allocation file systems need to be more conservative
+        * with reserving room for expansion - the actual allocation
+        * happens while we've got a journal handle open so re-taking
+        * a cluster lock (because we ran out of room for another
+        * extent) will violate ordering rules.
+        *
+        * Most of the time we'll only be seeing this 1 cluster at a time
+        * anyway.
+        *
+        * Always lock for any unwritten extents - we might want to
+        * add blocks during a split.
+        */
+       if (!num_free_extents ||
+           (ocfs2_sparse_alloc(osb) && num_free_extents < max_recs_needed)) {
+               ret = ocfs2_reserve_new_metadata(osb, root_el, meta_ac);
+               if (ret < 0) {
+                       if (ret != -ENOSPC)
+                               mlog_errno(ret);
+                       goto out;
+               }
+       }
+
+       if (clusters_to_add == 0)
+               goto out;
+
+       ret = ocfs2_reserve_clusters(osb, clusters_to_add, data_ac);
+       if (ret < 0) {
+               if (ret != -ENOSPC)
+                       mlog_errno(ret);
+               goto out;
+       }
+
+out:
+       if (ret) {
+               if (*meta_ac) {
+                       ocfs2_free_alloc_context(*meta_ac);
+                       *meta_ac = NULL;
+               }
+
+               /*
+                * We cannot have an error and a non null *data_ac.
+                */
+       }
+
+       return ret;
+}