it at the default (5 seconds).
Setting it to very large values will improve
performance.
+localalloc=8(*) Allows custom localalloc size in MB. If the value is too
+ large, the fs will silently revert it to the default.
+ Localalloc is not enabled for local mounts.
static int ocfs2_local_alloc_slide_window(struct ocfs2_super *osb,
struct inode *local_alloc_inode);
-/*
- * Determine how large our local alloc window should be, in bits.
- *
- * These values (and the behavior in ocfs2_alloc_should_use_local) have
- * been chosen so that most allocations, including new block groups go
- * through local alloc.
- */
static inline int ocfs2_local_alloc_window_bits(struct ocfs2_super *osb)
{
- BUG_ON(osb->s_clustersize_bits < 12);
+ BUG_ON(osb->s_clustersize_bits > 20);
- return 2048 >> (osb->s_clustersize_bits - 12);
+ /* Size local alloc windows by the megabyte */
+ return osb->local_alloc_size << (20 - osb->s_clustersize_bits);
}
/*
int ocfs2_alloc_should_use_local(struct ocfs2_super *osb, u64 bits)
{
int la_bits = ocfs2_local_alloc_window_bits(osb);
+ int ret = 0;
if (osb->local_alloc_state != OCFS2_LA_ENABLED)
- return 0;
+ goto bail;
/* la_bits should be at least twice the size (in clusters) of
* a new block group. We want to be sure block group
* allocations go through the local alloc, so allow an
* allocation to take up to half the bitmap. */
if (bits > (la_bits / 2))
- return 0;
+ goto bail;
- return 1;
+ ret = 1;
+bail:
+ mlog(0, "state=%d, bits=%llu, la_bits=%d, ret=%d\n",
+ osb->local_alloc_state, (unsigned long long)bits, la_bits, ret);
+ return ret;
}
int ocfs2_load_local_alloc(struct ocfs2_super *osb)
mlog_entry_void();
+ if (ocfs2_mount_local(osb))
+ goto bail;
+
+ if (osb->local_alloc_size == 0)
+ goto bail;
+
+ if (ocfs2_local_alloc_window_bits(osb) >= osb->bitmap_cpg) {
+ mlog(ML_NOTICE, "Requested local alloc window %d is larger "
+ "than max possible %u. Using defaults.\n",
+ ocfs2_local_alloc_window_bits(osb), (osb->bitmap_cpg - 1));
+ osb->local_alloc_size = OCFS2_DEFAULT_LOCAL_ALLOC_SIZE;
+ }
+
/* read the alloc off disk */
inode = ocfs2_get_system_file_inode(osb, LOCAL_ALLOC_SYSTEM_INODE,
osb->slot_num);
if (inode)
iput(inode);
+ mlog(0, "Local alloc window bits = %d\n",
+ ocfs2_local_alloc_window_bits(osb));
+
mlog_exit(status);
return status;
}
iput(local_alloc_inode);
}
+ mlog(0, "bits=%d, slot=%d, ret=%d\n", bits_wanted, osb->slot_num,
+ status);
+
mlog_exit(status);
return status;
}
struct ocfs2_journal *journal;
unsigned long osb_commit_interval;
+ int local_alloc_size;
enum ocfs2_local_alloc_state local_alloc_state;
struct buffer_head *local_alloc_bh;
u64 la_last_gd;
/* Journal limits (in bytes) */
#define OCFS2_MIN_JOURNAL_SIZE (4 * 1024 * 1024)
+/*
+ * Default local alloc size (in megabytes)
+ *
+ * The value chosen should be such that most allocations, including new
+ * block groups, use local alloc.
+ */
+#define OCFS2_DEFAULT_LOCAL_ALLOC_SIZE 8
+
struct ocfs2_system_inode_info {
char *si_name;
int si_iflags;
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;
}
unsigned long mount_opt;
unsigned int atime_quantum;
signed short slot;
+ unsigned int localalloc_opt;
};
static int ocfs2_parse_options(struct super_block *sb, char *options,
Opt_atime_quantum,
Opt_slot,
Opt_commit,
+ Opt_localalloc,
Opt_err,
};
{Opt_atime_quantum, "atime_quantum=%u"},
{Opt_slot, "preferred_slot=%u"},
{Opt_commit, "commit=%u"},
+ {Opt_localalloc, "localalloc=%d"},
{Opt_err, NULL}
};
osb->s_atime_quantum = parsed_options.atime_quantum;
osb->preferred_slot = parsed_options.slot;
osb->osb_commit_interval = parsed_options.commit_interval;
+ osb->local_alloc_size = parsed_options.localalloc_opt;
sb->s_magic = OCFS2_SUPER_MAGIC;
mopt->mount_opt = 0;
mopt->atime_quantum = OCFS2_DEFAULT_ATIME_QUANTUM;
mopt->slot = OCFS2_INVALID_SLOT;
+ mopt->localalloc_opt = OCFS2_DEFAULT_LOCAL_ALLOC_SIZE;
if (!options) {
status = 1;
option = JBD_DEFAULT_MAX_COMMIT_AGE;
mopt->commit_interval = HZ * option;
break;
+ case Opt_localalloc:
+ option = 0;
+ if (match_int(&args[0], &option)) {
+ status = 0;
+ goto bail;
+ }
+ if (option >= 0 && (option <= ocfs2_local_alloc_size(sb) * 8))
+ mopt->localalloc_opt = option;
+ break;
default:
mlog(ML_ERROR,
"Unrecognized mount option \"%s\" "
seq_printf(s, ",commit=%u",
(unsigned) (osb->osb_commit_interval / HZ));
+ if (osb->local_alloc_size != OCFS2_DEFAULT_LOCAL_ALLOC_SIZE)
+ seq_printf(s, ",localalloc=%d", osb->local_alloc_size);
+
return 0;
}