]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - fs/ocfs2/suballoc.c
ocfs2: use allocation reservations for directory data
[karo-tx-linux.git] / fs / ocfs2 / suballoc.c
index c3c60bc3e0729a5fb55f99254dc5babd150ae6ff..f20bcbf64ce007e3dce7d25022e6552bb82c3111 100644 (file)
@@ -95,13 +95,6 @@ static inline int ocfs2_block_group_set_bits(handle_t *handle,
                                             struct buffer_head *group_bh,
                                             unsigned int bit_off,
                                             unsigned int num_bits);
-static inline int ocfs2_block_group_clear_bits(handle_t *handle,
-                                              struct inode *alloc_inode,
-                                              struct ocfs2_group_desc *bg,
-                                              struct buffer_head *group_bh,
-                                              unsigned int bit_off,
-                                              unsigned int num_bits);
-
 static int ocfs2_relink_block_group(handle_t *handle,
                                    struct inode *alloc_inode,
                                    struct buffer_head *fe_bh,
@@ -137,6 +130,7 @@ void ocfs2_free_ac_resource(struct ocfs2_alloc_context *ac)
        }
        brelse(ac->ac_bh);
        ac->ac_bh = NULL;
+       ac->ac_resv = NULL;
 }
 
 void ocfs2_free_alloc_context(struct ocfs2_alloc_context *ac)
@@ -152,7 +146,7 @@ static u32 ocfs2_bits_per_group(struct ocfs2_chain_list *cl)
 
 #define do_error(fmt, ...)                                             \
        do{                                                             \
-               if (clean_error)                                        \
+               if (resize)                                     \
                        mlog(ML_ERROR, fmt "\n", ##__VA_ARGS__);        \
                else                                                    \
                        ocfs2_error(sb, fmt, ##__VA_ARGS__);            \
@@ -160,7 +154,7 @@ static u32 ocfs2_bits_per_group(struct ocfs2_chain_list *cl)
 
 static int ocfs2_validate_gd_self(struct super_block *sb,
                                  struct buffer_head *bh,
-                                 int clean_error)
+                                 int resize)
 {
        struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data;
 
@@ -211,7 +205,7 @@ static int ocfs2_validate_gd_self(struct super_block *sb,
 static int ocfs2_validate_gd_parent(struct super_block *sb,
                                    struct ocfs2_dinode *di,
                                    struct buffer_head *bh,
-                                   int clean_error)
+                                   int resize)
 {
        unsigned int max_bits;
        struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data;
@@ -233,8 +227,11 @@ static int ocfs2_validate_gd_parent(struct super_block *sb,
                return -EINVAL;
        }
 
-       if (le16_to_cpu(gd->bg_chain) >=
-           le16_to_cpu(di->id2.i_chain.cl_next_free_rec)) {
+       /* In resize, we may meet the case bg_chain == cl_next_free_rec. */
+       if ((le16_to_cpu(gd->bg_chain) >
+            le16_to_cpu(di->id2.i_chain.cl_next_free_rec)) ||
+           ((le16_to_cpu(gd->bg_chain) ==
+            le16_to_cpu(di->id2.i_chain.cl_next_free_rec)) && !resize)) {
                do_error("Group descriptor #%llu has bad chain %u",
                         (unsigned long long)bh->b_blocknr,
                         le16_to_cpu(gd->bg_chain));
@@ -373,9 +370,7 @@ static int ocfs2_block_group_fill(handle_t *handle,
        ocfs2_set_bit(0, (unsigned long *)bg->bg_bitmap);
        bg->bg_free_bits_count = cpu_to_le16(le16_to_cpu(bg->bg_bits) - 1);
 
-       status = ocfs2_journal_dirty(handle, bg_bh);
-       if (status < 0)
-               mlog_errno(status);
+       ocfs2_journal_dirty(handle, bg_bh);
 
        /* There is no need to zero out or otherwise initialize the
         * other blocks in a group - All valid FS metadata in a block
@@ -510,11 +505,7 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb,
        le32_add_cpu(&fe->id1.bitmap1.i_total, le16_to_cpu(bg->bg_bits));
        le32_add_cpu(&fe->i_clusters, le16_to_cpu(cl->cl_cpg));
 
-       status = ocfs2_journal_dirty(handle, bh);
-       if (status < 0) {
-               mlog_errno(status);
-               goto bail;
-       }
+       ocfs2_journal_dirty(handle, bh);
 
        spin_lock(&OCFS2_I(alloc_inode)->ip_lock);
        OCFS2_I(alloc_inode)->ip_clusters = le32_to_cpu(fe->i_clusters);
@@ -1133,16 +1124,10 @@ static inline int ocfs2_block_group_set_bits(handle_t *handle,
        }
 
        le16_add_cpu(&bg->bg_free_bits_count, -num_bits);
-
        while(num_bits--)
                ocfs2_set_bit(bit_off++, bitmap);
 
-       status = ocfs2_journal_dirty(handle,
-                                    group_bh);
-       if (status < 0) {
-               mlog_errno(status);
-               goto bail;
-       }
+       ocfs2_journal_dirty(handle, group_bh);
 
 bail:
        mlog_exit(status);
@@ -1206,12 +1191,7 @@ static int ocfs2_relink_block_group(handle_t *handle,
        }
 
        prev_bg->bg_next_group = bg->bg_next_group;
-
-       status = ocfs2_journal_dirty(handle, prev_bg_bh);
-       if (status < 0) {
-               mlog_errno(status);
-               goto out_rollback;
-       }
+       ocfs2_journal_dirty(handle, prev_bg_bh);
 
        status = ocfs2_journal_access_gd(handle, INODE_CACHE(alloc_inode),
                                         bg_bh, OCFS2_JOURNAL_ACCESS_WRITE);
@@ -1221,12 +1201,7 @@ static int ocfs2_relink_block_group(handle_t *handle,
        }
 
        bg->bg_next_group = fe->id2.i_chain.cl_recs[chain].c_blkno;
-
-       status = ocfs2_journal_dirty(handle, bg_bh);
-       if (status < 0) {
-               mlog_errno(status);
-               goto out_rollback;
-       }
+       ocfs2_journal_dirty(handle, bg_bh);
 
        status = ocfs2_journal_access_di(handle, INODE_CACHE(alloc_inode),
                                         fe_bh, OCFS2_JOURNAL_ACCESS_WRITE);
@@ -1236,14 +1211,8 @@ static int ocfs2_relink_block_group(handle_t *handle,
        }
 
        fe->id2.i_chain.cl_recs[chain].c_blkno = bg->bg_blkno;
+       ocfs2_journal_dirty(handle, fe_bh);
 
-       status = ocfs2_journal_dirty(handle, fe_bh);
-       if (status < 0) {
-               mlog_errno(status);
-               goto out_rollback;
-       }
-
-       status = 0;
 out_rollback:
        if (status < 0) {
                fe->id2.i_chain.cl_recs[chain].c_blkno = cpu_to_le64(fe_ptr);
@@ -1390,10 +1359,7 @@ static int ocfs2_alloc_dinode_update_counts(struct inode *inode,
        tmp_used = le32_to_cpu(di->id1.bitmap1.i_used);
        di->id1.bitmap1.i_used = cpu_to_le32(num_bits + tmp_used);
        le32_add_cpu(&cl->cl_recs[chain].c_free, -num_bits);
-
-       ret = ocfs2_journal_dirty(handle, di_bh);
-       if (ret < 0)
-               mlog_errno(ret);
+       ocfs2_journal_dirty(handle, di_bh);
 
 out:
        return ret;
@@ -1564,13 +1530,7 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
        tmp_used = le32_to_cpu(fe->id1.bitmap1.i_used);
        fe->id1.bitmap1.i_used = cpu_to_le32(*num_bits + tmp_used);
        le32_add_cpu(&cl->cl_recs[chain].c_free, -(*num_bits));
-
-       status = ocfs2_journal_dirty(handle,
-                                    ac->ac_bh);
-       if (status < 0) {
-               mlog_errno(status);
-               goto bail;
-       }
+       ocfs2_journal_dirty(handle, ac->ac_bh);
 
        status = ocfs2_block_group_set_bits(handle,
                                            alloc_inode,
@@ -1975,18 +1935,18 @@ int ocfs2_claim_clusters(struct ocfs2_super *osb,
                                      bits_wanted, cluster_start, num_clusters);
 }
 
-static inline int ocfs2_block_group_clear_bits(handle_t *handle,
-                                              struct inode *alloc_inode,
-                                              struct ocfs2_group_desc *bg,
-                                              struct buffer_head *group_bh,
-                                              unsigned int bit_off,
-                                              unsigned int num_bits)
+static int ocfs2_block_group_clear_bits(handle_t *handle,
+                                       struct inode *alloc_inode,
+                                       struct ocfs2_group_desc *bg,
+                                       struct buffer_head *group_bh,
+                                       unsigned int bit_off,
+                                       unsigned int num_bits,
+                                       void (*undo_fn)(unsigned int bit,
+                                                       unsigned long *bmap))
 {
        int status;
        unsigned int tmp;
-       int journal_type = OCFS2_JOURNAL_ACCESS_WRITE;
        struct ocfs2_group_desc *undo_bg = NULL;
-       int cluster_bitmap = 0;
 
        mlog_entry_void();
 
@@ -1996,20 +1956,18 @@ static inline int ocfs2_block_group_clear_bits(handle_t *handle,
 
        mlog(0, "off = %u, num = %u\n", bit_off, num_bits);
 
-       if (ocfs2_is_cluster_bitmap(alloc_inode))
-               journal_type = OCFS2_JOURNAL_ACCESS_UNDO;
-
+       BUG_ON(undo_fn && !ocfs2_is_cluster_bitmap(alloc_inode));
        status = ocfs2_journal_access_gd(handle, INODE_CACHE(alloc_inode),
-                                        group_bh, journal_type);
+                                        group_bh,
+                                        undo_fn ?
+                                        OCFS2_JOURNAL_ACCESS_UNDO :
+                                        OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
        }
 
-       if (ocfs2_is_cluster_bitmap(alloc_inode))
-               cluster_bitmap = 1;
-
-       if (cluster_bitmap) {
+       if (undo_fn) {
                jbd_lock_bh_state(group_bh);
                undo_bg = (struct ocfs2_group_desc *)
                                        bh2jh(group_bh)->b_committed_data;
@@ -2020,18 +1978,16 @@ static inline int ocfs2_block_group_clear_bits(handle_t *handle,
        while(tmp--) {
                ocfs2_clear_bit((bit_off + tmp),
                                (unsigned long *) bg->bg_bitmap);
-               if (cluster_bitmap)
-                       ocfs2_set_bit(bit_off + tmp,
-                                     (unsigned long *) undo_bg->bg_bitmap);
+               if (undo_fn)
+                       undo_fn(bit_off + tmp,
+                               (unsigned long *) undo_bg->bg_bitmap);
        }
        le16_add_cpu(&bg->bg_free_bits_count, num_bits);
 
-       if (cluster_bitmap)
+       if (undo_fn)
                jbd_unlock_bh_state(group_bh);
 
-       status = ocfs2_journal_dirty(handle, group_bh);
-       if (status < 0)
-               mlog_errno(status);
+       ocfs2_journal_dirty(handle, group_bh);
 bail:
        return status;
 }
@@ -2039,12 +1995,14 @@ bail:
 /*
  * expects the suballoc inode to already be locked.
  */
-int ocfs2_free_suballoc_bits(handle_t *handle,
-                            struct inode *alloc_inode,
-                            struct buffer_head *alloc_bh,
-                            unsigned int start_bit,
-                            u64 bg_blkno,
-                            unsigned int count)
+static int _ocfs2_free_suballoc_bits(handle_t *handle,
+                                    struct inode *alloc_inode,
+                                    struct buffer_head *alloc_bh,
+                                    unsigned int start_bit,
+                                    u64 bg_blkno,
+                                    unsigned int count,
+                                    void (*undo_fn)(unsigned int bit,
+                                                    unsigned long *bitmap))
 {
        int status = 0;
        u32 tmp_used;
@@ -2079,7 +2037,7 @@ int ocfs2_free_suballoc_bits(handle_t *handle,
 
        status = ocfs2_block_group_clear_bits(handle, alloc_inode,
                                              group, group_bh,
-                                             start_bit, count);
+                                             start_bit, count, undo_fn);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
@@ -2096,12 +2054,7 @@ int ocfs2_free_suballoc_bits(handle_t *handle,
                     count);
        tmp_used = le32_to_cpu(fe->id1.bitmap1.i_used);
        fe->id1.bitmap1.i_used = cpu_to_le32(tmp_used - count);
-
-       status = ocfs2_journal_dirty(handle, alloc_bh);
-       if (status < 0) {
-               mlog_errno(status);
-               goto bail;
-       }
+       ocfs2_journal_dirty(handle, alloc_bh);
 
 bail:
        brelse(group_bh);
@@ -2110,6 +2063,17 @@ bail:
        return status;
 }
 
+int ocfs2_free_suballoc_bits(handle_t *handle,
+                            struct inode *alloc_inode,
+                            struct buffer_head *alloc_bh,
+                            unsigned int start_bit,
+                            u64 bg_blkno,
+                            unsigned int count)
+{
+       return _ocfs2_free_suballoc_bits(handle, alloc_inode, alloc_bh,
+                                        start_bit, bg_blkno, count, NULL);
+}
+
 int ocfs2_free_dinode(handle_t *handle,
                      struct inode *inode_alloc_inode,
                      struct buffer_head *inode_alloc_bh,
@@ -2123,11 +2087,13 @@ int ocfs2_free_dinode(handle_t *handle,
                                        inode_alloc_bh, bit, bg_blkno, 1);
 }
 
-int ocfs2_free_clusters(handle_t *handle,
-                      struct inode *bitmap_inode,
-                      struct buffer_head *bitmap_bh,
-                      u64 start_blk,
-                      unsigned int num_clusters)
+static int _ocfs2_free_clusters(handle_t *handle,
+                               struct inode *bitmap_inode,
+                               struct buffer_head *bitmap_bh,
+                               u64 start_blk,
+                               unsigned int num_clusters,
+                               void (*undo_fn)(unsigned int bit,
+                                               unsigned long *bitmap))
 {
        int status;
        u16 bg_start_bit;
@@ -2154,9 +2120,9 @@ int ocfs2_free_clusters(handle_t *handle,
        mlog(0, "bg_blkno = %llu, bg_start_bit = %u\n",
             (unsigned long long)bg_blkno, bg_start_bit);
 
-       status = ocfs2_free_suballoc_bits(handle, bitmap_inode, bitmap_bh,
-                                         bg_start_bit, bg_blkno,
-                                         num_clusters);
+       status = _ocfs2_free_suballoc_bits(handle, bitmap_inode, bitmap_bh,
+                                          bg_start_bit, bg_blkno,
+                                          num_clusters, undo_fn);
        if (status < 0) {
                mlog_errno(status);
                goto out;
@@ -2170,6 +2136,32 @@ out:
        return status;
 }
 
+int ocfs2_free_clusters(handle_t *handle,
+                       struct inode *bitmap_inode,
+                       struct buffer_head *bitmap_bh,
+                       u64 start_blk,
+                       unsigned int num_clusters)
+{
+       return _ocfs2_free_clusters(handle, bitmap_inode, bitmap_bh,
+                                   start_blk, num_clusters,
+                                   _ocfs2_set_bit);
+}
+
+/*
+ * Give never-used clusters back to the global bitmap.  We don't need
+ * to protect these bits in the undo buffer.
+ */
+int ocfs2_release_clusters(handle_t *handle,
+                          struct inode *bitmap_inode,
+                          struct buffer_head *bitmap_bh,
+                          u64 start_blk,
+                          unsigned int num_clusters)
+{
+       return _ocfs2_free_clusters(handle, bitmap_inode, bitmap_bh,
+                                   start_blk, num_clusters,
+                                   _ocfs2_clear_bit);
+}
+
 static inline void ocfs2_debug_bg(struct ocfs2_group_desc *bg)
 {
        printk("Block Group:\n");