u64 *bg_blkno,
u16 *bg_bit_off);
-static void ocfs2_free_ac_resource(struct ocfs2_alloc_context *ac)
+void ocfs2_free_ac_resource(struct ocfs2_alloc_context *ac)
{
struct inode *inode = ac->ac_inode;
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;
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;
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)
{
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;
}
}
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;
*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);
}
}
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;
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;
}
(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;
+}