|
@@ -5800,7 +5800,10 @@ int ocfs2_truncate_log_init(struct ocfs2_super *osb)
|
|
|
*/
|
|
|
|
|
|
/*
|
|
|
- * Describes a single block free from a suballocator
|
|
|
+ * Describe a single bit freed from a suballocator. For the block
|
|
|
+ * suballocators, it represents one block. For the global cluster
|
|
|
+ * allocator, it represents some clusters and free_bit indicates
|
|
|
+ * clusters number.
|
|
|
*/
|
|
|
struct ocfs2_cached_block_free {
|
|
|
struct ocfs2_cached_block_free *free_next;
|
|
@@ -5815,10 +5818,10 @@ struct ocfs2_per_slot_free_list {
|
|
|
struct ocfs2_cached_block_free *f_first;
|
|
|
};
|
|
|
|
|
|
-static int ocfs2_free_cached_items(struct ocfs2_super *osb,
|
|
|
- int sysfile_type,
|
|
|
- int slot,
|
|
|
- struct ocfs2_cached_block_free *head)
|
|
|
+static int ocfs2_free_cached_blocks(struct ocfs2_super *osb,
|
|
|
+ int sysfile_type,
|
|
|
+ int slot,
|
|
|
+ struct ocfs2_cached_block_free *head)
|
|
|
{
|
|
|
int ret;
|
|
|
u64 bg_blkno;
|
|
@@ -5893,6 +5896,82 @@ out:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+int ocfs2_cache_cluster_dealloc(struct ocfs2_cached_dealloc_ctxt *ctxt,
|
|
|
+ u64 blkno, unsigned int bit)
|
|
|
+{
|
|
|
+ int ret = 0;
|
|
|
+ struct ocfs2_cached_block_free *item;
|
|
|
+
|
|
|
+ item = kmalloc(sizeof(*item), GFP_NOFS);
|
|
|
+ if (item == NULL) {
|
|
|
+ ret = -ENOMEM;
|
|
|
+ mlog_errno(ret);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ mlog(0, "Insert clusters: (bit %u, blk %llu)\n",
|
|
|
+ bit, (unsigned long long)blkno);
|
|
|
+
|
|
|
+ item->free_blk = blkno;
|
|
|
+ item->free_bit = bit;
|
|
|
+ item->free_next = ctxt->c_global_allocator;
|
|
|
+
|
|
|
+ ctxt->c_global_allocator = item;
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+static int ocfs2_free_cached_clusters(struct ocfs2_super *osb,
|
|
|
+ struct ocfs2_cached_block_free *head)
|
|
|
+{
|
|
|
+ struct ocfs2_cached_block_free *tmp;
|
|
|
+ struct inode *tl_inode = osb->osb_tl_inode;
|
|
|
+ handle_t *handle;
|
|
|
+ int ret = 0;
|
|
|
+
|
|
|
+ mutex_lock(&tl_inode->i_mutex);
|
|
|
+
|
|
|
+ while (head) {
|
|
|
+ if (ocfs2_truncate_log_needs_flush(osb)) {
|
|
|
+ ret = __ocfs2_flush_truncate_log(osb);
|
|
|
+ if (ret < 0) {
|
|
|
+ mlog_errno(ret);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ handle = ocfs2_start_trans(osb, OCFS2_TRUNCATE_LOG_UPDATE);
|
|
|
+ if (IS_ERR(handle)) {
|
|
|
+ ret = PTR_ERR(handle);
|
|
|
+ mlog_errno(ret);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = ocfs2_truncate_log_append(osb, handle, head->free_blk,
|
|
|
+ head->free_bit);
|
|
|
+
|
|
|
+ ocfs2_commit_trans(osb, handle);
|
|
|
+ tmp = head;
|
|
|
+ head = head->free_next;
|
|
|
+ kfree(tmp);
|
|
|
+
|
|
|
+ if (ret < 0) {
|
|
|
+ mlog_errno(ret);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ mutex_unlock(&tl_inode->i_mutex);
|
|
|
+
|
|
|
+ while (head) {
|
|
|
+ /* Premature exit may have left some dangling items. */
|
|
|
+ tmp = head;
|
|
|
+ head = head->free_next;
|
|
|
+ kfree(tmp);
|
|
|
+ }
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
int ocfs2_run_deallocs(struct ocfs2_super *osb,
|
|
|
struct ocfs2_cached_dealloc_ctxt *ctxt)
|
|
|
{
|
|
@@ -5908,8 +5987,10 @@ int ocfs2_run_deallocs(struct ocfs2_super *osb,
|
|
|
if (fl->f_first) {
|
|
|
mlog(0, "Free items: (type %u, slot %d)\n",
|
|
|
fl->f_inode_type, fl->f_slot);
|
|
|
- ret2 = ocfs2_free_cached_items(osb, fl->f_inode_type,
|
|
|
- fl->f_slot, fl->f_first);
|
|
|
+ ret2 = ocfs2_free_cached_blocks(osb,
|
|
|
+ fl->f_inode_type,
|
|
|
+ fl->f_slot,
|
|
|
+ fl->f_first);
|
|
|
if (ret2)
|
|
|
mlog_errno(ret2);
|
|
|
if (!ret)
|
|
@@ -5920,6 +6001,17 @@ int ocfs2_run_deallocs(struct ocfs2_super *osb,
|
|
|
kfree(fl);
|
|
|
}
|
|
|
|
|
|
+ if (ctxt->c_global_allocator) {
|
|
|
+ ret2 = ocfs2_free_cached_clusters(osb,
|
|
|
+ ctxt->c_global_allocator);
|
|
|
+ if (ret2)
|
|
|
+ mlog_errno(ret2);
|
|
|
+ if (!ret)
|
|
|
+ ret = ret2;
|
|
|
+
|
|
|
+ ctxt->c_global_allocator = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
return ret;
|
|
|
}
|
|
|
|