fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / fs / ocfs2 / alloc.c
index edaab05..f27e537 100644 (file)
@@ -52,14 +52,14 @@ static int ocfs2_extent_contig(struct inode *inode,
                               u64 blkno);
 
 static int ocfs2_create_new_meta_bhs(struct ocfs2_super *osb,
-                                    struct ocfs2_journal_handle *handle,
+                                    handle_t *handle,
                                     struct inode *inode,
                                     int wanted,
                                     struct ocfs2_alloc_context *meta_ac,
                                     struct buffer_head *bhs[]);
 
 static int ocfs2_add_branch(struct ocfs2_super *osb,
-                           struct ocfs2_journal_handle *handle,
+                           handle_t *handle,
                            struct inode *inode,
                            struct buffer_head *fe_bh,
                            struct buffer_head *eb_bh,
@@ -67,14 +67,14 @@ static int ocfs2_add_branch(struct ocfs2_super *osb,
                            struct ocfs2_alloc_context *meta_ac);
 
 static int ocfs2_shift_tree_depth(struct ocfs2_super *osb,
-                                 struct ocfs2_journal_handle *handle,
+                                 handle_t *handle,
                                  struct inode *inode,
                                  struct buffer_head *fe_bh,
                                  struct ocfs2_alloc_context *meta_ac,
                                  struct buffer_head **ret_new_eb_bh);
 
 static int ocfs2_do_insert_extent(struct ocfs2_super *osb,
-                                 struct ocfs2_journal_handle *handle,
+                                 handle_t *handle,
                                  struct inode *inode,
                                  struct buffer_head *fe_bh,
                                  u64 blkno,
@@ -152,7 +152,7 @@ bail:
  * l_count for you
  */
 static int ocfs2_create_new_meta_bhs(struct ocfs2_super *osb,
-                                    struct ocfs2_journal_handle *handle,
+                                    handle_t *handle,
                                     struct inode *inode,
                                     int wanted,
                                     struct ocfs2_alloc_context *meta_ac,
@@ -253,7 +253,7 @@ bail:
  * contain a single record with e_clusters == 0.
  */
 static int ocfs2_add_branch(struct ocfs2_super *osb,
-                           struct ocfs2_journal_handle *handle,
+                           handle_t *handle,
                            struct inode *inode,
                            struct buffer_head *fe_bh,
                            struct buffer_head *eb_bh,
@@ -418,7 +418,7 @@ bail:
  * after this call.
  */
 static int ocfs2_shift_tree_depth(struct ocfs2_super *osb,
-                                 struct ocfs2_journal_handle *handle,
+                                 handle_t *handle,
                                  struct inode *inode,
                                  struct buffer_head *fe_bh,
                                  struct ocfs2_alloc_context *meta_ac,
@@ -520,7 +520,7 @@ bail:
  * down.
  */
 static int ocfs2_do_insert_extent(struct ocfs2_super *osb,
-                                 struct ocfs2_journal_handle *handle,
+                                 handle_t *handle,
                                  struct inode *inode,
                                  struct buffer_head *fe_bh,
                                  u64 start_blk,
@@ -809,7 +809,7 @@ bail:
 
 /* the caller needs to update fe->i_clusters */
 int ocfs2_insert_extent(struct ocfs2_super *osb,
-                       struct ocfs2_journal_handle *handle,
+                       handle_t *handle,
                        struct inode *inode,
                        struct buffer_head *fe_bh,
                        u64 start_blk,
@@ -951,7 +951,7 @@ static int ocfs2_truncate_log_can_coalesce(struct ocfs2_truncate_log *tl,
 }
 
 static int ocfs2_truncate_log_append(struct ocfs2_super *osb,
-                                    struct ocfs2_journal_handle *handle,
+                                    handle_t *handle,
                                     u64 start_blk,
                                     unsigned int num_clusters)
 {
@@ -1034,7 +1034,7 @@ bail:
 }
 
 static int ocfs2_replay_truncate_records(struct ocfs2_super *osb,
-                                        struct ocfs2_journal_handle *handle,
+                                        handle_t *handle,
                                         struct inode *data_alloc_inode,
                                         struct buffer_head *data_alloc_bh)
 {
@@ -1113,7 +1113,7 @@ static int __ocfs2_flush_truncate_log(struct ocfs2_super *osb)
 {
        int status;
        unsigned int num_to_flush;
-       struct ocfs2_journal_handle *handle = NULL;
+       handle_t *handle;
        struct inode *tl_inode = osb->osb_tl_inode;
        struct inode *data_alloc_inode = NULL;
        struct buffer_head *tl_bh = osb->osb_tl_bh;
@@ -1130,7 +1130,7 @@ static int __ocfs2_flush_truncate_log(struct ocfs2_super *osb)
        if (!OCFS2_IS_VALID_DINODE(di)) {
                OCFS2_RO_ON_INVALID_DINODE(osb->sb, di);
                status = -EIO;
-               goto bail;
+               goto out;
        }
 
        num_to_flush = le16_to_cpu(tl->tl_used);
@@ -1138,14 +1138,7 @@ static int __ocfs2_flush_truncate_log(struct ocfs2_super *osb)
             num_to_flush, (unsigned long long)OCFS2_I(tl_inode)->ip_blkno);
        if (!num_to_flush) {
                status = 0;
-               goto bail;
-       }
-
-       handle = ocfs2_alloc_handle(osb);
-       if (!handle) {
-               status = -ENOMEM;
-               mlog_errno(status);
-               goto bail;
+               goto out;
        }
 
        data_alloc_inode = ocfs2_get_system_file_inode(osb,
@@ -1154,41 +1147,40 @@ static int __ocfs2_flush_truncate_log(struct ocfs2_super *osb)
        if (!data_alloc_inode) {
                status = -EINVAL;
                mlog(ML_ERROR, "Could not get bitmap inode!\n");
-               goto bail;
+               goto out;
        }
 
-       ocfs2_handle_add_inode(handle, data_alloc_inode);
-       status = ocfs2_meta_lock(data_alloc_inode, handle, &data_alloc_bh, 1);
+       mutex_lock(&data_alloc_inode->i_mutex);
+
+       status = ocfs2_meta_lock(data_alloc_inode, &data_alloc_bh, 1);
        if (status < 0) {
                mlog_errno(status);
-               goto bail;
+               goto out_mutex;
        }
 
-       handle = ocfs2_start_trans(osb, handle, OCFS2_TRUNCATE_LOG_UPDATE);
+       handle = ocfs2_start_trans(osb, OCFS2_TRUNCATE_LOG_UPDATE);
        if (IS_ERR(handle)) {
                status = PTR_ERR(handle);
-               handle = NULL;
                mlog_errno(status);
-               goto bail;
+               goto out_unlock;
        }
 
        status = ocfs2_replay_truncate_records(osb, handle, data_alloc_inode,
                                               data_alloc_bh);
-       if (status < 0) {
+       if (status < 0)
                mlog_errno(status);
-               goto bail;
-       }
 
-bail:
-       if (handle)
-               ocfs2_commit_trans(handle);
+       ocfs2_commit_trans(osb, handle);
 
-       if (data_alloc_inode)
-               iput(data_alloc_inode);
+out_unlock:
+       brelse(data_alloc_bh);
+       ocfs2_meta_unlock(data_alloc_inode, 1);
 
-       if (data_alloc_bh)
-               brelse(data_alloc_bh);
+out_mutex:
+       mutex_unlock(&data_alloc_inode->i_mutex);
+       iput(data_alloc_inode);
 
+out:
        mlog_exit(status);
        return status;
 }
@@ -1205,10 +1197,12 @@ int ocfs2_flush_truncate_log(struct ocfs2_super *osb)
        return status;
 }
 
-static void ocfs2_truncate_log_worker(void *data)
+static void ocfs2_truncate_log_worker(struct work_struct *work)
 {
        int status;
-       struct ocfs2_super *osb = data;
+       struct ocfs2_super *osb =
+               container_of(work, struct ocfs2_super,
+                            osb_truncate_log_wq.work);
 
        mlog_entry_void();
 
@@ -1347,7 +1341,7 @@ int ocfs2_complete_truncate_log_recovery(struct ocfs2_super *osb,
        int i;
        unsigned int clusters, num_recs, start_cluster;
        u64 start_blk;
-       struct ocfs2_journal_handle *handle;
+       handle_t *handle;
        struct inode *tl_inode = osb->osb_tl_inode;
        struct ocfs2_truncate_log *tl;
 
@@ -1373,8 +1367,7 @@ int ocfs2_complete_truncate_log_recovery(struct ocfs2_super *osb,
                        }
                }
 
-               handle = ocfs2_start_trans(osb, NULL,
-                                          OCFS2_TRUNCATE_LOG_UPDATE);
+               handle = ocfs2_start_trans(osb, OCFS2_TRUNCATE_LOG_UPDATE);
                if (IS_ERR(handle)) {
                        status = PTR_ERR(handle);
                        mlog_errno(status);
@@ -1387,7 +1380,7 @@ int ocfs2_complete_truncate_log_recovery(struct ocfs2_super *osb,
 
                status = ocfs2_truncate_log_append(osb, handle,
                                                   start_blk, clusters);
-               ocfs2_commit_trans(handle);
+               ocfs2_commit_trans(osb, handle);
                if (status < 0) {
                        mlog_errno(status);
                        goto bail_up;
@@ -1441,7 +1434,8 @@ int ocfs2_truncate_log_init(struct ocfs2_super *osb)
        /* ocfs2_truncate_log_shutdown keys on the existence of
         * osb->osb_tl_inode so we don't set any of the osb variables
         * until we're sure all is well. */
-       INIT_WORK(&osb->osb_truncate_log_wq, ocfs2_truncate_log_worker, osb);
+       INIT_DELAYED_WORK(&osb->osb_truncate_log_wq,
+                         ocfs2_truncate_log_worker);
        osb->osb_tl_bh    = tl_bh;
        osb->osb_tl_inode = tl_inode;
 
@@ -1543,7 +1537,7 @@ static int ocfs2_do_truncate(struct ocfs2_super *osb,
                             struct inode *inode,
                             struct buffer_head *fe_bh,
                             struct buffer_head *old_last_eb_bh,
-                            struct ocfs2_journal_handle *handle,
+                            handle_t *handle,
                             struct ocfs2_truncate_context *tc)
 {
        int status, i, depth;
@@ -1717,17 +1711,29 @@ static int ocfs2_do_truncate(struct ocfs2_super *osb,
 
                        ocfs2_remove_from_cache(inode, eb_bh);
 
-                       BUG_ON(eb->h_suballoc_slot);
                        BUG_ON(el->l_recs[0].e_clusters);
                        BUG_ON(el->l_recs[0].e_cpos);
                        BUG_ON(el->l_recs[0].e_blkno);
-                       status = ocfs2_free_extent_block(handle,
-                                                        tc->tc_ext_alloc_inode,
-                                                        tc->tc_ext_alloc_bh,
-                                                        eb);
-                       if (status < 0) {
-                               mlog_errno(status);
-                               goto bail;
+                       if (eb->h_suballoc_slot == 0) {
+                               /*
+                                * This code only understands how to
+                                * lock the suballocator in slot 0,
+                                * which is fine because allocation is
+                                * only ever done out of that
+                                * suballocator too. A future version
+                                * might change that however, so avoid
+                                * a free if we don't know how to
+                                * handle it. This way an fs incompat
+                                * bit will not be necessary.
+                                */
+                               status = ocfs2_free_extent_block(handle,
+                                                                tc->tc_ext_alloc_inode,
+                                                                tc->tc_ext_alloc_bh,
+                                                                eb);
+                               if (status < 0) {
+                                       mlog_errno(status);
+                                       goto bail;
+                               }
                        }
                }
                brelse(eb_bh);
@@ -1770,7 +1776,7 @@ int ocfs2_commit_truncate(struct ocfs2_super *osb,
        struct ocfs2_extent_block *eb;
        struct ocfs2_extent_list *el;
        struct buffer_head *last_eb_bh;
-       struct ocfs2_journal_handle *handle = NULL;
+       handle_t *handle = NULL;
        struct inode *tl_inode = osb->osb_tl_inode;
 
        mlog_entry_void();
@@ -1856,7 +1862,7 @@ start:
 
        credits = ocfs2_calc_tree_trunc_credits(osb->sb, clusters_to_del,
                                                fe, el);
-       handle = ocfs2_start_trans(osb, NULL, credits);
+       handle = ocfs2_start_trans(osb, credits);
        if (IS_ERR(handle)) {
                status = PTR_ERR(handle);
                handle = NULL;
@@ -1879,7 +1885,7 @@ start:
        mutex_unlock(&tl_inode->i_mutex);
        tl_sem = 0;
 
-       ocfs2_commit_trans(handle);
+       ocfs2_commit_trans(osb, handle);
        handle = NULL;
 
        BUG_ON(le32_to_cpu(fe->i_clusters) < target_i_clusters);
@@ -1894,7 +1900,7 @@ bail:
                mutex_unlock(&tl_inode->i_mutex);
 
        if (handle)
-               ocfs2_commit_trans(handle);
+               ocfs2_commit_trans(osb, handle);
 
        if (last_eb_bh)
                brelse(last_eb_bh);
@@ -1953,7 +1959,7 @@ int ocfs2_prepare_truncate(struct ocfs2_super *osb,
                goto bail;
        }
 
-       *tc = kcalloc(1, sizeof(struct ocfs2_truncate_context), GFP_KERNEL);
+       *tc = kzalloc(sizeof(struct ocfs2_truncate_context), GFP_KERNEL);
        if (!(*tc)) {
                status = -ENOMEM;
                mlog_errno(status);
@@ -1999,10 +2005,7 @@ int ocfs2_prepare_truncate(struct ocfs2_super *osb,
                mutex_lock(&ext_alloc_inode->i_mutex);
                (*tc)->tc_ext_alloc_inode = ext_alloc_inode;
 
-               status = ocfs2_meta_lock(ext_alloc_inode,
-                                        NULL,
-                                        &ext_alloc_bh,
-                                        1);
+               status = ocfs2_meta_lock(ext_alloc_inode, &ext_alloc_bh, 1);
                if (status < 0) {
                        mlog_errno(status);
                        goto bail;