1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * NILFS segment usage file. 4 * 5 * Copyright (C) 2006-2008 Nippon Telegraph and Telephone Corporation. 6 * 7 * Written by Koji Sato. 8 * Revised by Ryusuke Konishi. 9 */ 10 11 #include <linux/kernel.h> 12 #include <linux/fs.h> 13 #include <linux/string.h> 14 #include <linux/buffer_head.h> 15 #include <linux/errno.h> 16 #include "mdt.h" 17 #include "sufile.h" 18 19 #include <trace/events/nilfs2.h> 20 21 /** 22 * struct nilfs_sufile_info - on-memory private data of sufile 23 * @mi: on-memory private data of metadata file 24 * @ncleansegs: number of clean segments 25 * @allocmin: lower limit of allocatable segment range 26 * @allocmax: upper limit of allocatable segment range 27 */ 28 struct nilfs_sufile_info { 29 struct nilfs_mdt_info mi; 30 unsigned long ncleansegs;/* number of clean segments */ 31 __u64 allocmin; /* lower limit of allocatable segment range */ 32 __u64 allocmax; /* upper limit of allocatable segment range */ 33 }; 34 35 static inline struct nilfs_sufile_info *NILFS_SUI(struct inode *sufile) 36 { 37 return (struct nilfs_sufile_info *)NILFS_MDT(sufile); 38 } 39 40 static inline unsigned long 41 nilfs_sufile_segment_usages_per_block(const struct inode *sufile) 42 { 43 return NILFS_MDT(sufile)->mi_entries_per_block; 44 } 45 46 static unsigned long 47 nilfs_sufile_get_blkoff(const struct inode *sufile, __u64 segnum) 48 { 49 __u64 t = segnum + NILFS_MDT(sufile)->mi_first_entry_offset; 50 51 t = div64_ul(t, nilfs_sufile_segment_usages_per_block(sufile)); 52 return (unsigned long)t; 53 } 54 55 static unsigned long 56 nilfs_sufile_get_offset(const struct inode *sufile, __u64 segnum) 57 { 58 __u64 t = segnum + NILFS_MDT(sufile)->mi_first_entry_offset; 59 60 return do_div(t, nilfs_sufile_segment_usages_per_block(sufile)); 61 } 62 63 static unsigned long 64 nilfs_sufile_segment_usages_in_block(const struct inode *sufile, __u64 curr, 65 __u64 max) 66 { 67 return min_t(unsigned long, 68 nilfs_sufile_segment_usages_per_block(sufile) - 69 nilfs_sufile_get_offset(sufile, curr), 70 max - curr + 1); 71 } 72 73 /** 74 * nilfs_sufile_segment_usage_offset - calculate the byte offset of a segment 75 * usage entry in the folio containing it 76 * @sufile: segment usage file inode 77 * @segnum: number of segment usage 78 * @bh: buffer head of block containing segment usage indexed by @segnum 79 * 80 * Return: Byte offset in the folio of the segment usage entry. 81 */ 82 static size_t nilfs_sufile_segment_usage_offset(const struct inode *sufile, 83 __u64 segnum, 84 struct buffer_head *bh) 85 { 86 return offset_in_folio(bh->b_folio, bh->b_data) + 87 nilfs_sufile_get_offset(sufile, segnum) * 88 NILFS_MDT(sufile)->mi_entry_size; 89 } 90 91 static int nilfs_sufile_get_header_block(struct inode *sufile, 92 struct buffer_head **bhp) 93 { 94 int err = nilfs_mdt_get_block(sufile, 0, 0, NULL, bhp); 95 96 if (unlikely(err == -ENOENT)) { 97 nilfs_error(sufile->i_sb, 98 "missing header block in segment usage metadata"); 99 err = -EIO; 100 } 101 return err; 102 } 103 104 static inline int 105 nilfs_sufile_get_segment_usage_block(struct inode *sufile, __u64 segnum, 106 int create, struct buffer_head **bhp) 107 { 108 return nilfs_mdt_get_block(sufile, 109 nilfs_sufile_get_blkoff(sufile, segnum), 110 create, NULL, bhp); 111 } 112 113 static int nilfs_sufile_delete_segment_usage_block(struct inode *sufile, 114 __u64 segnum) 115 { 116 return nilfs_mdt_delete_block(sufile, 117 nilfs_sufile_get_blkoff(sufile, segnum)); 118 } 119 120 static void nilfs_sufile_mod_counter(struct buffer_head *header_bh, 121 u64 ncleanadd, u64 ndirtyadd) 122 { 123 struct nilfs_sufile_header *header; 124 125 header = kmap_local_folio(header_bh->b_folio, 0); 126 le64_add_cpu(&header->sh_ncleansegs, ncleanadd); 127 le64_add_cpu(&header->sh_ndirtysegs, ndirtyadd); 128 kunmap_local(header); 129 130 mark_buffer_dirty(header_bh); 131 } 132 133 /** 134 * nilfs_sufile_get_ncleansegs - return the number of clean segments 135 * @sufile: inode of segment usage file 136 */ 137 unsigned long nilfs_sufile_get_ncleansegs(struct inode *sufile) 138 { 139 return NILFS_SUI(sufile)->ncleansegs; 140 } 141 142 /** 143 * nilfs_sufile_updatev - modify multiple segment usages at a time 144 * @sufile: inode of segment usage file 145 * @segnumv: array of segment numbers 146 * @nsegs: size of @segnumv array 147 * @create: creation flag 148 * @ndone: place to store number of modified segments on @segnumv 149 * @dofunc: primitive operation for the update 150 * 151 * Description: nilfs_sufile_updatev() repeatedly calls @dofunc 152 * against the given array of segments. The @dofunc is called with 153 * buffers of a header block and the sufile block in which the target 154 * segment usage entry is contained. If @ndone is given, the number 155 * of successfully modified segments from the head is stored in the 156 * place @ndone points to. 157 * 158 * Return Value: On success, zero is returned. On error, one of the 159 * following negative error codes is returned. 160 * 161 * %-EIO - I/O error. 162 * 163 * %-ENOMEM - Insufficient amount of memory available. 164 * 165 * %-ENOENT - Given segment usage is in hole block (may be returned if 166 * @create is zero) 167 * 168 * %-EINVAL - Invalid segment usage number 169 */ 170 int nilfs_sufile_updatev(struct inode *sufile, __u64 *segnumv, size_t nsegs, 171 int create, size_t *ndone, 172 void (*dofunc)(struct inode *, __u64, 173 struct buffer_head *, 174 struct buffer_head *)) 175 { 176 struct buffer_head *header_bh, *bh; 177 unsigned long blkoff, prev_blkoff; 178 __u64 *seg; 179 size_t nerr = 0, n = 0; 180 int ret = 0; 181 182 if (unlikely(nsegs == 0)) 183 goto out; 184 185 down_write(&NILFS_MDT(sufile)->mi_sem); 186 for (seg = segnumv; seg < segnumv + nsegs; seg++) { 187 if (unlikely(*seg >= nilfs_sufile_get_nsegments(sufile))) { 188 nilfs_warn(sufile->i_sb, 189 "%s: invalid segment number: %llu", 190 __func__, (unsigned long long)*seg); 191 nerr++; 192 } 193 } 194 if (nerr > 0) { 195 ret = -EINVAL; 196 goto out_sem; 197 } 198 199 ret = nilfs_sufile_get_header_block(sufile, &header_bh); 200 if (ret < 0) 201 goto out_sem; 202 203 seg = segnumv; 204 blkoff = nilfs_sufile_get_blkoff(sufile, *seg); 205 ret = nilfs_mdt_get_block(sufile, blkoff, create, NULL, &bh); 206 if (ret < 0) 207 goto out_header; 208 209 for (;;) { 210 dofunc(sufile, *seg, header_bh, bh); 211 212 if (++seg >= segnumv + nsegs) 213 break; 214 prev_blkoff = blkoff; 215 blkoff = nilfs_sufile_get_blkoff(sufile, *seg); 216 if (blkoff == prev_blkoff) 217 continue; 218 219 /* get different block */ 220 brelse(bh); 221 ret = nilfs_mdt_get_block(sufile, blkoff, create, NULL, &bh); 222 if (unlikely(ret < 0)) 223 goto out_header; 224 } 225 brelse(bh); 226 227 out_header: 228 n = seg - segnumv; 229 brelse(header_bh); 230 out_sem: 231 up_write(&NILFS_MDT(sufile)->mi_sem); 232 out: 233 if (ndone) 234 *ndone = n; 235 return ret; 236 } 237 238 int nilfs_sufile_update(struct inode *sufile, __u64 segnum, int create, 239 void (*dofunc)(struct inode *, __u64, 240 struct buffer_head *, 241 struct buffer_head *)) 242 { 243 struct buffer_head *header_bh, *bh; 244 int ret; 245 246 if (unlikely(segnum >= nilfs_sufile_get_nsegments(sufile))) { 247 nilfs_warn(sufile->i_sb, "%s: invalid segment number: %llu", 248 __func__, (unsigned long long)segnum); 249 return -EINVAL; 250 } 251 down_write(&NILFS_MDT(sufile)->mi_sem); 252 253 ret = nilfs_sufile_get_header_block(sufile, &header_bh); 254 if (ret < 0) 255 goto out_sem; 256 257 ret = nilfs_sufile_get_segment_usage_block(sufile, segnum, create, &bh); 258 if (!ret) { 259 dofunc(sufile, segnum, header_bh, bh); 260 brelse(bh); 261 } 262 brelse(header_bh); 263 264 out_sem: 265 up_write(&NILFS_MDT(sufile)->mi_sem); 266 return ret; 267 } 268 269 /** 270 * nilfs_sufile_set_alloc_range - limit range of segment to be allocated 271 * @sufile: inode of segment usage file 272 * @start: minimum segment number of allocatable region (inclusive) 273 * @end: maximum segment number of allocatable region (inclusive) 274 * 275 * Return Value: On success, 0 is returned. On error, one of the 276 * following negative error codes is returned. 277 * 278 * %-ERANGE - invalid segment region 279 */ 280 int nilfs_sufile_set_alloc_range(struct inode *sufile, __u64 start, __u64 end) 281 { 282 struct nilfs_sufile_info *sui = NILFS_SUI(sufile); 283 __u64 nsegs; 284 int ret = -ERANGE; 285 286 down_write(&NILFS_MDT(sufile)->mi_sem); 287 nsegs = nilfs_sufile_get_nsegments(sufile); 288 289 if (start <= end && end < nsegs) { 290 sui->allocmin = start; 291 sui->allocmax = end; 292 ret = 0; 293 } 294 up_write(&NILFS_MDT(sufile)->mi_sem); 295 return ret; 296 } 297 298 /** 299 * nilfs_sufile_alloc - allocate a segment 300 * @sufile: inode of segment usage file 301 * @segnump: pointer to segment number 302 * 303 * Description: nilfs_sufile_alloc() allocates a clean segment. 304 * 305 * Return Value: On success, 0 is returned and the segment number of the 306 * allocated segment is stored in the place pointed by @segnump. On error, one 307 * of the following negative error codes is returned. 308 * 309 * %-EIO - I/O error. 310 * 311 * %-ENOMEM - Insufficient amount of memory available. 312 * 313 * %-ENOSPC - No clean segment left. 314 */ 315 int nilfs_sufile_alloc(struct inode *sufile, __u64 *segnump) 316 { 317 struct buffer_head *header_bh, *su_bh; 318 struct nilfs_sufile_header *header; 319 struct nilfs_segment_usage *su; 320 struct nilfs_sufile_info *sui = NILFS_SUI(sufile); 321 size_t susz = NILFS_MDT(sufile)->mi_entry_size; 322 __u64 segnum, maxsegnum, last_alloc; 323 size_t offset; 324 void *kaddr; 325 unsigned long nsegments, nsus, cnt; 326 int ret, j; 327 328 down_write(&NILFS_MDT(sufile)->mi_sem); 329 330 ret = nilfs_sufile_get_header_block(sufile, &header_bh); 331 if (ret < 0) 332 goto out_sem; 333 header = kmap_local_folio(header_bh->b_folio, 0); 334 last_alloc = le64_to_cpu(header->sh_last_alloc); 335 kunmap_local(header); 336 337 nsegments = nilfs_sufile_get_nsegments(sufile); 338 maxsegnum = sui->allocmax; 339 segnum = last_alloc + 1; 340 if (segnum < sui->allocmin || segnum > sui->allocmax) 341 segnum = sui->allocmin; 342 343 for (cnt = 0; cnt < nsegments; cnt += nsus) { 344 if (segnum > maxsegnum) { 345 if (cnt < sui->allocmax - sui->allocmin + 1) { 346 /* 347 * wrap around in the limited region. 348 * if allocation started from 349 * sui->allocmin, this never happens. 350 */ 351 segnum = sui->allocmin; 352 maxsegnum = last_alloc; 353 } else if (segnum > sui->allocmin && 354 sui->allocmax + 1 < nsegments) { 355 segnum = sui->allocmax + 1; 356 maxsegnum = nsegments - 1; 357 } else if (sui->allocmin > 0) { 358 segnum = 0; 359 maxsegnum = sui->allocmin - 1; 360 } else { 361 break; /* never happens */ 362 } 363 } 364 trace_nilfs2_segment_usage_check(sufile, segnum, cnt); 365 ret = nilfs_sufile_get_segment_usage_block(sufile, segnum, 1, 366 &su_bh); 367 if (ret < 0) 368 goto out_header; 369 370 offset = nilfs_sufile_segment_usage_offset(sufile, segnum, 371 su_bh); 372 su = kaddr = kmap_local_folio(su_bh->b_folio, offset); 373 374 nsus = nilfs_sufile_segment_usages_in_block( 375 sufile, segnum, maxsegnum); 376 for (j = 0; j < nsus; j++, su = (void *)su + susz, segnum++) { 377 if (!nilfs_segment_usage_clean(su)) 378 continue; 379 /* found a clean segment */ 380 nilfs_segment_usage_set_dirty(su); 381 kunmap_local(kaddr); 382 383 header = kmap_local_folio(header_bh->b_folio, 0); 384 le64_add_cpu(&header->sh_ncleansegs, -1); 385 le64_add_cpu(&header->sh_ndirtysegs, 1); 386 header->sh_last_alloc = cpu_to_le64(segnum); 387 kunmap_local(header); 388 389 sui->ncleansegs--; 390 mark_buffer_dirty(header_bh); 391 mark_buffer_dirty(su_bh); 392 nilfs_mdt_mark_dirty(sufile); 393 brelse(su_bh); 394 *segnump = segnum; 395 396 trace_nilfs2_segment_usage_allocated(sufile, segnum); 397 398 goto out_header; 399 } 400 401 kunmap_local(kaddr); 402 brelse(su_bh); 403 } 404 405 /* no segments left */ 406 ret = -ENOSPC; 407 408 out_header: 409 brelse(header_bh); 410 411 out_sem: 412 up_write(&NILFS_MDT(sufile)->mi_sem); 413 return ret; 414 } 415 416 void nilfs_sufile_do_cancel_free(struct inode *sufile, __u64 segnum, 417 struct buffer_head *header_bh, 418 struct buffer_head *su_bh) 419 { 420 struct nilfs_segment_usage *su; 421 size_t offset; 422 423 offset = nilfs_sufile_segment_usage_offset(sufile, segnum, su_bh); 424 su = kmap_local_folio(su_bh->b_folio, offset); 425 if (unlikely(!nilfs_segment_usage_clean(su))) { 426 nilfs_warn(sufile->i_sb, "%s: segment %llu must be clean", 427 __func__, (unsigned long long)segnum); 428 kunmap_local(su); 429 return; 430 } 431 nilfs_segment_usage_set_dirty(su); 432 kunmap_local(su); 433 434 nilfs_sufile_mod_counter(header_bh, -1, 1); 435 NILFS_SUI(sufile)->ncleansegs--; 436 437 mark_buffer_dirty(su_bh); 438 nilfs_mdt_mark_dirty(sufile); 439 } 440 441 void nilfs_sufile_do_scrap(struct inode *sufile, __u64 segnum, 442 struct buffer_head *header_bh, 443 struct buffer_head *su_bh) 444 { 445 struct nilfs_segment_usage *su; 446 size_t offset; 447 int clean, dirty; 448 449 offset = nilfs_sufile_segment_usage_offset(sufile, segnum, su_bh); 450 su = kmap_local_folio(su_bh->b_folio, offset); 451 if (su->su_flags == cpu_to_le32(BIT(NILFS_SEGMENT_USAGE_DIRTY)) && 452 su->su_nblocks == cpu_to_le32(0)) { 453 kunmap_local(su); 454 return; 455 } 456 clean = nilfs_segment_usage_clean(su); 457 dirty = nilfs_segment_usage_dirty(su); 458 459 /* make the segment garbage */ 460 su->su_lastmod = cpu_to_le64(0); 461 su->su_nblocks = cpu_to_le32(0); 462 su->su_flags = cpu_to_le32(BIT(NILFS_SEGMENT_USAGE_DIRTY)); 463 kunmap_local(su); 464 465 nilfs_sufile_mod_counter(header_bh, clean ? (u64)-1 : 0, dirty ? 0 : 1); 466 NILFS_SUI(sufile)->ncleansegs -= clean; 467 468 mark_buffer_dirty(su_bh); 469 nilfs_mdt_mark_dirty(sufile); 470 } 471 472 void nilfs_sufile_do_free(struct inode *sufile, __u64 segnum, 473 struct buffer_head *header_bh, 474 struct buffer_head *su_bh) 475 { 476 struct nilfs_segment_usage *su; 477 size_t offset; 478 int sudirty; 479 480 offset = nilfs_sufile_segment_usage_offset(sufile, segnum, su_bh); 481 su = kmap_local_folio(su_bh->b_folio, offset); 482 if (nilfs_segment_usage_clean(su)) { 483 nilfs_warn(sufile->i_sb, "%s: segment %llu is already clean", 484 __func__, (unsigned long long)segnum); 485 kunmap_local(su); 486 return; 487 } 488 if (unlikely(nilfs_segment_usage_error(su))) 489 nilfs_warn(sufile->i_sb, "free segment %llu marked in error", 490 (unsigned long long)segnum); 491 492 sudirty = nilfs_segment_usage_dirty(su); 493 if (unlikely(!sudirty)) 494 nilfs_warn(sufile->i_sb, "free unallocated segment %llu", 495 (unsigned long long)segnum); 496 497 nilfs_segment_usage_set_clean(su); 498 kunmap_local(su); 499 mark_buffer_dirty(su_bh); 500 501 nilfs_sufile_mod_counter(header_bh, 1, sudirty ? (u64)-1 : 0); 502 NILFS_SUI(sufile)->ncleansegs++; 503 504 nilfs_mdt_mark_dirty(sufile); 505 506 trace_nilfs2_segment_usage_freed(sufile, segnum); 507 } 508 509 /** 510 * nilfs_sufile_mark_dirty - mark the buffer having a segment usage dirty 511 * @sufile: inode of segment usage file 512 * @segnum: segment number 513 */ 514 int nilfs_sufile_mark_dirty(struct inode *sufile, __u64 segnum) 515 { 516 struct buffer_head *bh; 517 size_t offset; 518 struct nilfs_segment_usage *su; 519 int ret; 520 521 down_write(&NILFS_MDT(sufile)->mi_sem); 522 ret = nilfs_sufile_get_segment_usage_block(sufile, segnum, 0, &bh); 523 if (unlikely(ret)) { 524 if (ret == -ENOENT) { 525 nilfs_error(sufile->i_sb, 526 "segment usage for segment %llu is unreadable due to a hole block", 527 (unsigned long long)segnum); 528 ret = -EIO; 529 } 530 goto out_sem; 531 } 532 533 offset = nilfs_sufile_segment_usage_offset(sufile, segnum, bh); 534 su = kmap_local_folio(bh->b_folio, offset); 535 if (unlikely(nilfs_segment_usage_error(su))) { 536 struct the_nilfs *nilfs = sufile->i_sb->s_fs_info; 537 538 kunmap_local(su); 539 brelse(bh); 540 if (nilfs_segment_is_active(nilfs, segnum)) { 541 nilfs_error(sufile->i_sb, 542 "active segment %llu is erroneous", 543 (unsigned long long)segnum); 544 } else { 545 /* 546 * Segments marked erroneous are never allocated by 547 * nilfs_sufile_alloc(); only active segments, ie, 548 * the segments indexed by ns_segnum or ns_nextnum, 549 * can be erroneous here. 550 */ 551 WARN_ON_ONCE(1); 552 } 553 ret = -EIO; 554 } else { 555 nilfs_segment_usage_set_dirty(su); 556 kunmap_local(su); 557 mark_buffer_dirty(bh); 558 nilfs_mdt_mark_dirty(sufile); 559 brelse(bh); 560 } 561 out_sem: 562 up_write(&NILFS_MDT(sufile)->mi_sem); 563 return ret; 564 } 565 566 /** 567 * nilfs_sufile_set_segment_usage - set usage of a segment 568 * @sufile: inode of segment usage file 569 * @segnum: segment number 570 * @nblocks: number of live blocks in the segment 571 * @modtime: modification time (option) 572 */ 573 int nilfs_sufile_set_segment_usage(struct inode *sufile, __u64 segnum, 574 unsigned long nblocks, time64_t modtime) 575 { 576 struct buffer_head *bh; 577 struct nilfs_segment_usage *su; 578 size_t offset; 579 int ret; 580 581 down_write(&NILFS_MDT(sufile)->mi_sem); 582 ret = nilfs_sufile_get_segment_usage_block(sufile, segnum, 0, &bh); 583 if (ret < 0) 584 goto out_sem; 585 586 offset = nilfs_sufile_segment_usage_offset(sufile, segnum, bh); 587 su = kmap_local_folio(bh->b_folio, offset); 588 if (modtime) { 589 /* 590 * Check segusage error and set su_lastmod only when updating 591 * this entry with a valid timestamp, not for cancellation. 592 */ 593 WARN_ON_ONCE(nilfs_segment_usage_error(su)); 594 su->su_lastmod = cpu_to_le64(modtime); 595 } 596 su->su_nblocks = cpu_to_le32(nblocks); 597 kunmap_local(su); 598 599 mark_buffer_dirty(bh); 600 nilfs_mdt_mark_dirty(sufile); 601 brelse(bh); 602 603 out_sem: 604 up_write(&NILFS_MDT(sufile)->mi_sem); 605 return ret; 606 } 607 608 /** 609 * nilfs_sufile_get_stat - get segment usage statistics 610 * @sufile: inode of segment usage file 611 * @sustat: pointer to a structure of segment usage statistics 612 * 613 * Description: nilfs_sufile_get_stat() returns information about segment 614 * usage. 615 * 616 * Return Value: On success, 0 is returned, and segment usage information is 617 * stored in the place pointed by @sustat. On error, one of the following 618 * negative error codes is returned. 619 * 620 * %-EIO - I/O error. 621 * 622 * %-ENOMEM - Insufficient amount of memory available. 623 */ 624 int nilfs_sufile_get_stat(struct inode *sufile, struct nilfs_sustat *sustat) 625 { 626 struct buffer_head *header_bh; 627 struct nilfs_sufile_header *header; 628 struct the_nilfs *nilfs = sufile->i_sb->s_fs_info; 629 int ret; 630 631 down_read(&NILFS_MDT(sufile)->mi_sem); 632 633 ret = nilfs_sufile_get_header_block(sufile, &header_bh); 634 if (ret < 0) 635 goto out_sem; 636 637 header = kmap_local_folio(header_bh->b_folio, 0); 638 sustat->ss_nsegs = nilfs_sufile_get_nsegments(sufile); 639 sustat->ss_ncleansegs = le64_to_cpu(header->sh_ncleansegs); 640 sustat->ss_ndirtysegs = le64_to_cpu(header->sh_ndirtysegs); 641 sustat->ss_ctime = nilfs->ns_ctime; 642 sustat->ss_nongc_ctime = nilfs->ns_nongc_ctime; 643 spin_lock(&nilfs->ns_last_segment_lock); 644 sustat->ss_prot_seq = nilfs->ns_prot_seq; 645 spin_unlock(&nilfs->ns_last_segment_lock); 646 kunmap_local(header); 647 brelse(header_bh); 648 649 out_sem: 650 up_read(&NILFS_MDT(sufile)->mi_sem); 651 return ret; 652 } 653 654 void nilfs_sufile_do_set_error(struct inode *sufile, __u64 segnum, 655 struct buffer_head *header_bh, 656 struct buffer_head *su_bh) 657 { 658 struct nilfs_segment_usage *su; 659 size_t offset; 660 int suclean; 661 662 offset = nilfs_sufile_segment_usage_offset(sufile, segnum, su_bh); 663 su = kmap_local_folio(su_bh->b_folio, offset); 664 if (nilfs_segment_usage_error(su)) { 665 kunmap_local(su); 666 return; 667 } 668 suclean = nilfs_segment_usage_clean(su); 669 nilfs_segment_usage_set_error(su); 670 kunmap_local(su); 671 672 if (suclean) { 673 nilfs_sufile_mod_counter(header_bh, -1, 0); 674 NILFS_SUI(sufile)->ncleansegs--; 675 } 676 mark_buffer_dirty(su_bh); 677 nilfs_mdt_mark_dirty(sufile); 678 } 679 680 /** 681 * nilfs_sufile_truncate_range - truncate range of segment array 682 * @sufile: inode of segment usage file 683 * @start: start segment number (inclusive) 684 * @end: end segment number (inclusive) 685 * 686 * Return Value: On success, 0 is returned. On error, one of the 687 * following negative error codes is returned. 688 * 689 * %-EIO - I/O error. 690 * 691 * %-ENOMEM - Insufficient amount of memory available. 692 * 693 * %-EINVAL - Invalid number of segments specified 694 * 695 * %-EBUSY - Dirty or active segments are present in the range 696 */ 697 static int nilfs_sufile_truncate_range(struct inode *sufile, 698 __u64 start, __u64 end) 699 { 700 struct the_nilfs *nilfs = sufile->i_sb->s_fs_info; 701 struct buffer_head *header_bh; 702 struct buffer_head *su_bh; 703 struct nilfs_segment_usage *su, *su2; 704 size_t susz = NILFS_MDT(sufile)->mi_entry_size; 705 unsigned long segusages_per_block; 706 unsigned long nsegs, ncleaned; 707 __u64 segnum; 708 size_t offset; 709 ssize_t n, nc; 710 int ret; 711 int j; 712 713 nsegs = nilfs_sufile_get_nsegments(sufile); 714 715 ret = -EINVAL; 716 if (start > end || start >= nsegs) 717 goto out; 718 719 ret = nilfs_sufile_get_header_block(sufile, &header_bh); 720 if (ret < 0) 721 goto out; 722 723 segusages_per_block = nilfs_sufile_segment_usages_per_block(sufile); 724 ncleaned = 0; 725 726 for (segnum = start; segnum <= end; segnum += n) { 727 n = min_t(unsigned long, 728 segusages_per_block - 729 nilfs_sufile_get_offset(sufile, segnum), 730 end - segnum + 1); 731 ret = nilfs_sufile_get_segment_usage_block(sufile, segnum, 0, 732 &su_bh); 733 if (ret < 0) { 734 if (ret != -ENOENT) 735 goto out_header; 736 /* hole */ 737 continue; 738 } 739 offset = nilfs_sufile_segment_usage_offset(sufile, segnum, 740 su_bh); 741 su = kmap_local_folio(su_bh->b_folio, offset); 742 su2 = su; 743 for (j = 0; j < n; j++, su = (void *)su + susz) { 744 if ((le32_to_cpu(su->su_flags) & 745 ~BIT(NILFS_SEGMENT_USAGE_ERROR)) || 746 nilfs_segment_is_active(nilfs, segnum + j)) { 747 ret = -EBUSY; 748 kunmap_local(su2); 749 brelse(su_bh); 750 goto out_header; 751 } 752 } 753 nc = 0; 754 for (su = su2, j = 0; j < n; j++, su = (void *)su + susz) { 755 if (nilfs_segment_usage_error(su)) { 756 nilfs_segment_usage_set_clean(su); 757 nc++; 758 } 759 } 760 kunmap_local(su2); 761 if (nc > 0) { 762 mark_buffer_dirty(su_bh); 763 ncleaned += nc; 764 } 765 brelse(su_bh); 766 767 if (n == segusages_per_block) { 768 /* make hole */ 769 nilfs_sufile_delete_segment_usage_block(sufile, segnum); 770 } 771 } 772 ret = 0; 773 774 out_header: 775 if (ncleaned > 0) { 776 NILFS_SUI(sufile)->ncleansegs += ncleaned; 777 nilfs_sufile_mod_counter(header_bh, ncleaned, 0); 778 nilfs_mdt_mark_dirty(sufile); 779 } 780 brelse(header_bh); 781 out: 782 return ret; 783 } 784 785 /** 786 * nilfs_sufile_resize - resize segment array 787 * @sufile: inode of segment usage file 788 * @newnsegs: new number of segments 789 * 790 * Return Value: On success, 0 is returned. On error, one of the 791 * following negative error codes is returned. 792 * 793 * %-EIO - I/O error. 794 * 795 * %-ENOMEM - Insufficient amount of memory available. 796 * 797 * %-ENOSPC - Enough free space is not left for shrinking 798 * 799 * %-EBUSY - Dirty or active segments exist in the region to be truncated 800 */ 801 int nilfs_sufile_resize(struct inode *sufile, __u64 newnsegs) 802 { 803 struct the_nilfs *nilfs = sufile->i_sb->s_fs_info; 804 struct buffer_head *header_bh; 805 struct nilfs_sufile_header *header; 806 struct nilfs_sufile_info *sui = NILFS_SUI(sufile); 807 unsigned long nsegs, nrsvsegs; 808 int ret = 0; 809 810 down_write(&NILFS_MDT(sufile)->mi_sem); 811 812 nsegs = nilfs_sufile_get_nsegments(sufile); 813 if (nsegs == newnsegs) 814 goto out; 815 816 ret = -ENOSPC; 817 nrsvsegs = nilfs_nrsvsegs(nilfs, newnsegs); 818 if (newnsegs < nsegs && nsegs - newnsegs + nrsvsegs > sui->ncleansegs) 819 goto out; 820 821 ret = nilfs_sufile_get_header_block(sufile, &header_bh); 822 if (ret < 0) 823 goto out; 824 825 if (newnsegs > nsegs) { 826 sui->ncleansegs += newnsegs - nsegs; 827 } else /* newnsegs < nsegs */ { 828 ret = nilfs_sufile_truncate_range(sufile, newnsegs, nsegs - 1); 829 if (ret < 0) 830 goto out_header; 831 832 sui->ncleansegs -= nsegs - newnsegs; 833 834 /* 835 * If the sufile is successfully truncated, immediately adjust 836 * the segment allocation space while locking the semaphore 837 * "mi_sem" so that nilfs_sufile_alloc() never allocates 838 * segments in the truncated space. 839 */ 840 sui->allocmax = newnsegs - 1; 841 sui->allocmin = 0; 842 } 843 844 header = kmap_local_folio(header_bh->b_folio, 0); 845 header->sh_ncleansegs = cpu_to_le64(sui->ncleansegs); 846 kunmap_local(header); 847 848 mark_buffer_dirty(header_bh); 849 nilfs_mdt_mark_dirty(sufile); 850 nilfs_set_nsegments(nilfs, newnsegs); 851 852 out_header: 853 brelse(header_bh); 854 out: 855 up_write(&NILFS_MDT(sufile)->mi_sem); 856 return ret; 857 } 858 859 /** 860 * nilfs_sufile_get_suinfo - get segment usage information 861 * @sufile: inode of segment usage file 862 * @segnum: segment number to start looking 863 * @buf: array of suinfo 864 * @sisz: byte size of suinfo 865 * @nsi: size of suinfo array 866 * 867 * Return: Count of segment usage info items stored in the output buffer on 868 * success, or the following negative error code on failure. 869 * * %-EIO - I/O error (including metadata corruption). 870 * * %-ENOMEM - Insufficient memory available. 871 */ 872 ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum, void *buf, 873 unsigned int sisz, size_t nsi) 874 { 875 struct buffer_head *su_bh; 876 struct nilfs_segment_usage *su; 877 struct nilfs_suinfo *si = buf; 878 size_t susz = NILFS_MDT(sufile)->mi_entry_size; 879 struct the_nilfs *nilfs = sufile->i_sb->s_fs_info; 880 size_t offset; 881 void *kaddr; 882 unsigned long nsegs, segusages_per_block; 883 ssize_t n; 884 int ret, i, j; 885 886 down_read(&NILFS_MDT(sufile)->mi_sem); 887 888 segusages_per_block = nilfs_sufile_segment_usages_per_block(sufile); 889 nsegs = min_t(unsigned long, 890 nilfs_sufile_get_nsegments(sufile) - segnum, 891 nsi); 892 for (i = 0; i < nsegs; i += n, segnum += n) { 893 n = min_t(unsigned long, 894 segusages_per_block - 895 nilfs_sufile_get_offset(sufile, segnum), 896 nsegs - i); 897 ret = nilfs_sufile_get_segment_usage_block(sufile, segnum, 0, 898 &su_bh); 899 if (ret < 0) { 900 if (ret != -ENOENT) 901 goto out; 902 /* hole */ 903 memset(si, 0, sisz * n); 904 si = (void *)si + sisz * n; 905 continue; 906 } 907 908 offset = nilfs_sufile_segment_usage_offset(sufile, segnum, 909 su_bh); 910 su = kaddr = kmap_local_folio(su_bh->b_folio, offset); 911 for (j = 0; j < n; 912 j++, su = (void *)su + susz, si = (void *)si + sisz) { 913 si->sui_lastmod = le64_to_cpu(su->su_lastmod); 914 si->sui_nblocks = le32_to_cpu(su->su_nblocks); 915 si->sui_flags = le32_to_cpu(su->su_flags) & 916 ~BIT(NILFS_SEGMENT_USAGE_ACTIVE); 917 if (nilfs_segment_is_active(nilfs, segnum + j)) 918 si->sui_flags |= 919 BIT(NILFS_SEGMENT_USAGE_ACTIVE); 920 } 921 kunmap_local(kaddr); 922 brelse(su_bh); 923 } 924 ret = nsegs; 925 926 out: 927 up_read(&NILFS_MDT(sufile)->mi_sem); 928 return ret; 929 } 930 931 /** 932 * nilfs_sufile_set_suinfo - sets segment usage info 933 * @sufile: inode of segment usage file 934 * @buf: array of suinfo_update 935 * @supsz: byte size of suinfo_update 936 * @nsup: size of suinfo_update array 937 * 938 * Description: Takes an array of nilfs_suinfo_update structs and updates 939 * segment usage accordingly. Only the fields indicated by the sup_flags 940 * are updated. 941 * 942 * Return Value: On success, 0 is returned. On error, one of the 943 * following negative error codes is returned. 944 * 945 * %-EIO - I/O error. 946 * 947 * %-ENOMEM - Insufficient amount of memory available. 948 * 949 * %-EINVAL - Invalid values in input (segment number, flags or nblocks) 950 */ 951 ssize_t nilfs_sufile_set_suinfo(struct inode *sufile, void *buf, 952 unsigned int supsz, size_t nsup) 953 { 954 struct the_nilfs *nilfs = sufile->i_sb->s_fs_info; 955 struct buffer_head *header_bh, *bh; 956 struct nilfs_suinfo_update *sup, *supend = buf + supsz * nsup; 957 struct nilfs_segment_usage *su; 958 size_t offset; 959 unsigned long blkoff, prev_blkoff; 960 int cleansi, cleansu, dirtysi, dirtysu; 961 long ncleaned = 0, ndirtied = 0; 962 int ret = 0; 963 964 if (unlikely(nsup == 0)) 965 return ret; 966 967 for (sup = buf; sup < supend; sup = (void *)sup + supsz) { 968 if (sup->sup_segnum >= nilfs->ns_nsegments 969 || (sup->sup_flags & 970 (~0UL << __NR_NILFS_SUINFO_UPDATE_FIELDS)) 971 || (nilfs_suinfo_update_nblocks(sup) && 972 sup->sup_sui.sui_nblocks > 973 nilfs->ns_blocks_per_segment)) 974 return -EINVAL; 975 } 976 977 down_write(&NILFS_MDT(sufile)->mi_sem); 978 979 ret = nilfs_sufile_get_header_block(sufile, &header_bh); 980 if (ret < 0) 981 goto out_sem; 982 983 sup = buf; 984 blkoff = nilfs_sufile_get_blkoff(sufile, sup->sup_segnum); 985 ret = nilfs_mdt_get_block(sufile, blkoff, 1, NULL, &bh); 986 if (ret < 0) 987 goto out_header; 988 989 for (;;) { 990 offset = nilfs_sufile_segment_usage_offset( 991 sufile, sup->sup_segnum, bh); 992 su = kmap_local_folio(bh->b_folio, offset); 993 994 if (nilfs_suinfo_update_lastmod(sup)) 995 su->su_lastmod = cpu_to_le64(sup->sup_sui.sui_lastmod); 996 997 if (nilfs_suinfo_update_nblocks(sup)) 998 su->su_nblocks = cpu_to_le32(sup->sup_sui.sui_nblocks); 999 1000 if (nilfs_suinfo_update_flags(sup)) { 1001 /* 1002 * Active flag is a virtual flag projected by running 1003 * nilfs kernel code - drop it not to write it to 1004 * disk. 1005 */ 1006 sup->sup_sui.sui_flags &= 1007 ~BIT(NILFS_SEGMENT_USAGE_ACTIVE); 1008 1009 cleansi = nilfs_suinfo_clean(&sup->sup_sui); 1010 cleansu = nilfs_segment_usage_clean(su); 1011 dirtysi = nilfs_suinfo_dirty(&sup->sup_sui); 1012 dirtysu = nilfs_segment_usage_dirty(su); 1013 1014 if (cleansi && !cleansu) 1015 ++ncleaned; 1016 else if (!cleansi && cleansu) 1017 --ncleaned; 1018 1019 if (dirtysi && !dirtysu) 1020 ++ndirtied; 1021 else if (!dirtysi && dirtysu) 1022 --ndirtied; 1023 1024 su->su_flags = cpu_to_le32(sup->sup_sui.sui_flags); 1025 } 1026 1027 kunmap_local(su); 1028 1029 sup = (void *)sup + supsz; 1030 if (sup >= supend) 1031 break; 1032 1033 prev_blkoff = blkoff; 1034 blkoff = nilfs_sufile_get_blkoff(sufile, sup->sup_segnum); 1035 if (blkoff == prev_blkoff) 1036 continue; 1037 1038 /* get different block */ 1039 mark_buffer_dirty(bh); 1040 put_bh(bh); 1041 ret = nilfs_mdt_get_block(sufile, blkoff, 1, NULL, &bh); 1042 if (unlikely(ret < 0)) 1043 goto out_mark; 1044 } 1045 mark_buffer_dirty(bh); 1046 put_bh(bh); 1047 1048 out_mark: 1049 if (ncleaned || ndirtied) { 1050 nilfs_sufile_mod_counter(header_bh, (u64)ncleaned, 1051 (u64)ndirtied); 1052 NILFS_SUI(sufile)->ncleansegs += ncleaned; 1053 } 1054 nilfs_mdt_mark_dirty(sufile); 1055 out_header: 1056 put_bh(header_bh); 1057 out_sem: 1058 up_write(&NILFS_MDT(sufile)->mi_sem); 1059 return ret; 1060 } 1061 1062 /** 1063 * nilfs_sufile_trim_fs() - trim ioctl handle function 1064 * @sufile: inode of segment usage file 1065 * @range: fstrim_range structure 1066 * 1067 * start: First Byte to trim 1068 * len: number of Bytes to trim from start 1069 * minlen: minimum extent length in Bytes 1070 * 1071 * Decription: nilfs_sufile_trim_fs goes through all segments containing bytes 1072 * from start to start+len. start is rounded up to the next block boundary 1073 * and start+len is rounded down. For each clean segment blkdev_issue_discard 1074 * function is invoked. 1075 * 1076 * Return Value: On success, 0 is returned or negative error code, otherwise. 1077 */ 1078 int nilfs_sufile_trim_fs(struct inode *sufile, struct fstrim_range *range) 1079 { 1080 struct the_nilfs *nilfs = sufile->i_sb->s_fs_info; 1081 struct buffer_head *su_bh; 1082 struct nilfs_segment_usage *su; 1083 size_t offset; 1084 void *kaddr; 1085 size_t n, i, susz = NILFS_MDT(sufile)->mi_entry_size; 1086 sector_t seg_start, seg_end, start_block, end_block; 1087 sector_t start = 0, nblocks = 0; 1088 u64 segnum, segnum_end, minlen, len, max_blocks, ndiscarded = 0; 1089 int ret = 0; 1090 unsigned int sects_per_block; 1091 1092 sects_per_block = (1 << nilfs->ns_blocksize_bits) / 1093 bdev_logical_block_size(nilfs->ns_bdev); 1094 len = range->len >> nilfs->ns_blocksize_bits; 1095 minlen = range->minlen >> nilfs->ns_blocksize_bits; 1096 max_blocks = ((u64)nilfs->ns_nsegments * nilfs->ns_blocks_per_segment); 1097 1098 if (!len || range->start >= max_blocks << nilfs->ns_blocksize_bits) 1099 return -EINVAL; 1100 1101 start_block = (range->start + nilfs->ns_blocksize - 1) >> 1102 nilfs->ns_blocksize_bits; 1103 1104 /* 1105 * range->len can be very large (actually, it is set to 1106 * ULLONG_MAX by default) - truncate upper end of the range 1107 * carefully so as not to overflow. 1108 */ 1109 if (max_blocks - start_block < len) 1110 end_block = max_blocks - 1; 1111 else 1112 end_block = start_block + len - 1; 1113 1114 segnum = nilfs_get_segnum_of_block(nilfs, start_block); 1115 segnum_end = nilfs_get_segnum_of_block(nilfs, end_block); 1116 1117 down_read(&NILFS_MDT(sufile)->mi_sem); 1118 1119 while (segnum <= segnum_end) { 1120 n = nilfs_sufile_segment_usages_in_block(sufile, segnum, 1121 segnum_end); 1122 1123 ret = nilfs_sufile_get_segment_usage_block(sufile, segnum, 0, 1124 &su_bh); 1125 if (ret < 0) { 1126 if (ret != -ENOENT) 1127 goto out_sem; 1128 /* hole */ 1129 segnum += n; 1130 continue; 1131 } 1132 1133 offset = nilfs_sufile_segment_usage_offset(sufile, segnum, 1134 su_bh); 1135 su = kaddr = kmap_local_folio(su_bh->b_folio, offset); 1136 for (i = 0; i < n; ++i, ++segnum, su = (void *)su + susz) { 1137 if (!nilfs_segment_usage_clean(su)) 1138 continue; 1139 1140 nilfs_get_segment_range(nilfs, segnum, &seg_start, 1141 &seg_end); 1142 1143 if (!nblocks) { 1144 /* start new extent */ 1145 start = seg_start; 1146 nblocks = seg_end - seg_start + 1; 1147 continue; 1148 } 1149 1150 if (start + nblocks == seg_start) { 1151 /* add to previous extent */ 1152 nblocks += seg_end - seg_start + 1; 1153 continue; 1154 } 1155 1156 /* discard previous extent */ 1157 if (start < start_block) { 1158 nblocks -= start_block - start; 1159 start = start_block; 1160 } 1161 1162 if (nblocks >= minlen) { 1163 kunmap_local(kaddr); 1164 1165 ret = blkdev_issue_discard(nilfs->ns_bdev, 1166 start * sects_per_block, 1167 nblocks * sects_per_block, 1168 GFP_NOFS); 1169 if (ret < 0) { 1170 put_bh(su_bh); 1171 goto out_sem; 1172 } 1173 1174 ndiscarded += nblocks; 1175 offset = nilfs_sufile_segment_usage_offset( 1176 sufile, segnum, su_bh); 1177 su = kaddr = kmap_local_folio(su_bh->b_folio, 1178 offset); 1179 } 1180 1181 /* start new extent */ 1182 start = seg_start; 1183 nblocks = seg_end - seg_start + 1; 1184 } 1185 kunmap_local(kaddr); 1186 put_bh(su_bh); 1187 } 1188 1189 1190 if (nblocks) { 1191 /* discard last extent */ 1192 if (start < start_block) { 1193 nblocks -= start_block - start; 1194 start = start_block; 1195 } 1196 if (start + nblocks > end_block + 1) 1197 nblocks = end_block - start + 1; 1198 1199 if (nblocks >= minlen) { 1200 ret = blkdev_issue_discard(nilfs->ns_bdev, 1201 start * sects_per_block, 1202 nblocks * sects_per_block, 1203 GFP_NOFS); 1204 if (!ret) 1205 ndiscarded += nblocks; 1206 } 1207 } 1208 1209 out_sem: 1210 up_read(&NILFS_MDT(sufile)->mi_sem); 1211 1212 range->len = ndiscarded << nilfs->ns_blocksize_bits; 1213 return ret; 1214 } 1215 1216 /** 1217 * nilfs_sufile_read - read or get sufile inode 1218 * @sb: super block instance 1219 * @susize: size of a segment usage entry 1220 * @raw_inode: on-disk sufile inode 1221 * @inodep: buffer to store the inode 1222 */ 1223 int nilfs_sufile_read(struct super_block *sb, size_t susize, 1224 struct nilfs_inode *raw_inode, struct inode **inodep) 1225 { 1226 struct inode *sufile; 1227 struct nilfs_sufile_info *sui; 1228 struct buffer_head *header_bh; 1229 struct nilfs_sufile_header *header; 1230 int err; 1231 1232 if (susize > sb->s_blocksize) { 1233 nilfs_err(sb, "too large segment usage size: %zu bytes", 1234 susize); 1235 return -EINVAL; 1236 } else if (susize < NILFS_MIN_SEGMENT_USAGE_SIZE) { 1237 nilfs_err(sb, "too small segment usage size: %zu bytes", 1238 susize); 1239 return -EINVAL; 1240 } 1241 1242 sufile = nilfs_iget_locked(sb, NULL, NILFS_SUFILE_INO); 1243 if (unlikely(!sufile)) 1244 return -ENOMEM; 1245 if (!(sufile->i_state & I_NEW)) 1246 goto out; 1247 1248 err = nilfs_mdt_init(sufile, NILFS_MDT_GFP, sizeof(*sui)); 1249 if (err) 1250 goto failed; 1251 1252 nilfs_mdt_set_entry_size(sufile, susize, 1253 sizeof(struct nilfs_sufile_header)); 1254 1255 err = nilfs_read_inode_common(sufile, raw_inode); 1256 if (err) 1257 goto failed; 1258 1259 err = nilfs_mdt_get_block(sufile, 0, 0, NULL, &header_bh); 1260 if (unlikely(err)) { 1261 if (err == -ENOENT) { 1262 nilfs_err(sb, 1263 "missing header block in segment usage metadata"); 1264 err = -EINVAL; 1265 } 1266 goto failed; 1267 } 1268 1269 sui = NILFS_SUI(sufile); 1270 header = kmap_local_folio(header_bh->b_folio, 0); 1271 sui->ncleansegs = le64_to_cpu(header->sh_ncleansegs); 1272 kunmap_local(header); 1273 brelse(header_bh); 1274 1275 sui->allocmax = nilfs_sufile_get_nsegments(sufile) - 1; 1276 sui->allocmin = 0; 1277 1278 unlock_new_inode(sufile); 1279 out: 1280 *inodep = sufile; 1281 return 0; 1282 failed: 1283 iget_failed(sufile); 1284 return err; 1285 } 1286