aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/filesystems/ocfs2.txt3
-rw-r--r--fs/ocfs2/localalloc.c42
-rw-r--r--fs/ocfs2/ocfs2.h1
-rw-r--r--fs/ocfs2/ocfs2_fs.h8
-rw-r--r--fs/ocfs2/suballoc.c5
-rw-r--r--fs/ocfs2/super.c17
6 files changed, 62 insertions, 14 deletions
diff --git a/Documentation/filesystems/ocfs2.txt b/Documentation/filesystems/ocfs2.txt
index b63bd2d7fcd..071fad137eb 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.
75localalloc=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 0de0792fce7..add1ffdc5c6 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,
75static int ocfs2_local_alloc_slide_window(struct ocfs2_super *osb, 75static 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 */
85static inline int ocfs2_local_alloc_window_bits(struct ocfs2_super *osb) 78static 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)
96int ocfs2_alloc_should_use_local(struct ocfs2_super *osb, u64 bits) 90int 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;
106bail:
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
113int ocfs2_load_local_alloc(struct ocfs2_super *osb) 112int 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 82802f5672a..d12bd7036da 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 425551737f1..3633edd3982 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
273struct ocfs2_system_inode_info { 281struct 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 4391744e80f..7e397e2c25d 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 8044ed97d36..1104f14c318 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
92static int ocfs2_parse_options(struct super_block *sb, char *options, 93static 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