1 /* 2 * sufile.c - NILFS segment usage file. 3 * 4 * Copyright (C) 2006-2008 Nippon Telegraph and Telephone Corporation. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 * 20 * Written by Koji Sato <koji@osrg.net>. 21 * Revised by Ryusuke Konishi <ryusuke@osrg.net>. 22 */ 23 24 #include <linux/kernel.h> 25 #include <linux/fs.h> 26 #include <linux/string.h> 27 #include <linux/buffer_head.h> 28 #include <linux/errno.h> 29 #include <linux/nilfs2_fs.h> 30 #include "mdt.h" 31 #include "sufile.h" 32 33 34 struct nilfs_sufile_info { 35 struct nilfs_mdt_info mi; 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 */ 39 }; 40 41 static inline struct nilfs_sufile_info *NILFS_SUI(struct inode *sufile) 42 { 43 return (struct nilfs_sufile_info *)NILFS_MDT(sufile); 44 } 45 46 static inline unsigned long 47 nilfs_sufile_segment_usages_per_block(const struct inode *sufile) 48 { 49 return NILFS_MDT(sufile)->mi_entries_per_block; 50 } 51 52 static unsigned long 53 nilfs_sufile_get_blkoff(const struct inode *sufile, __u64 segnum) 54 { 55 __u64 t = segnum + NILFS_MDT(sufile)->mi_first_entry_offset; 56 do_div(t, nilfs_sufile_segment_usages_per_block(sufile)); 57 return (unsigned long)t; 58 } 59 60 static unsigned long 61 nilfs_sufile_get_offset(const struct inode *sufile, __u64 segnum) 62 { 63 __u64 t = segnum + NILFS_MDT(sufile)->mi_first_entry_offset; 64 return do_div(t, nilfs_sufile_segment_usages_per_block(sufile)); 65 } 66 67 static unsigned long 68 nilfs_sufile_segment_usages_in_block(const struct inode *sufile, __u64 curr, 69 __u64 max) 70 { 71 return min_t(unsigned long, 72 nilfs_sufile_segment_usages_per_block(sufile) - 73 nilfs_sufile_get_offset(sufile, curr), 74 max - curr + 1); 75 } 76 77 static struct nilfs_segment_usage * 78 nilfs_sufile_block_get_segment_usage(const struct inode *sufile, __u64 segnum, 79 struct buffer_head *bh, void *kaddr) 80 { 81 return kaddr + bh_offset(bh) + 82 nilfs_sufile_get_offset(sufile, segnum) * 83 NILFS_MDT(sufile)->mi_entry_size; 84 } 85 86 static inline int nilfs_sufile_get_header_block(struct inode *sufile, 87 struct buffer_head **bhp) 88 { 89 return nilfs_mdt_get_block(sufile, 0, 0, NULL, bhp); 90 } 91 92 static inline int 93 nilfs_sufile_get_segment_usage_block(struct inode *sufile, __u64 segnum, 94 int create, struct buffer_head **bhp) 95 { 96 return nilfs_mdt_get_block(sufile, 97 nilfs_sufile_get_blkoff(sufile, segnum), 98 create, NULL, bhp); 99 } 100 101 static int nilfs_sufile_delete_segment_usage_block(struct inode *sufile, 102 __u64 segnum) 103 { 104 return nilfs_mdt_delete_block(sufile, 105 nilfs_sufile_get_blkoff(sufile, segnum)); 106 } 107 108 static void nilfs_sufile_mod_counter(struct buffer_head *header_bh, 109 u64 ncleanadd, u64 ndirtyadd) 110 { 111 struct nilfs_sufile_header *header; 112 void *kaddr; 113 114 kaddr = kmap_atomic(header_bh->b_page); 115 header = kaddr + bh_offset(header_bh); 116 le64_add_cpu(&header->sh_ncleansegs, ncleanadd); 117 le64_add_cpu(&header->sh_ndirtysegs, ndirtyadd); 118 kunmap_atomic(kaddr); 119 120 mark_buffer_dirty(header_bh); 121 } 122 123 /** 124 * nilfs_sufile_get_ncleansegs - return the number of clean segments 125 * @sufile: inode of segment usage file 126 */ 127 unsigned long nilfs_sufile_get_ncleansegs(struct inode *sufile) 128 { 129 return NILFS_SUI(sufile)->ncleansegs; 130 } 131 132 /** 133 * nilfs_sufile_updatev - modify multiple segment usages at a time 134 * @sufile: inode of segment usage file 135 * @segnumv: array of segment numbers 136 * @nsegs: size of @segnumv array 137 * @create: creation flag 138 * @ndone: place to store number of modified segments on @segnumv 139 * @dofunc: primitive operation for the update 140 * 141 * Description: nilfs_sufile_updatev() repeatedly calls @dofunc 142 * against the given array of segments. The @dofunc is called with 143 * buffers of a header block and the sufile block in which the target 144 * segment usage entry is contained. If @ndone is given, the number 145 * of successfully modified segments from the head is stored in the 146 * place @ndone points to. 147 * 148 * Return Value: On success, zero is returned. On error, one of the 149 * following negative error codes is returned. 150 * 151 * %-EIO - I/O error. 152 * 153 * %-ENOMEM - Insufficient amount of memory available. 154 * 155 * %-ENOENT - Given segment usage is in hole block (may be returned if 156 * @create is zero) 157 * 158 * %-EINVAL - Invalid segment usage number 159 */ 160 int nilfs_sufile_updatev(struct inode *sufile, __u64 *segnumv, size_t nsegs, 161 int create, size_t *ndone, 162 void (*dofunc)(struct inode *, __u64, 163 struct buffer_head *, 164 struct buffer_head *)) 165 { 166 struct buffer_head *header_bh, *bh; 167 unsigned long blkoff, prev_blkoff; 168 __u64 *seg; 169 size_t nerr = 0, n = 0; 170 int ret = 0; 171 172 if (unlikely(nsegs == 0)) 173 goto out; 174 175 down_write(&NILFS_MDT(sufile)->mi_sem); 176 for (seg = segnumv; seg < segnumv + nsegs; seg++) { 177 if (unlikely(*seg >= nilfs_sufile_get_nsegments(sufile))) { 178 printk(KERN_WARNING 179 "%s: invalid segment number: %llu\n", __func__, 180 (unsigned long long)*seg); 181 nerr++; 182 } 183 } 184 if (nerr > 0) { 185 ret = -EINVAL; 186 goto out_sem; 187 } 188 189 ret = nilfs_sufile_get_header_block(sufile, &header_bh); 190 if (ret < 0) 191 goto out_sem; 192 193 seg = segnumv; 194 blkoff = nilfs_sufile_get_blkoff(sufile, *seg); 195 ret = nilfs_mdt_get_block(sufile, blkoff, create, NULL, &bh); 196 if (ret < 0) 197 goto out_header; 198 199 for (;;) { 200 dofunc(sufile, *seg, header_bh, bh); 201 202 if (++seg >= segnumv + nsegs) 203 break; 204 prev_blkoff = blkoff; 205 blkoff = nilfs_sufile_get_blkoff(sufile, *seg); 206 if (blkoff == prev_blkoff) 207 continue; 208 209 /* get different block */ 210 brelse(bh); 211 ret = nilfs_mdt_get_block(sufile, blkoff, create, NULL, &bh); 212 if (unlikely(ret < 0)) 213 goto out_header; 214 } 215 brelse(bh); 216 217 out_header: 218 n = seg - segnumv; 219 brelse(header_bh); 220 out_sem: 221 up_write(&NILFS_MDT(sufile)->mi_sem); 222 out: 223 if (ndone) 224 *ndone = n; 225 return ret; 226 } 227 228 int nilfs_sufile_update(struct inode *sufile, __u64 segnum, int create, 229 void (*dofunc)(struct inode *, __u64, 230 struct buffer_head *, 231 struct buffer_head *)) 232 { 233 struct buffer_head *header_bh, *bh; 234 int ret; 235 236 if (unlikely(segnum >= nilfs_sufile_get_nsegments(sufile))) { 237 printk(KERN_WARNING "%s: invalid segment number: %llu\n", 238 __func__, (unsigned long long)segnum); 239 return -EINVAL; 240 } 241 down_write(&NILFS_MDT(sufile)->mi_sem); 242 243 ret = nilfs_sufile_get_header_block(sufile, &header_bh); 244 if (ret < 0) 245 goto out_sem; 246 247 ret = nilfs_sufile_get_segment_usage_block(sufile, segnum, create, &bh); 248 if (!ret) { 249 dofunc(sufile, segnum, header_bh, bh); 250 brelse(bh); 251 } 252 brelse(header_bh); 253 254 out_sem: 255 up_write(&NILFS_MDT(sufile)->mi_sem); 256 return ret; 257 } 258 259 /** 260 * nilfs_sufile_set_alloc_range - limit range of segment to be allocated 261 * @sufile: inode of segment usage file 262 * @start: minimum segment number of allocatable region (inclusive) 263 * @end: maximum segment number of allocatable region (inclusive) 264 * 265 * Return Value: On success, 0 is returned. On error, one of the 266 * following negative error codes is returned. 267 * 268 * %-ERANGE - invalid segment region 269 */ 270 int nilfs_sufile_set_alloc_range(struct inode *sufile, __u64 start, __u64 end) 271 { 272 struct nilfs_sufile_info *sui = NILFS_SUI(sufile); 273 __u64 nsegs; 274 int ret = -ERANGE; 275 276 down_write(&NILFS_MDT(sufile)->mi_sem); 277 nsegs = nilfs_sufile_get_nsegments(sufile); 278 279 if (start <= end && end < nsegs) { 280 sui->allocmin = start; 281 sui->allocmax = end; 282 ret = 0; 283 } 284 up_write(&NILFS_MDT(sufile)->mi_sem); 285 return ret; 286 } 287 288 /** 289 * nilfs_sufile_alloc - allocate a segment 290 * @sufile: inode of segment usage file 291 * @segnump: pointer to segment number 292 * 293 * Description: nilfs_sufile_alloc() allocates a clean segment. 294 * 295 * Return Value: On success, 0 is returned and the segment number of the 296 * allocated segment is stored in the place pointed by @segnump. On error, one 297 * of the following negative error codes is returned. 298 * 299 * %-EIO - I/O error. 300 * 301 * %-ENOMEM - Insufficient amount of memory available. 302 * 303 * %-ENOSPC - No clean segment left. 304 */ 305 int nilfs_sufile_alloc(struct inode *sufile, __u64 *segnump) 306 { 307 struct buffer_head *header_bh, *su_bh; 308 struct nilfs_sufile_header *header; 309 struct nilfs_segment_usage *su; 310 struct nilfs_sufile_info *sui = NILFS_SUI(sufile); 311 size_t susz = NILFS_MDT(sufile)->mi_entry_size; 312 __u64 segnum, maxsegnum, last_alloc; 313 void *kaddr; 314 unsigned long nsegments, ncleansegs, nsus, cnt; 315 int ret, j; 316 317 down_write(&NILFS_MDT(sufile)->mi_sem); 318 319 ret = nilfs_sufile_get_header_block(sufile, &header_bh); 320 if (ret < 0) 321 goto out_sem; 322 kaddr = kmap_atomic(header_bh->b_page); 323 header = kaddr + bh_offset(header_bh); 324 ncleansegs = le64_to_cpu(header->sh_ncleansegs); 325 last_alloc = le64_to_cpu(header->sh_last_alloc); 326 kunmap_atomic(kaddr); 327 328 nsegments = nilfs_sufile_get_nsegments(sufile); 329 maxsegnum = sui->allocmax; 330 segnum = last_alloc + 1; 331 if (segnum < sui->allocmin || segnum > sui->allocmax) 332 segnum = sui->allocmin; 333 334 for (cnt = 0; cnt < nsegments; cnt += nsus) { 335 if (segnum > maxsegnum) { 336 if (cnt < sui->allocmax - sui->allocmin + 1) { 337 /* 338 * wrap around in the limited region. 339 * if allocation started from 340 * sui->allocmin, this never happens. 341 */ 342 segnum = sui->allocmin; 343 maxsegnum = last_alloc; 344 } else if (segnum > sui->allocmin && 345 sui->allocmax + 1 < nsegments) { 346 segnum = sui->allocmax + 1; 347 maxsegnum = nsegments - 1; 348 } else if (sui->allocmin > 0) { 349 segnum = 0; 350 maxsegnum = sui->allocmin - 1; 351 } else { 352 break; /* never happens */ 353 } 354 } 355 ret = nilfs_sufile_get_segment_usage_block(sufile, segnum, 1, 356 &su_bh); 357 if (ret < 0) 358 goto out_header; 359 kaddr = kmap_atomic(su_bh->b_page); 360 su = nilfs_sufile_block_get_segment_usage( 361 sufile, segnum, su_bh, kaddr); 362 363 nsus = nilfs_sufile_segment_usages_in_block( 364 sufile, segnum, maxsegnum); 365 for (j = 0; j < nsus; j++, su = (void *)su + susz, segnum++) { 366 if (!nilfs_segment_usage_clean(su)) 367 continue; 368 /* found a clean segment */ 369 nilfs_segment_usage_set_dirty(su); 370 kunmap_atomic(kaddr); 371 372 kaddr = kmap_atomic(header_bh->b_page); 373 header = kaddr + bh_offset(header_bh); 374 le64_add_cpu(&header->sh_ncleansegs, -1); 375 le64_add_cpu(&header->sh_ndirtysegs, 1); 376 header->sh_last_alloc = cpu_to_le64(segnum); 377 kunmap_atomic(kaddr); 378 379 sui->ncleansegs--; 380 mark_buffer_dirty(header_bh); 381 mark_buffer_dirty(su_bh); 382 nilfs_mdt_mark_dirty(sufile); 383 brelse(su_bh); 384 *segnump = segnum; 385 goto out_header; 386 } 387 388 kunmap_atomic(kaddr); 389 brelse(su_bh); 390 } 391 392 /* no segments left */ 393 ret = -ENOSPC; 394 395 out_header: 396 brelse(header_bh); 397 398 out_sem: 399 up_write(&NILFS_MDT(sufile)->mi_sem); 400 return ret; 401 } 402 403 void nilfs_sufile_do_cancel_free(struct inode *sufile, __u64 segnum, 404 struct buffer_head *header_bh, 405 struct buffer_head *su_bh) 406 { 407 struct nilfs_segment_usage *su; 408 void *kaddr; 409 410 kaddr = kmap_atomic(su_bh->b_page); 411 su = nilfs_sufile_block_get_segment_usage(sufile, segnum, su_bh, kaddr); 412 if (unlikely(!nilfs_segment_usage_clean(su))) { 413 printk(KERN_WARNING "%s: segment %llu must be clean\n", 414 __func__, (unsigned long long)segnum); 415 kunmap_atomic(kaddr); 416 return; 417 } 418 nilfs_segment_usage_set_dirty(su); 419 kunmap_atomic(kaddr); 420 421 nilfs_sufile_mod_counter(header_bh, -1, 1); 422 NILFS_SUI(sufile)->ncleansegs--; 423 424 mark_buffer_dirty(su_bh); 425 nilfs_mdt_mark_dirty(sufile); 426 } 427 428 void nilfs_sufile_do_scrap(struct inode *sufile, __u64 segnum, 429 struct buffer_head *header_bh, 430 struct buffer_head *su_bh) 431 { 432 struct nilfs_segment_usage *su; 433 void *kaddr; 434 int clean, dirty; 435 436 kaddr = kmap_atomic(su_bh->b_page); 437 su = nilfs_sufile_block_get_segment_usage(sufile, segnum, su_bh, kaddr); 438 if (su->su_flags == cpu_to_le32(1UL << NILFS_SEGMENT_USAGE_DIRTY) && 439 su->su_nblocks == cpu_to_le32(0)) { 440 kunmap_atomic(kaddr); 441 return; 442 } 443 clean = nilfs_segment_usage_clean(su); 444 dirty = nilfs_segment_usage_dirty(su); 445 446 /* make the segment garbage */ 447 su->su_lastmod = cpu_to_le64(0); 448 su->su_nblocks = cpu_to_le32(0); 449 su->su_flags = cpu_to_le32(1UL << NILFS_SEGMENT_USAGE_DIRTY); 450 kunmap_atomic(kaddr); 451 452 nilfs_sufile_mod_counter(header_bh, clean ? (u64)-1 : 0, dirty ? 0 : 1); 453 NILFS_SUI(sufile)->ncleansegs -= clean; 454 455 mark_buffer_dirty(su_bh); 456 nilfs_mdt_mark_dirty(sufile); 457 } 458 459 void nilfs_sufile_do_free(struct inode *sufile, __u64 segnum, 460 struct buffer_head *header_bh, 461 struct buffer_head *su_bh) 462 { 463 struct nilfs_segment_usage *su; 464 void *kaddr; 465 int sudirty; 466 467 kaddr = kmap_atomic(su_bh->b_page); 468 su = nilfs_sufile_block_get_segment_usage(sufile, segnum, su_bh, kaddr); 469 if (nilfs_segment_usage_clean(su)) { 470 printk(KERN_WARNING "%s: segment %llu is already clean\n", 471 __func__, (unsigned long long)segnum); 472 kunmap_atomic(kaddr); 473 return; 474 } 475 WARN_ON(nilfs_segment_usage_error(su)); 476 WARN_ON(!nilfs_segment_usage_dirty(su)); 477 478 sudirty = nilfs_segment_usage_dirty(su); 479 nilfs_segment_usage_set_clean(su); 480 kunmap_atomic(kaddr); 481 mark_buffer_dirty(su_bh); 482 483 nilfs_sufile_mod_counter(header_bh, 1, sudirty ? (u64)-1 : 0); 484 NILFS_SUI(sufile)->ncleansegs++; 485 486 nilfs_mdt_mark_dirty(sufile); 487 } 488 489 /** 490 * nilfs_sufile_mark_dirty - mark the buffer having a segment usage dirty 491 * @sufile: inode of segment usage file 492 * @segnum: segment number 493 */ 494 int nilfs_sufile_mark_dirty(struct inode *sufile, __u64 segnum) 495 { 496 struct buffer_head *bh; 497 int ret; 498 499 ret = nilfs_sufile_get_segment_usage_block(sufile, segnum, 0, &bh); 500 if (!ret) { 501 mark_buffer_dirty(bh); 502 nilfs_mdt_mark_dirty(sufile); 503 brelse(bh); 504 } 505 return ret; 506 } 507 508 /** 509 * nilfs_sufile_set_segment_usage - set usage of a segment 510 * @sufile: inode of segment usage file 511 * @segnum: segment number 512 * @nblocks: number of live blocks in the segment 513 * @modtime: modification time (option) 514 */ 515 int nilfs_sufile_set_segment_usage(struct inode *sufile, __u64 segnum, 516 unsigned long nblocks, time_t modtime) 517 { 518 struct buffer_head *bh; 519 struct nilfs_segment_usage *su; 520 void *kaddr; 521 int ret; 522 523 down_write(&NILFS_MDT(sufile)->mi_sem); 524 ret = nilfs_sufile_get_segment_usage_block(sufile, segnum, 0, &bh); 525 if (ret < 0) 526 goto out_sem; 527 528 kaddr = kmap_atomic(bh->b_page); 529 su = nilfs_sufile_block_get_segment_usage(sufile, segnum, bh, kaddr); 530 WARN_ON(nilfs_segment_usage_error(su)); 531 if (modtime) 532 su->su_lastmod = cpu_to_le64(modtime); 533 su->su_nblocks = cpu_to_le32(nblocks); 534 kunmap_atomic(kaddr); 535 536 mark_buffer_dirty(bh); 537 nilfs_mdt_mark_dirty(sufile); 538 brelse(bh); 539 540 out_sem: 541 up_write(&NILFS_MDT(sufile)->mi_sem); 542 return ret; 543 } 544 545 /** 546 * nilfs_sufile_get_stat - get segment usage statistics 547 * @sufile: inode of segment usage file 548 * @stat: pointer to a structure of segment usage statistics 549 * 550 * Description: nilfs_sufile_get_stat() returns information about segment 551 * usage. 552 * 553 * Return Value: On success, 0 is returned, and segment usage information is 554 * stored in the place pointed by @stat. On error, one of the following 555 * negative error codes is returned. 556 * 557 * %-EIO - I/O error. 558 * 559 * %-ENOMEM - Insufficient amount of memory available. 560 */ 561 int nilfs_sufile_get_stat(struct inode *sufile, struct nilfs_sustat *sustat) 562 { 563 struct buffer_head *header_bh; 564 struct nilfs_sufile_header *header; 565 struct the_nilfs *nilfs = sufile->i_sb->s_fs_info; 566 void *kaddr; 567 int ret; 568 569 down_read(&NILFS_MDT(sufile)->mi_sem); 570 571 ret = nilfs_sufile_get_header_block(sufile, &header_bh); 572 if (ret < 0) 573 goto out_sem; 574 575 kaddr = kmap_atomic(header_bh->b_page); 576 header = kaddr + bh_offset(header_bh); 577 sustat->ss_nsegs = nilfs_sufile_get_nsegments(sufile); 578 sustat->ss_ncleansegs = le64_to_cpu(header->sh_ncleansegs); 579 sustat->ss_ndirtysegs = le64_to_cpu(header->sh_ndirtysegs); 580 sustat->ss_ctime = nilfs->ns_ctime; 581 sustat->ss_nongc_ctime = nilfs->ns_nongc_ctime; 582 spin_lock(&nilfs->ns_last_segment_lock); 583 sustat->ss_prot_seq = nilfs->ns_prot_seq; 584 spin_unlock(&nilfs->ns_last_segment_lock); 585 kunmap_atomic(kaddr); 586 brelse(header_bh); 587 588 out_sem: 589 up_read(&NILFS_MDT(sufile)->mi_sem); 590 return ret; 591 } 592 593 void nilfs_sufile_do_set_error(struct inode *sufile, __u64 segnum, 594 struct buffer_head *header_bh, 595 struct buffer_head *su_bh) 596 { 597 struct nilfs_segment_usage *su; 598 void *kaddr; 599 int suclean; 600 601 kaddr = kmap_atomic(su_bh->b_page); 602 su = nilfs_sufile_block_get_segment_usage(sufile, segnum, su_bh, kaddr); 603 if (nilfs_segment_usage_error(su)) { 604 kunmap_atomic(kaddr); 605 return; 606 } 607 suclean = nilfs_segment_usage_clean(su); 608 nilfs_segment_usage_set_error(su); 609 kunmap_atomic(kaddr); 610 611 if (suclean) { 612 nilfs_sufile_mod_counter(header_bh, -1, 0); 613 NILFS_SUI(sufile)->ncleansegs--; 614 } 615 mark_buffer_dirty(su_bh); 616 nilfs_mdt_mark_dirty(sufile); 617 } 618 619 /** 620 * nilfs_sufile_truncate_range - truncate range of segment array 621 * @sufile: inode of segment usage file 622 * @start: start segment number (inclusive) 623 * @end: end segment number (inclusive) 624 * 625 * Return Value: On success, 0 is returned. On error, one of the 626 * following negative error codes is returned. 627 * 628 * %-EIO - I/O error. 629 * 630 * %-ENOMEM - Insufficient amount of memory available. 631 * 632 * %-EINVAL - Invalid number of segments specified 633 * 634 * %-EBUSY - Dirty or active segments are present in the range 635 */ 636 static int nilfs_sufile_truncate_range(struct inode *sufile, 637 __u64 start, __u64 end) 638 { 639 struct the_nilfs *nilfs = sufile->i_sb->s_fs_info; 640 struct buffer_head *header_bh; 641 struct buffer_head *su_bh; 642 struct nilfs_segment_usage *su, *su2; 643 size_t susz = NILFS_MDT(sufile)->mi_entry_size; 644 unsigned long segusages_per_block; 645 unsigned long nsegs, ncleaned; 646 __u64 segnum; 647 void *kaddr; 648 ssize_t n, nc; 649 int ret; 650 int j; 651 652 nsegs = nilfs_sufile_get_nsegments(sufile); 653 654 ret = -EINVAL; 655 if (start > end || start >= nsegs) 656 goto out; 657 658 ret = nilfs_sufile_get_header_block(sufile, &header_bh); 659 if (ret < 0) 660 goto out; 661 662 segusages_per_block = nilfs_sufile_segment_usages_per_block(sufile); 663 ncleaned = 0; 664 665 for (segnum = start; segnum <= end; segnum += n) { 666 n = min_t(unsigned long, 667 segusages_per_block - 668 nilfs_sufile_get_offset(sufile, segnum), 669 end - segnum + 1); 670 ret = nilfs_sufile_get_segment_usage_block(sufile, segnum, 0, 671 &su_bh); 672 if (ret < 0) { 673 if (ret != -ENOENT) 674 goto out_header; 675 /* hole */ 676 continue; 677 } 678 kaddr = kmap_atomic(su_bh->b_page); 679 su = nilfs_sufile_block_get_segment_usage( 680 sufile, segnum, su_bh, kaddr); 681 su2 = su; 682 for (j = 0; j < n; j++, su = (void *)su + susz) { 683 if ((le32_to_cpu(su->su_flags) & 684 ~(1UL << NILFS_SEGMENT_USAGE_ERROR)) || 685 nilfs_segment_is_active(nilfs, segnum + j)) { 686 ret = -EBUSY; 687 kunmap_atomic(kaddr); 688 brelse(su_bh); 689 goto out_header; 690 } 691 } 692 nc = 0; 693 for (su = su2, j = 0; j < n; j++, su = (void *)su + susz) { 694 if (nilfs_segment_usage_error(su)) { 695 nilfs_segment_usage_set_clean(su); 696 nc++; 697 } 698 } 699 kunmap_atomic(kaddr); 700 if (nc > 0) { 701 mark_buffer_dirty(su_bh); 702 ncleaned += nc; 703 } 704 brelse(su_bh); 705 706 if (n == segusages_per_block) { 707 /* make hole */ 708 nilfs_sufile_delete_segment_usage_block(sufile, segnum); 709 } 710 } 711 ret = 0; 712 713 out_header: 714 if (ncleaned > 0) { 715 NILFS_SUI(sufile)->ncleansegs += ncleaned; 716 nilfs_sufile_mod_counter(header_bh, ncleaned, 0); 717 nilfs_mdt_mark_dirty(sufile); 718 } 719 brelse(header_bh); 720 out: 721 return ret; 722 } 723 724 /** 725 * nilfs_sufile_resize - resize segment array 726 * @sufile: inode of segment usage file 727 * @newnsegs: new number of segments 728 * 729 * Return Value: On success, 0 is returned. On error, one of the 730 * following negative error codes is returned. 731 * 732 * %-EIO - I/O error. 733 * 734 * %-ENOMEM - Insufficient amount of memory available. 735 * 736 * %-ENOSPC - Enough free space is not left for shrinking 737 * 738 * %-EBUSY - Dirty or active segments exist in the region to be truncated 739 */ 740 int nilfs_sufile_resize(struct inode *sufile, __u64 newnsegs) 741 { 742 struct the_nilfs *nilfs = sufile->i_sb->s_fs_info; 743 struct buffer_head *header_bh; 744 struct nilfs_sufile_header *header; 745 struct nilfs_sufile_info *sui = NILFS_SUI(sufile); 746 void *kaddr; 747 unsigned long nsegs, nrsvsegs; 748 int ret = 0; 749 750 down_write(&NILFS_MDT(sufile)->mi_sem); 751 752 nsegs = nilfs_sufile_get_nsegments(sufile); 753 if (nsegs == newnsegs) 754 goto out; 755 756 ret = -ENOSPC; 757 nrsvsegs = nilfs_nrsvsegs(nilfs, newnsegs); 758 if (newnsegs < nsegs && nsegs - newnsegs + nrsvsegs > sui->ncleansegs) 759 goto out; 760 761 ret = nilfs_sufile_get_header_block(sufile, &header_bh); 762 if (ret < 0) 763 goto out; 764 765 if (newnsegs > nsegs) { 766 sui->ncleansegs += newnsegs - nsegs; 767 } else /* newnsegs < nsegs */ { 768 ret = nilfs_sufile_truncate_range(sufile, newnsegs, nsegs - 1); 769 if (ret < 0) 770 goto out_header; 771 772 sui->ncleansegs -= nsegs - newnsegs; 773 } 774 775 kaddr = kmap_atomic(header_bh->b_page); 776 header = kaddr + bh_offset(header_bh); 777 header->sh_ncleansegs = cpu_to_le64(sui->ncleansegs); 778 kunmap_atomic(kaddr); 779 780 mark_buffer_dirty(header_bh); 781 nilfs_mdt_mark_dirty(sufile); 782 nilfs_set_nsegments(nilfs, newnsegs); 783 784 out_header: 785 brelse(header_bh); 786 out: 787 up_write(&NILFS_MDT(sufile)->mi_sem); 788 return ret; 789 } 790 791 /** 792 * nilfs_sufile_get_suinfo - 793 * @sufile: inode of segment usage file 794 * @segnum: segment number to start looking 795 * @buf: array of suinfo 796 * @sisz: byte size of suinfo 797 * @nsi: size of suinfo array 798 * 799 * Description: 800 * 801 * Return Value: On success, 0 is returned and .... On error, one of the 802 * following negative error codes is returned. 803 * 804 * %-EIO - I/O error. 805 * 806 * %-ENOMEM - Insufficient amount of memory available. 807 */ 808 ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum, void *buf, 809 unsigned sisz, size_t nsi) 810 { 811 struct buffer_head *su_bh; 812 struct nilfs_segment_usage *su; 813 struct nilfs_suinfo *si = buf; 814 size_t susz = NILFS_MDT(sufile)->mi_entry_size; 815 struct the_nilfs *nilfs = sufile->i_sb->s_fs_info; 816 void *kaddr; 817 unsigned long nsegs, segusages_per_block; 818 ssize_t n; 819 int ret, i, j; 820 821 down_read(&NILFS_MDT(sufile)->mi_sem); 822 823 segusages_per_block = nilfs_sufile_segment_usages_per_block(sufile); 824 nsegs = min_t(unsigned long, 825 nilfs_sufile_get_nsegments(sufile) - segnum, 826 nsi); 827 for (i = 0; i < nsegs; i += n, segnum += n) { 828 n = min_t(unsigned long, 829 segusages_per_block - 830 nilfs_sufile_get_offset(sufile, segnum), 831 nsegs - i); 832 ret = nilfs_sufile_get_segment_usage_block(sufile, segnum, 0, 833 &su_bh); 834 if (ret < 0) { 835 if (ret != -ENOENT) 836 goto out; 837 /* hole */ 838 memset(si, 0, sisz * n); 839 si = (void *)si + sisz * n; 840 continue; 841 } 842 843 kaddr = kmap_atomic(su_bh->b_page); 844 su = nilfs_sufile_block_get_segment_usage( 845 sufile, segnum, su_bh, kaddr); 846 for (j = 0; j < n; 847 j++, su = (void *)su + susz, si = (void *)si + sisz) { 848 si->sui_lastmod = le64_to_cpu(su->su_lastmod); 849 si->sui_nblocks = le32_to_cpu(su->su_nblocks); 850 si->sui_flags = le32_to_cpu(su->su_flags) & 851 ~(1UL << NILFS_SEGMENT_USAGE_ACTIVE); 852 if (nilfs_segment_is_active(nilfs, segnum + j)) 853 si->sui_flags |= 854 (1UL << NILFS_SEGMENT_USAGE_ACTIVE); 855 } 856 kunmap_atomic(kaddr); 857 brelse(su_bh); 858 } 859 ret = nsegs; 860 861 out: 862 up_read(&NILFS_MDT(sufile)->mi_sem); 863 return ret; 864 } 865 866 /** 867 * nilfs_sufile_read - read or get sufile inode 868 * @sb: super block instance 869 * @susize: size of a segment usage entry 870 * @raw_inode: on-disk sufile inode 871 * @inodep: buffer to store the inode 872 */ 873 int nilfs_sufile_read(struct super_block *sb, size_t susize, 874 struct nilfs_inode *raw_inode, struct inode **inodep) 875 { 876 struct inode *sufile; 877 struct nilfs_sufile_info *sui; 878 struct buffer_head *header_bh; 879 struct nilfs_sufile_header *header; 880 void *kaddr; 881 int err; 882 883 sufile = nilfs_iget_locked(sb, NULL, NILFS_SUFILE_INO); 884 if (unlikely(!sufile)) 885 return -ENOMEM; 886 if (!(sufile->i_state & I_NEW)) 887 goto out; 888 889 err = nilfs_mdt_init(sufile, NILFS_MDT_GFP, sizeof(*sui)); 890 if (err) 891 goto failed; 892 893 nilfs_mdt_set_entry_size(sufile, susize, 894 sizeof(struct nilfs_sufile_header)); 895 896 err = nilfs_read_inode_common(sufile, raw_inode); 897 if (err) 898 goto failed; 899 900 err = nilfs_sufile_get_header_block(sufile, &header_bh); 901 if (err) 902 goto failed; 903 904 sui = NILFS_SUI(sufile); 905 kaddr = kmap_atomic(header_bh->b_page); 906 header = kaddr + bh_offset(header_bh); 907 sui->ncleansegs = le64_to_cpu(header->sh_ncleansegs); 908 kunmap_atomic(kaddr); 909 brelse(header_bh); 910 911 sui->allocmax = nilfs_sufile_get_nsegments(sufile) - 1; 912 sui->allocmin = 0; 913 914 unlock_new_inode(sufile); 915 out: 916 *inodep = sufile; 917 return 0; 918 failed: 919 iget_failed(sufile); 920 return err; 921 } 922