aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nilfs2/sufile.c
diff options
context:
space:
mode:
authorRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>2011-05-04 12:23:57 -0400
committerRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>2011-05-10 09:21:45 -0400
commit619205da5b567504310daf829dede1187fa29bbc (patch)
treecd672bb647ff22c711d93437fc53821852f27eba /fs/nilfs2/sufile.c
parent56eb55388580ebd51f3bbd9af40ebb56849356af (diff)
nilfs2: add ioctl which limits range of segment to be allocated
This adds a new ioctl command which limits range of segment to be allocated. This is intended to gather data whithin a range of the partition before shrinking the filesystem, or to control new log location for some purpose. If a range is specified by the ioctl, segment allocator of nilfs tries to allocate new segments from the range unless no free segments are available there. Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Diffstat (limited to 'fs/nilfs2/sufile.c')
-rw-r--r--fs/nilfs2/sufile.c73
1 files changed, 63 insertions, 10 deletions
diff --git a/fs/nilfs2/sufile.c b/fs/nilfs2/sufile.c
index 1d6f488ccae8..f4374df00ad5 100644
--- a/fs/nilfs2/sufile.c
+++ b/fs/nilfs2/sufile.c
@@ -33,7 +33,9 @@
33 33
34struct nilfs_sufile_info { 34struct nilfs_sufile_info {
35 struct nilfs_mdt_info mi; 35 struct nilfs_mdt_info mi;
36 unsigned long ncleansegs; 36 unsigned long ncleansegs;/* number of clean segments */
37 __u64 allocmin; /* lower limit of allocatable segment range */
38 __u64 allocmax; /* upper limit of allocatable segment range */
37}; 39};
38 40
39static inline struct nilfs_sufile_info *NILFS_SUI(struct inode *sufile) 41static inline struct nilfs_sufile_info *NILFS_SUI(struct inode *sufile)
@@ -248,6 +250,35 @@ int nilfs_sufile_update(struct inode *sufile, __u64 segnum, int create,
248} 250}
249 251
250/** 252/**
253 * nilfs_sufile_set_alloc_range - limit range of segment to be allocated
254 * @sufile: inode of segment usage file
255 * @start: minimum segment number of allocatable region (inclusive)
256 * @end: maximum segment number of allocatable region (inclusive)
257 *
258 * Return Value: On success, 0 is returned. On error, one of the
259 * following negative error codes is returned.
260 *
261 * %-ERANGE - invalid segment region
262 */
263int nilfs_sufile_set_alloc_range(struct inode *sufile, __u64 start, __u64 end)
264{
265 struct nilfs_sufile_info *sui = NILFS_SUI(sufile);
266 __u64 nsegs;
267 int ret = -ERANGE;
268
269 down_write(&NILFS_MDT(sufile)->mi_sem);
270 nsegs = nilfs_sufile_get_nsegments(sufile);
271
272 if (start <= end && end < nsegs) {
273 sui->allocmin = start;
274 sui->allocmax = end;
275 ret = 0;
276 }
277 up_write(&NILFS_MDT(sufile)->mi_sem);
278 return ret;
279}
280
281/**
251 * nilfs_sufile_alloc - allocate a segment 282 * nilfs_sufile_alloc - allocate a segment
252 * @sufile: inode of segment usage file 283 * @sufile: inode of segment usage file
253 * @segnump: pointer to segment number 284 * @segnump: pointer to segment number
@@ -269,11 +300,12 @@ int nilfs_sufile_alloc(struct inode *sufile, __u64 *segnump)
269 struct buffer_head *header_bh, *su_bh; 300 struct buffer_head *header_bh, *su_bh;
270 struct nilfs_sufile_header *header; 301 struct nilfs_sufile_header *header;
271 struct nilfs_segment_usage *su; 302 struct nilfs_segment_usage *su;
303 struct nilfs_sufile_info *sui = NILFS_SUI(sufile);
272 size_t susz = NILFS_MDT(sufile)->mi_entry_size; 304 size_t susz = NILFS_MDT(sufile)->mi_entry_size;
273 __u64 segnum, maxsegnum, last_alloc; 305 __u64 segnum, maxsegnum, last_alloc;
274 void *kaddr; 306 void *kaddr;
275 unsigned long nsegments, ncleansegs, nsus; 307 unsigned long nsegments, ncleansegs, nsus, cnt;
276 int ret, i, j; 308 int ret, j;
277 309
278 down_write(&NILFS_MDT(sufile)->mi_sem); 310 down_write(&NILFS_MDT(sufile)->mi_sem);
279 311
@@ -287,13 +319,31 @@ int nilfs_sufile_alloc(struct inode *sufile, __u64 *segnump)
287 kunmap_atomic(kaddr, KM_USER0); 319 kunmap_atomic(kaddr, KM_USER0);
288 320
289 nsegments = nilfs_sufile_get_nsegments(sufile); 321 nsegments = nilfs_sufile_get_nsegments(sufile);
322 maxsegnum = sui->allocmax;
290 segnum = last_alloc + 1; 323 segnum = last_alloc + 1;
291 maxsegnum = nsegments - 1; 324 if (segnum < sui->allocmin || segnum > sui->allocmax)
292 for (i = 0; i < nsegments; i += nsus) { 325 segnum = sui->allocmin;
293 if (segnum >= nsegments) { 326
294 /* wrap around */ 327 for (cnt = 0; cnt < nsegments; cnt += nsus) {
295 segnum = 0; 328 if (segnum > maxsegnum) {
296 maxsegnum = last_alloc; 329 if (cnt < sui->allocmax - sui->allocmin + 1) {
330 /*
331 * wrap around in the limited region.
332 * if allocation started from
333 * sui->allocmin, this never happens.
334 */
335 segnum = sui->allocmin;
336 maxsegnum = last_alloc;
337 } else if (segnum > sui->allocmin &&
338 sui->allocmax + 1 < nsegments) {
339 segnum = sui->allocmax + 1;
340 maxsegnum = nsegments - 1;
341 } else if (sui->allocmin > 0) {
342 segnum = 0;
343 maxsegnum = sui->allocmin - 1;
344 } else {
345 break; /* never happens */
346 }
297 } 347 }
298 ret = nilfs_sufile_get_segment_usage_block(sufile, segnum, 1, 348 ret = nilfs_sufile_get_segment_usage_block(sufile, segnum, 1,
299 &su_bh); 349 &su_bh);
@@ -319,7 +369,7 @@ int nilfs_sufile_alloc(struct inode *sufile, __u64 *segnump)
319 header->sh_last_alloc = cpu_to_le64(segnum); 369 header->sh_last_alloc = cpu_to_le64(segnum);
320 kunmap_atomic(kaddr, KM_USER0); 370 kunmap_atomic(kaddr, KM_USER0);
321 371
322 NILFS_SUI(sufile)->ncleansegs--; 372 sui->ncleansegs--;
323 nilfs_mdt_mark_buffer_dirty(header_bh); 373 nilfs_mdt_mark_buffer_dirty(header_bh);
324 nilfs_mdt_mark_buffer_dirty(su_bh); 374 nilfs_mdt_mark_buffer_dirty(su_bh);
325 nilfs_mdt_mark_dirty(sufile); 375 nilfs_mdt_mark_dirty(sufile);
@@ -679,6 +729,9 @@ int nilfs_sufile_read(struct super_block *sb, size_t susize,
679 kunmap_atomic(kaddr, KM_USER0); 729 kunmap_atomic(kaddr, KM_USER0);
680 brelse(header_bh); 730 brelse(header_bh);
681 731
732 sui->allocmax = nilfs_sufile_get_nsegments(sufile) - 1;
733 sui->allocmin = 0;
734
682 unlock_new_inode(sufile); 735 unlock_new_inode(sufile);
683 out: 736 out:
684 *inodep = sufile; 737 *inodep = sufile;