diff options
-rw-r--r-- | Documentation/filesystems/ocfs2.txt | 3 | ||||
-rw-r--r-- | fs/ocfs2/localalloc.c | 42 | ||||
-rw-r--r-- | fs/ocfs2/ocfs2.h | 1 | ||||
-rw-r--r-- | fs/ocfs2/ocfs2_fs.h | 8 | ||||
-rw-r--r-- | fs/ocfs2/suballoc.c | 5 | ||||
-rw-r--r-- | fs/ocfs2/super.c | 17 |
6 files changed, 62 insertions, 14 deletions
diff --git a/Documentation/filesystems/ocfs2.txt b/Documentation/filesystems/ocfs2.txt index b63bd2d7fcd3..071fad137eb5 100644 --- a/Documentation/filesystems/ocfs2.txt +++ b/Documentation/filesystems/ocfs2.txt | |||
@@ -72,3 +72,6 @@ commit=nrsec (*) Ocfs2 can be told to sync all its data and metadata | |||
72 | it at the default (5 seconds). | 72 | it at the default (5 seconds). |
73 | Setting it to very large values will improve | 73 | Setting it to very large values will improve |
74 | performance. | 74 | performance. |
75 | localalloc=8(*) Allows custom localalloc size in MB. If the value is too | ||
76 | large, the fs will silently revert it to the default. | ||
77 | Localalloc is not enabled for local mounts. | ||
diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c index 0de0792fce7f..add1ffdc5c6c 100644 --- a/fs/ocfs2/localalloc.c +++ b/fs/ocfs2/localalloc.c | |||
@@ -75,18 +75,12 @@ static int ocfs2_local_alloc_new_window(struct ocfs2_super *osb, | |||
75 | static int ocfs2_local_alloc_slide_window(struct ocfs2_super *osb, | 75 | static int ocfs2_local_alloc_slide_window(struct ocfs2_super *osb, |
76 | struct inode *local_alloc_inode); | 76 | struct inode *local_alloc_inode); |
77 | 77 | ||
78 | /* | ||
79 | * Determine how large our local alloc window should be, in bits. | ||
80 | * | ||
81 | * These values (and the behavior in ocfs2_alloc_should_use_local) have | ||
82 | * been chosen so that most allocations, including new block groups go | ||
83 | * through local alloc. | ||
84 | */ | ||
85 | static inline int ocfs2_local_alloc_window_bits(struct ocfs2_super *osb) | 78 | static inline int ocfs2_local_alloc_window_bits(struct ocfs2_super *osb) |
86 | { | 79 | { |
87 | BUG_ON(osb->s_clustersize_bits < 12); | 80 | BUG_ON(osb->s_clustersize_bits > 20); |
88 | 81 | ||
89 | return 2048 >> (osb->s_clustersize_bits - 12); | 82 | /* Size local alloc windows by the megabyte */ |
83 | return osb->local_alloc_size << (20 - osb->s_clustersize_bits); | ||
90 | } | 84 | } |
91 | 85 | ||
92 | /* | 86 | /* |
@@ -96,18 +90,23 @@ static inline int ocfs2_local_alloc_window_bits(struct ocfs2_super *osb) | |||
96 | int ocfs2_alloc_should_use_local(struct ocfs2_super *osb, u64 bits) | 90 | int ocfs2_alloc_should_use_local(struct ocfs2_super *osb, u64 bits) |
97 | { | 91 | { |
98 | int la_bits = ocfs2_local_alloc_window_bits(osb); | 92 | int la_bits = ocfs2_local_alloc_window_bits(osb); |
93 | int ret = 0; | ||
99 | 94 | ||
100 | if (osb->local_alloc_state != OCFS2_LA_ENABLED) | 95 | if (osb->local_alloc_state != OCFS2_LA_ENABLED) |
101 | return 0; | 96 | goto bail; |
102 | 97 | ||
103 | /* la_bits should be at least twice the size (in clusters) of | 98 | /* la_bits should be at least twice the size (in clusters) of |
104 | * a new block group. We want to be sure block group | 99 | * a new block group. We want to be sure block group |
105 | * allocations go through the local alloc, so allow an | 100 | * allocations go through the local alloc, so allow an |
106 | * allocation to take up to half the bitmap. */ | 101 | * allocation to take up to half the bitmap. */ |
107 | if (bits > (la_bits / 2)) | 102 | if (bits > (la_bits / 2)) |
108 | return 0; | 103 | goto bail; |
109 | 104 | ||
110 | return 1; | 105 | ret = 1; |
106 | bail: | ||
107 | mlog(0, "state=%d, bits=%llu, la_bits=%d, ret=%d\n", | ||
108 | osb->local_alloc_state, (unsigned long long)bits, la_bits, ret); | ||
109 | return ret; | ||
111 | } | 110 | } |
112 | 111 | ||
113 | int ocfs2_load_local_alloc(struct ocfs2_super *osb) | 112 | int ocfs2_load_local_alloc(struct ocfs2_super *osb) |
@@ -121,6 +120,19 @@ int ocfs2_load_local_alloc(struct ocfs2_super *osb) | |||
121 | 120 | ||
122 | mlog_entry_void(); | 121 | mlog_entry_void(); |
123 | 122 | ||
123 | if (ocfs2_mount_local(osb)) | ||
124 | goto bail; | ||
125 | |||
126 | if (osb->local_alloc_size == 0) | ||
127 | goto bail; | ||
128 | |||
129 | if (ocfs2_local_alloc_window_bits(osb) >= osb->bitmap_cpg) { | ||
130 | mlog(ML_NOTICE, "Requested local alloc window %d is larger " | ||
131 | "than max possible %u. Using defaults.\n", | ||
132 | ocfs2_local_alloc_window_bits(osb), (osb->bitmap_cpg - 1)); | ||
133 | osb->local_alloc_size = OCFS2_DEFAULT_LOCAL_ALLOC_SIZE; | ||
134 | } | ||
135 | |||
124 | /* read the alloc off disk */ | 136 | /* read the alloc off disk */ |
125 | inode = ocfs2_get_system_file_inode(osb, LOCAL_ALLOC_SYSTEM_INODE, | 137 | inode = ocfs2_get_system_file_inode(osb, LOCAL_ALLOC_SYSTEM_INODE, |
126 | osb->slot_num); | 138 | osb->slot_num); |
@@ -181,6 +193,9 @@ bail: | |||
181 | if (inode) | 193 | if (inode) |
182 | iput(inode); | 194 | iput(inode); |
183 | 195 | ||
196 | mlog(0, "Local alloc window bits = %d\n", | ||
197 | ocfs2_local_alloc_window_bits(osb)); | ||
198 | |||
184 | mlog_exit(status); | 199 | mlog_exit(status); |
185 | return status; | 200 | return status; |
186 | } | 201 | } |
@@ -521,6 +536,9 @@ bail: | |||
521 | iput(local_alloc_inode); | 536 | iput(local_alloc_inode); |
522 | } | 537 | } |
523 | 538 | ||
539 | mlog(0, "bits=%d, slot=%d, ret=%d\n", bits_wanted, osb->slot_num, | ||
540 | status); | ||
541 | |||
524 | mlog_exit(status); | 542 | mlog_exit(status); |
525 | return status; | 543 | return status; |
526 | } | 544 | } |
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index 82802f5672a1..d12bd7036da7 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h | |||
@@ -231,6 +231,7 @@ struct ocfs2_super | |||
231 | struct ocfs2_journal *journal; | 231 | struct ocfs2_journal *journal; |
232 | unsigned long osb_commit_interval; | 232 | unsigned long osb_commit_interval; |
233 | 233 | ||
234 | int local_alloc_size; | ||
234 | enum ocfs2_local_alloc_state local_alloc_state; | 235 | enum ocfs2_local_alloc_state local_alloc_state; |
235 | struct buffer_head *local_alloc_bh; | 236 | struct buffer_head *local_alloc_bh; |
236 | u64 la_last_gd; | 237 | u64 la_last_gd; |
diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h index 425551737f1f..3633edd3982f 100644 --- a/fs/ocfs2/ocfs2_fs.h +++ b/fs/ocfs2/ocfs2_fs.h | |||
@@ -270,6 +270,14 @@ struct ocfs2_new_group_input { | |||
270 | /* Journal limits (in bytes) */ | 270 | /* Journal limits (in bytes) */ |
271 | #define OCFS2_MIN_JOURNAL_SIZE (4 * 1024 * 1024) | 271 | #define OCFS2_MIN_JOURNAL_SIZE (4 * 1024 * 1024) |
272 | 272 | ||
273 | /* | ||
274 | * Default local alloc size (in megabytes) | ||
275 | * | ||
276 | * The value chosen should be such that most allocations, including new | ||
277 | * block groups, use local alloc. | ||
278 | */ | ||
279 | #define OCFS2_DEFAULT_LOCAL_ALLOC_SIZE 8 | ||
280 | |||
273 | struct ocfs2_system_inode_info { | 281 | struct ocfs2_system_inode_info { |
274 | char *si_name; | 282 | char *si_name; |
275 | int si_iflags; | 283 | int si_iflags; |
diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index 4391744e80f8..7e397e2c25dd 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c | |||
@@ -1516,8 +1516,9 @@ int __ocfs2_claim_clusters(struct ocfs2_super *osb, | |||
1516 | if (min_clusters > (osb->bitmap_cpg - 1)) { | 1516 | if (min_clusters > (osb->bitmap_cpg - 1)) { |
1517 | /* The only paths asking for contiguousness | 1517 | /* The only paths asking for contiguousness |
1518 | * should know about this already. */ | 1518 | * should know about this already. */ |
1519 | mlog(ML_ERROR, "minimum allocation requested exceeds " | 1519 | mlog(ML_ERROR, "minimum allocation requested %u exceeds " |
1520 | "group bitmap size!"); | 1520 | "group bitmap size %u!\n", min_clusters, |
1521 | osb->bitmap_cpg); | ||
1521 | status = -ENOSPC; | 1522 | status = -ENOSPC; |
1522 | goto bail; | 1523 | goto bail; |
1523 | } | 1524 | } |
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 8044ed97d362..1104f14c3183 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c | |||
@@ -87,6 +87,7 @@ struct mount_options | |||
87 | unsigned long mount_opt; | 87 | unsigned long mount_opt; |
88 | unsigned int atime_quantum; | 88 | unsigned int atime_quantum; |
89 | signed short slot; | 89 | signed short slot; |
90 | unsigned int localalloc_opt; | ||
90 | }; | 91 | }; |
91 | 92 | ||
92 | static int ocfs2_parse_options(struct super_block *sb, char *options, | 93 | static int ocfs2_parse_options(struct super_block *sb, char *options, |
@@ -151,6 +152,7 @@ enum { | |||
151 | Opt_atime_quantum, | 152 | Opt_atime_quantum, |
152 | Opt_slot, | 153 | Opt_slot, |
153 | Opt_commit, | 154 | Opt_commit, |
155 | Opt_localalloc, | ||
154 | Opt_err, | 156 | Opt_err, |
155 | }; | 157 | }; |
156 | 158 | ||
@@ -167,6 +169,7 @@ static match_table_t tokens = { | |||
167 | {Opt_atime_quantum, "atime_quantum=%u"}, | 169 | {Opt_atime_quantum, "atime_quantum=%u"}, |
168 | {Opt_slot, "preferred_slot=%u"}, | 170 | {Opt_slot, "preferred_slot=%u"}, |
169 | {Opt_commit, "commit=%u"}, | 171 | {Opt_commit, "commit=%u"}, |
172 | {Opt_localalloc, "localalloc=%d"}, | ||
170 | {Opt_err, NULL} | 173 | {Opt_err, NULL} |
171 | }; | 174 | }; |
172 | 175 | ||
@@ -602,6 +605,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) | |||
602 | osb->s_atime_quantum = parsed_options.atime_quantum; | 605 | osb->s_atime_quantum = parsed_options.atime_quantum; |
603 | osb->preferred_slot = parsed_options.slot; | 606 | osb->preferred_slot = parsed_options.slot; |
604 | osb->osb_commit_interval = parsed_options.commit_interval; | 607 | osb->osb_commit_interval = parsed_options.commit_interval; |
608 | osb->local_alloc_size = parsed_options.localalloc_opt; | ||
605 | 609 | ||
606 | sb->s_magic = OCFS2_SUPER_MAGIC; | 610 | sb->s_magic = OCFS2_SUPER_MAGIC; |
607 | 611 | ||
@@ -756,6 +760,7 @@ static int ocfs2_parse_options(struct super_block *sb, | |||
756 | mopt->mount_opt = 0; | 760 | mopt->mount_opt = 0; |
757 | mopt->atime_quantum = OCFS2_DEFAULT_ATIME_QUANTUM; | 761 | mopt->atime_quantum = OCFS2_DEFAULT_ATIME_QUANTUM; |
758 | mopt->slot = OCFS2_INVALID_SLOT; | 762 | mopt->slot = OCFS2_INVALID_SLOT; |
763 | mopt->localalloc_opt = OCFS2_DEFAULT_LOCAL_ALLOC_SIZE; | ||
759 | 764 | ||
760 | if (!options) { | 765 | if (!options) { |
761 | status = 1; | 766 | status = 1; |
@@ -834,6 +839,15 @@ static int ocfs2_parse_options(struct super_block *sb, | |||
834 | option = JBD_DEFAULT_MAX_COMMIT_AGE; | 839 | option = JBD_DEFAULT_MAX_COMMIT_AGE; |
835 | mopt->commit_interval = HZ * option; | 840 | mopt->commit_interval = HZ * option; |
836 | break; | 841 | break; |
842 | case Opt_localalloc: | ||
843 | option = 0; | ||
844 | if (match_int(&args[0], &option)) { | ||
845 | status = 0; | ||
846 | goto bail; | ||
847 | } | ||
848 | if (option >= 0 && (option <= ocfs2_local_alloc_size(sb) * 8)) | ||
849 | mopt->localalloc_opt = option; | ||
850 | break; | ||
837 | default: | 851 | default: |
838 | mlog(ML_ERROR, | 852 | mlog(ML_ERROR, |
839 | "Unrecognized mount option \"%s\" " | 853 | "Unrecognized mount option \"%s\" " |
@@ -886,6 +900,9 @@ static int ocfs2_show_options(struct seq_file *s, struct vfsmount *mnt) | |||
886 | seq_printf(s, ",commit=%u", | 900 | seq_printf(s, ",commit=%u", |
887 | (unsigned) (osb->osb_commit_interval / HZ)); | 901 | (unsigned) (osb->osb_commit_interval / HZ)); |
888 | 902 | ||
903 | if (osb->local_alloc_size != OCFS2_DEFAULT_LOCAL_ALLOC_SIZE) | ||
904 | seq_printf(s, ",localalloc=%d", osb->local_alloc_size); | ||
905 | |||
889 | return 0; | 906 | return 0; |
890 | } | 907 | } |
891 | 908 | ||