aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/super.c
diff options
context:
space:
mode:
authorMark Fasheh <mfasheh@suse.com>2009-12-07 16:10:48 -0500
committerJoel Becker <joel.becker@oracle.com>2010-05-05 21:17:30 -0400
commitd02f00cc057809d96c044cc72d5b9809d59f7d49 (patch)
tree44a6d81ecf9fb4b5aa91c0501a8da2ee36890a38 /fs/ocfs2/super.c
parentec20cec7a351584ca6c70ead012e73d61f9a8e04 (diff)
ocfs2: allocation reservations
This patch improves Ocfs2 allocation policy by allowing an inode to reserve a portion of the local alloc bitmap for itself. The reserved portion (allocation window) is advisory in that other allocation windows might steal it if the local alloc bitmap becomes full. Otherwise, the reservations are honored and guaranteed to be free. When the local alloc window is moved to a different portion of the bitmap, existing reservations are discarded. Reservation windows are represented internally by a red-black tree. Within that tree, each node represents the reservation window of one inode. An LRU of active reservations is also maintained. When new data is written, we allocate it from the inodes window. When all bits in a window are exhausted, we allocate a new one as close to the previous one as possible. Should we not find free space, an existing reservation is pulled off the LRU and cannibalized. Signed-off-by: Mark Fasheh <mfasheh@suse.com>
Diffstat (limited to 'fs/ocfs2/super.c')
-rw-r--r--fs/ocfs2/super.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index dee03197a494..cfe672e72b27 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -95,6 +95,7 @@ struct mount_options
95 unsigned int atime_quantum; 95 unsigned int atime_quantum;
96 signed short slot; 96 signed short slot;
97 unsigned int localalloc_opt; 97 unsigned int localalloc_opt;
98 unsigned int resv_level;
98 char cluster_stack[OCFS2_STACK_LABEL_LEN + 1]; 99 char cluster_stack[OCFS2_STACK_LABEL_LEN + 1];
99}; 100};
100 101
@@ -176,6 +177,7 @@ enum {
176 Opt_noacl, 177 Opt_noacl,
177 Opt_usrquota, 178 Opt_usrquota,
178 Opt_grpquota, 179 Opt_grpquota,
180 Opt_resv_level,
179 Opt_err, 181 Opt_err,
180}; 182};
181 183
@@ -202,6 +204,7 @@ static const match_table_t tokens = {
202 {Opt_noacl, "noacl"}, 204 {Opt_noacl, "noacl"},
203 {Opt_usrquota, "usrquota"}, 205 {Opt_usrquota, "usrquota"},
204 {Opt_grpquota, "grpquota"}, 206 {Opt_grpquota, "grpquota"},
207 {Opt_resv_level, "resv_level=%u"},
205 {Opt_err, NULL} 208 {Opt_err, NULL}
206}; 209};
207 210
@@ -1030,6 +1033,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
1030 osb->osb_commit_interval = parsed_options.commit_interval; 1033 osb->osb_commit_interval = parsed_options.commit_interval;
1031 osb->local_alloc_default_bits = ocfs2_megabytes_to_clusters(sb, parsed_options.localalloc_opt); 1034 osb->local_alloc_default_bits = ocfs2_megabytes_to_clusters(sb, parsed_options.localalloc_opt);
1032 osb->local_alloc_bits = osb->local_alloc_default_bits; 1035 osb->local_alloc_bits = osb->local_alloc_default_bits;
1036 osb->osb_resv_level = parsed_options.resv_level;
1033 1037
1034 status = ocfs2_verify_userspace_stack(osb, &parsed_options); 1038 status = ocfs2_verify_userspace_stack(osb, &parsed_options);
1035 if (status) 1039 if (status)
@@ -1290,6 +1294,7 @@ static int ocfs2_parse_options(struct super_block *sb,
1290 mopt->slot = OCFS2_INVALID_SLOT; 1294 mopt->slot = OCFS2_INVALID_SLOT;
1291 mopt->localalloc_opt = OCFS2_DEFAULT_LOCAL_ALLOC_SIZE; 1295 mopt->localalloc_opt = OCFS2_DEFAULT_LOCAL_ALLOC_SIZE;
1292 mopt->cluster_stack[0] = '\0'; 1296 mopt->cluster_stack[0] = '\0';
1297 mopt->resv_level = OCFS2_DEFAULT_RESV_LEVEL;
1293 1298
1294 if (!options) { 1299 if (!options) {
1295 status = 1; 1300 status = 1;
@@ -1433,6 +1438,17 @@ static int ocfs2_parse_options(struct super_block *sb,
1433 mopt->mount_opt |= OCFS2_MOUNT_NO_POSIX_ACL; 1438 mopt->mount_opt |= OCFS2_MOUNT_NO_POSIX_ACL;
1434 mopt->mount_opt &= ~OCFS2_MOUNT_POSIX_ACL; 1439 mopt->mount_opt &= ~OCFS2_MOUNT_POSIX_ACL;
1435 break; 1440 break;
1441 case Opt_resv_level:
1442 if (is_remount)
1443 break;
1444 if (match_int(&args[0], &option)) {
1445 status = 0;
1446 goto bail;
1447 }
1448 if (option >= OCFS2_MIN_RESV_LEVEL &&
1449 option < OCFS2_MAX_RESV_LEVEL)
1450 mopt->resv_level = option;
1451 break;
1436 default: 1452 default:
1437 mlog(ML_ERROR, 1453 mlog(ML_ERROR,
1438 "Unrecognized mount option \"%s\" " 1454 "Unrecognized mount option \"%s\" "
@@ -1514,6 +1530,9 @@ static int ocfs2_show_options(struct seq_file *s, struct vfsmount *mnt)
1514 else 1530 else
1515 seq_printf(s, ",noacl"); 1531 seq_printf(s, ",noacl");
1516 1532
1533 if (osb->osb_resv_level != OCFS2_DEFAULT_RESV_LEVEL)
1534 seq_printf(s, ",resv_level=%d", osb->osb_resv_level);
1535
1517 return 0; 1536 return 0;
1518} 1537}
1519 1538
@@ -2042,6 +2061,12 @@ static int ocfs2_initialize_super(struct super_block *sb,
2042 2061
2043 init_waitqueue_head(&osb->osb_mount_event); 2062 init_waitqueue_head(&osb->osb_mount_event);
2044 2063
2064 status = ocfs2_resmap_init(osb, &osb->osb_la_resmap);
2065 if (status) {
2066 mlog_errno(status);
2067 goto bail;
2068 }
2069
2045 osb->vol_label = kmalloc(OCFS2_MAX_VOL_LABEL_LEN, GFP_KERNEL); 2070 osb->vol_label = kmalloc(OCFS2_MAX_VOL_LABEL_LEN, GFP_KERNEL);
2046 if (!osb->vol_label) { 2071 if (!osb->vol_label) {
2047 mlog(ML_ERROR, "unable to alloc vol label\n"); 2072 mlog(ML_ERROR, "unable to alloc vol label\n");