diff options
author | Mark Fasheh <mfasheh@suse.com> | 2010-04-05 21:17:16 -0400 |
---|---|---|
committer | Joel Becker <joel.becker@oracle.com> | 2010-05-05 21:18:07 -0400 |
commit | 83f92318fa33cc084e14e64dc903e605f75884c1 (patch) | |
tree | c7466c64019fb050c69cab27b4388e3a86d58b1a | |
parent | b07f8f24dfe54da0f074b78949044842e8df881f (diff) |
ocfs2: Add dir_resv_level mount option
The default behavior for directory reservations stays the same, but we add a
mount option so people can tweak the size of directory reservations
according to their workloads.
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
Signed-off-by: Joel Becker <joel.becker@oracle.com>
-rw-r--r-- | Documentation/filesystems/ocfs2.txt | 4 | ||||
-rw-r--r-- | fs/ocfs2/dir.c | 6 | ||||
-rw-r--r-- | fs/ocfs2/ocfs2.h | 1 | ||||
-rw-r--r-- | fs/ocfs2/reservations.c | 9 | ||||
-rw-r--r-- | fs/ocfs2/reservations.h | 2 | ||||
-rw-r--r-- | fs/ocfs2/super.c | 23 |
6 files changed, 40 insertions, 5 deletions
diff --git a/Documentation/filesystems/ocfs2.txt b/Documentation/filesystems/ocfs2.txt index 32339e584a9a..1f7ae144f6d8 100644 --- a/Documentation/filesystems/ocfs2.txt +++ b/Documentation/filesystems/ocfs2.txt | |||
@@ -83,3 +83,7 @@ noacl (*) Disables POSIX Access Control Lists support. | |||
83 | resv_level=2 (*) Set how agressive allocation reservations will be. | 83 | resv_level=2 (*) Set how agressive allocation reservations will be. |
84 | Valid values are between 0 (reservations off) to 8 | 84 | Valid values are between 0 (reservations off) to 8 |
85 | (maximum space for reservations). | 85 | (maximum space for reservations). |
86 | dir_resv_level= (*) By default, directory reservations will scale with file | ||
87 | reservations - users should rarely need to change this | ||
88 | value. If allocation reservations are turned off, this | ||
89 | option will have no effect. | ||
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index 8563f97c58af..6c9a28a2d3ae 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c | |||
@@ -2977,7 +2977,8 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh, | |||
2977 | * if we only get one now, that's enough to continue. The rest | 2977 | * if we only get one now, that's enough to continue. The rest |
2978 | * will be claimed after the conversion to extents. | 2978 | * will be claimed after the conversion to extents. |
2979 | */ | 2979 | */ |
2980 | data_ac->ac_resv = &oi->ip_la_data_resv; | 2980 | if (ocfs2_dir_resv_allowed(osb)) |
2981 | data_ac->ac_resv = &oi->ip_la_data_resv; | ||
2981 | ret = ocfs2_claim_clusters(osb, handle, data_ac, 1, &bit_off, &len); | 2982 | ret = ocfs2_claim_clusters(osb, handle, data_ac, 1, &bit_off, &len); |
2982 | if (ret) { | 2983 | if (ret) { |
2983 | mlog_errno(ret); | 2984 | mlog_errno(ret); |
@@ -3348,7 +3349,8 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb, | |||
3348 | goto bail; | 3349 | goto bail; |
3349 | } | 3350 | } |
3350 | 3351 | ||
3351 | data_ac->ac_resv = &OCFS2_I(dir)->ip_la_data_resv; | 3352 | if (ocfs2_dir_resv_allowed(osb)) |
3353 | data_ac->ac_resv = &OCFS2_I(dir)->ip_la_data_resv; | ||
3352 | 3354 | ||
3353 | credits = ocfs2_calc_extend_credits(sb, el, 1); | 3355 | credits = ocfs2_calc_extend_credits(sb, el, 1); |
3354 | } else { | 3356 | } else { |
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index 09d7aee3dabe..a388528f485c 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h | |||
@@ -356,6 +356,7 @@ struct ocfs2_super | |||
356 | struct ocfs2_reservation_map osb_la_resmap; | 356 | struct ocfs2_reservation_map osb_la_resmap; |
357 | 357 | ||
358 | unsigned int osb_resv_level; | 358 | unsigned int osb_resv_level; |
359 | unsigned int osb_dir_resv_level; | ||
359 | 360 | ||
360 | /* Next three fields are for local node slot recovery during | 361 | /* Next three fields are for local node slot recovery during |
361 | * mount. */ | 362 | * mount. */ |
diff --git a/fs/ocfs2/reservations.c b/fs/ocfs2/reservations.c index 87fa35791f18..6497bcc00fa5 100644 --- a/fs/ocfs2/reservations.c +++ b/fs/ocfs2/reservations.c | |||
@@ -44,7 +44,11 @@ DEFINE_SPINLOCK(resv_lock); | |||
44 | 44 | ||
45 | #define OCFS2_MIN_RESV_WINDOW_BITS 8 | 45 | #define OCFS2_MIN_RESV_WINDOW_BITS 8 |
46 | #define OCFS2_MAX_RESV_WINDOW_BITS 1024 | 46 | #define OCFS2_MAX_RESV_WINDOW_BITS 1024 |
47 | #define OCFS2_RESV_DIR_WINDOW_BITS OCFS2_MIN_RESV_WINDOW_BITS | 47 | |
48 | int ocfs2_dir_resv_allowed(struct ocfs2_super *osb) | ||
49 | { | ||
50 | return (osb->osb_resv_level && osb->osb_dir_resv_level); | ||
51 | } | ||
48 | 52 | ||
49 | static unsigned int ocfs2_resv_window_bits(struct ocfs2_reservation_map *resmap, | 53 | static unsigned int ocfs2_resv_window_bits(struct ocfs2_reservation_map *resmap, |
50 | struct ocfs2_alloc_reservation *resv) | 54 | struct ocfs2_alloc_reservation *resv) |
@@ -56,8 +60,7 @@ static unsigned int ocfs2_resv_window_bits(struct ocfs2_reservation_map *resmap, | |||
56 | /* 8, 16, 32, 64, 128, 256, 512, 1024 */ | 60 | /* 8, 16, 32, 64, 128, 256, 512, 1024 */ |
57 | bits = 4 << osb->osb_resv_level; | 61 | bits = 4 << osb->osb_resv_level; |
58 | } else { | 62 | } else { |
59 | /* For now, treat directories the same as files. */ | 63 | bits = 4 << osb->osb_dir_resv_level; |
60 | bits = 4 << osb->osb_resv_level; | ||
61 | } | 64 | } |
62 | return bits; | 65 | return bits; |
63 | } | 66 | } |
diff --git a/fs/ocfs2/reservations.h b/fs/ocfs2/reservations.h index 022aff601e15..25b0c0e31e91 100644 --- a/fs/ocfs2/reservations.h +++ b/fs/ocfs2/reservations.h | |||
@@ -67,6 +67,8 @@ void ocfs2_resv_init_once(struct ocfs2_alloc_reservation *resv); | |||
67 | void ocfs2_resv_set_type(struct ocfs2_alloc_reservation *resv, | 67 | void ocfs2_resv_set_type(struct ocfs2_alloc_reservation *resv, |
68 | unsigned int flags); | 68 | unsigned int flags); |
69 | 69 | ||
70 | int ocfs2_dir_resv_allowed(struct ocfs2_super *osb); | ||
71 | |||
70 | /** | 72 | /** |
71 | * ocfs2_resv_discard() - truncate a reservation | 73 | * ocfs2_resv_discard() - truncate a reservation |
72 | * @resmap: | 74 | * @resmap: |
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 5745682eb1c0..79d7d4cf45b1 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c | |||
@@ -96,6 +96,7 @@ struct mount_options | |||
96 | signed short slot; | 96 | signed short slot; |
97 | int localalloc_opt; | 97 | int localalloc_opt; |
98 | unsigned int resv_level; | 98 | unsigned int resv_level; |
99 | int dir_resv_level; | ||
99 | char cluster_stack[OCFS2_STACK_LABEL_LEN + 1]; | 100 | char cluster_stack[OCFS2_STACK_LABEL_LEN + 1]; |
100 | }; | 101 | }; |
101 | 102 | ||
@@ -178,6 +179,7 @@ enum { | |||
178 | Opt_usrquota, | 179 | Opt_usrquota, |
179 | Opt_grpquota, | 180 | Opt_grpquota, |
180 | Opt_resv_level, | 181 | Opt_resv_level, |
182 | Opt_dir_resv_level, | ||
181 | Opt_err, | 183 | Opt_err, |
182 | }; | 184 | }; |
183 | 185 | ||
@@ -205,6 +207,7 @@ static const match_table_t tokens = { | |||
205 | {Opt_usrquota, "usrquota"}, | 207 | {Opt_usrquota, "usrquota"}, |
206 | {Opt_grpquota, "grpquota"}, | 208 | {Opt_grpquota, "grpquota"}, |
207 | {Opt_resv_level, "resv_level=%u"}, | 209 | {Opt_resv_level, "resv_level=%u"}, |
210 | {Opt_dir_resv_level, "dir_resv_level=%u"}, | ||
208 | {Opt_err, NULL} | 211 | {Opt_err, NULL} |
209 | }; | 212 | }; |
210 | 213 | ||
@@ -1034,6 +1037,11 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) | |||
1034 | 1037 | ||
1035 | ocfs2_la_set_sizes(osb, parsed_options.localalloc_opt); | 1038 | ocfs2_la_set_sizes(osb, parsed_options.localalloc_opt); |
1036 | osb->osb_resv_level = parsed_options.resv_level; | 1039 | osb->osb_resv_level = parsed_options.resv_level; |
1040 | osb->osb_dir_resv_level = parsed_options.resv_level; | ||
1041 | if (parsed_options.dir_resv_level == -1) | ||
1042 | osb->osb_dir_resv_level = parsed_options.resv_level; | ||
1043 | else | ||
1044 | osb->osb_dir_resv_level = parsed_options.dir_resv_level; | ||
1037 | 1045 | ||
1038 | status = ocfs2_verify_userspace_stack(osb, &parsed_options); | 1046 | status = ocfs2_verify_userspace_stack(osb, &parsed_options); |
1039 | if (status) | 1047 | if (status) |
@@ -1295,6 +1303,7 @@ static int ocfs2_parse_options(struct super_block *sb, | |||
1295 | mopt->localalloc_opt = -1; | 1303 | mopt->localalloc_opt = -1; |
1296 | mopt->cluster_stack[0] = '\0'; | 1304 | mopt->cluster_stack[0] = '\0'; |
1297 | mopt->resv_level = OCFS2_DEFAULT_RESV_LEVEL; | 1305 | mopt->resv_level = OCFS2_DEFAULT_RESV_LEVEL; |
1306 | mopt->dir_resv_level = -1; | ||
1298 | 1307 | ||
1299 | if (!options) { | 1308 | if (!options) { |
1300 | status = 1; | 1309 | status = 1; |
@@ -1449,6 +1458,17 @@ static int ocfs2_parse_options(struct super_block *sb, | |||
1449 | option < OCFS2_MAX_RESV_LEVEL) | 1458 | option < OCFS2_MAX_RESV_LEVEL) |
1450 | mopt->resv_level = option; | 1459 | mopt->resv_level = option; |
1451 | break; | 1460 | break; |
1461 | case Opt_dir_resv_level: | ||
1462 | if (is_remount) | ||
1463 | break; | ||
1464 | if (match_int(&args[0], &option)) { | ||
1465 | status = 0; | ||
1466 | goto bail; | ||
1467 | } | ||
1468 | if (option >= OCFS2_MIN_RESV_LEVEL && | ||
1469 | option < OCFS2_MAX_RESV_LEVEL) | ||
1470 | mopt->dir_resv_level = option; | ||
1471 | break; | ||
1452 | default: | 1472 | default: |
1453 | mlog(ML_ERROR, | 1473 | mlog(ML_ERROR, |
1454 | "Unrecognized mount option \"%s\" " | 1474 | "Unrecognized mount option \"%s\" " |
@@ -1533,6 +1553,9 @@ static int ocfs2_show_options(struct seq_file *s, struct vfsmount *mnt) | |||
1533 | if (osb->osb_resv_level != OCFS2_DEFAULT_RESV_LEVEL) | 1553 | if (osb->osb_resv_level != OCFS2_DEFAULT_RESV_LEVEL) |
1534 | seq_printf(s, ",resv_level=%d", osb->osb_resv_level); | 1554 | seq_printf(s, ",resv_level=%d", osb->osb_resv_level); |
1535 | 1555 | ||
1556 | if (osb->osb_dir_resv_level != osb->osb_resv_level) | ||
1557 | seq_printf(s, ",dir_resv_level=%d", osb->osb_resv_level); | ||
1558 | |||
1536 | return 0; | 1559 | return 0; |
1537 | } | 1560 | } |
1538 | 1561 | ||