diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-15 12:13:49 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-15 12:13:49 -0400 |
commit | 9c7cb99a8202452d3e0440a5505c5c6d262771d9 (patch) | |
tree | 56d2fe83150f7bea3446b28bfa3094066c5f26b5 /fs/nilfs2/cpfile.c | |
parent | 0a8eba9b7f7aa3ad0305627c99ad4d6deedd871d (diff) | |
parent | c3a7abf06ce719a51139e62a034590be99abbc2c (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ryusuke/nilfs2
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ryusuke/nilfs2: (22 commits)
nilfs2: support contiguous lookup of blocks
nilfs2: add sync_page method to page caches of meta data
nilfs2: use device's backing_dev_info for btree node caches
nilfs2: return EBUSY against delete request on snapshot
nilfs2: modify list of unsupported features in caveats
nilfs2: enable sync_page method
nilfs2: set bio unplug flag for the last bio in segment
nilfs2: allow future expansion of metadata read out via get info ioctl
NILFS2: Pagecache usage optimization on NILFS2
nilfs2: remove nilfs_btree_operations from btree mapping
nilfs2: remove nilfs_direct_operations from direct mapping
nilfs2: remove bmap pointer operations
nilfs2: remove useless b_low and b_high fields from nilfs_bmap struct
nilfs2: remove pointless NULL check of bpop_commit_alloc_ptr function
nilfs2: move get block functions in bmap.c into btree codes
nilfs2: remove nilfs_bmap_delete_block
nilfs2: remove nilfs_bmap_put_block
nilfs2: remove header file for segment list operations
nilfs2: eliminate removal list of segments
nilfs2: add sufile function that can modify multiple segment usages
...
Diffstat (limited to 'fs/nilfs2/cpfile.c')
-rw-r--r-- | fs/nilfs2/cpfile.c | 47 |
1 files changed, 23 insertions, 24 deletions
diff --git a/fs/nilfs2/cpfile.c b/fs/nilfs2/cpfile.c index cadd36b14d07..7d49813f66d6 100644 --- a/fs/nilfs2/cpfile.c +++ b/fs/nilfs2/cpfile.c | |||
@@ -295,10 +295,6 @@ int nilfs_cpfile_delete_checkpoints(struct inode *cpfile, | |||
295 | return -EINVAL; | 295 | return -EINVAL; |
296 | } | 296 | } |
297 | 297 | ||
298 | /* cannot delete the latest checkpoint */ | ||
299 | if (start == nilfs_mdt_cno(cpfile) - 1) | ||
300 | return -EPERM; | ||
301 | |||
302 | down_write(&NILFS_MDT(cpfile)->mi_sem); | 298 | down_write(&NILFS_MDT(cpfile)->mi_sem); |
303 | 299 | ||
304 | ret = nilfs_cpfile_get_header_block(cpfile, &header_bh); | 300 | ret = nilfs_cpfile_get_header_block(cpfile, &header_bh); |
@@ -384,9 +380,10 @@ static void nilfs_cpfile_checkpoint_to_cpinfo(struct inode *cpfile, | |||
384 | } | 380 | } |
385 | 381 | ||
386 | static ssize_t nilfs_cpfile_do_get_cpinfo(struct inode *cpfile, __u64 *cnop, | 382 | static ssize_t nilfs_cpfile_do_get_cpinfo(struct inode *cpfile, __u64 *cnop, |
387 | struct nilfs_cpinfo *ci, size_t nci) | 383 | void *buf, unsigned cisz, size_t nci) |
388 | { | 384 | { |
389 | struct nilfs_checkpoint *cp; | 385 | struct nilfs_checkpoint *cp; |
386 | struct nilfs_cpinfo *ci = buf; | ||
390 | struct buffer_head *bh; | 387 | struct buffer_head *bh; |
391 | size_t cpsz = NILFS_MDT(cpfile)->mi_entry_size; | 388 | size_t cpsz = NILFS_MDT(cpfile)->mi_entry_size; |
392 | __u64 cur_cno = nilfs_mdt_cno(cpfile), cno = *cnop; | 389 | __u64 cur_cno = nilfs_mdt_cno(cpfile), cno = *cnop; |
@@ -410,17 +407,22 @@ static ssize_t nilfs_cpfile_do_get_cpinfo(struct inode *cpfile, __u64 *cnop, | |||
410 | kaddr = kmap_atomic(bh->b_page, KM_USER0); | 407 | kaddr = kmap_atomic(bh->b_page, KM_USER0); |
411 | cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, bh, kaddr); | 408 | cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, bh, kaddr); |
412 | for (i = 0; i < ncps && n < nci; i++, cp = (void *)cp + cpsz) { | 409 | for (i = 0; i < ncps && n < nci; i++, cp = (void *)cp + cpsz) { |
413 | if (!nilfs_checkpoint_invalid(cp)) | 410 | if (!nilfs_checkpoint_invalid(cp)) { |
414 | nilfs_cpfile_checkpoint_to_cpinfo( | 411 | nilfs_cpfile_checkpoint_to_cpinfo(cpfile, cp, |
415 | cpfile, cp, &ci[n++]); | 412 | ci); |
413 | ci = (void *)ci + cisz; | ||
414 | n++; | ||
415 | } | ||
416 | } | 416 | } |
417 | kunmap_atomic(kaddr, KM_USER0); | 417 | kunmap_atomic(kaddr, KM_USER0); |
418 | brelse(bh); | 418 | brelse(bh); |
419 | } | 419 | } |
420 | 420 | ||
421 | ret = n; | 421 | ret = n; |
422 | if (n > 0) | 422 | if (n > 0) { |
423 | *cnop = ci[n - 1].ci_cno + 1; | 423 | ci = (void *)ci - cisz; |
424 | *cnop = ci->ci_cno + 1; | ||
425 | } | ||
424 | 426 | ||
425 | out: | 427 | out: |
426 | up_read(&NILFS_MDT(cpfile)->mi_sem); | 428 | up_read(&NILFS_MDT(cpfile)->mi_sem); |
@@ -428,11 +430,12 @@ static ssize_t nilfs_cpfile_do_get_cpinfo(struct inode *cpfile, __u64 *cnop, | |||
428 | } | 430 | } |
429 | 431 | ||
430 | static ssize_t nilfs_cpfile_do_get_ssinfo(struct inode *cpfile, __u64 *cnop, | 432 | static ssize_t nilfs_cpfile_do_get_ssinfo(struct inode *cpfile, __u64 *cnop, |
431 | struct nilfs_cpinfo *ci, size_t nci) | 433 | void *buf, unsigned cisz, size_t nci) |
432 | { | 434 | { |
433 | struct buffer_head *bh; | 435 | struct buffer_head *bh; |
434 | struct nilfs_cpfile_header *header; | 436 | struct nilfs_cpfile_header *header; |
435 | struct nilfs_checkpoint *cp; | 437 | struct nilfs_checkpoint *cp; |
438 | struct nilfs_cpinfo *ci = buf; | ||
436 | __u64 curr = *cnop, next; | 439 | __u64 curr = *cnop, next; |
437 | unsigned long curr_blkoff, next_blkoff; | 440 | unsigned long curr_blkoff, next_blkoff; |
438 | void *kaddr; | 441 | void *kaddr; |
@@ -472,7 +475,9 @@ static ssize_t nilfs_cpfile_do_get_ssinfo(struct inode *cpfile, __u64 *cnop, | |||
472 | if (unlikely(nilfs_checkpoint_invalid(cp) || | 475 | if (unlikely(nilfs_checkpoint_invalid(cp) || |
473 | !nilfs_checkpoint_snapshot(cp))) | 476 | !nilfs_checkpoint_snapshot(cp))) |
474 | break; | 477 | break; |
475 | nilfs_cpfile_checkpoint_to_cpinfo(cpfile, cp, &ci[n++]); | 478 | nilfs_cpfile_checkpoint_to_cpinfo(cpfile, cp, ci); |
479 | ci = (void *)ci + cisz; | ||
480 | n++; | ||
476 | next = le64_to_cpu(cp->cp_snapshot_list.ssl_next); | 481 | next = le64_to_cpu(cp->cp_snapshot_list.ssl_next); |
477 | if (next == 0) | 482 | if (next == 0) |
478 | break; /* reach end of the snapshot list */ | 483 | break; /* reach end of the snapshot list */ |
@@ -511,13 +516,13 @@ static ssize_t nilfs_cpfile_do_get_ssinfo(struct inode *cpfile, __u64 *cnop, | |||
511 | */ | 516 | */ |
512 | 517 | ||
513 | ssize_t nilfs_cpfile_get_cpinfo(struct inode *cpfile, __u64 *cnop, int mode, | 518 | ssize_t nilfs_cpfile_get_cpinfo(struct inode *cpfile, __u64 *cnop, int mode, |
514 | struct nilfs_cpinfo *ci, size_t nci) | 519 | void *buf, unsigned cisz, size_t nci) |
515 | { | 520 | { |
516 | switch (mode) { | 521 | switch (mode) { |
517 | case NILFS_CHECKPOINT: | 522 | case NILFS_CHECKPOINT: |
518 | return nilfs_cpfile_do_get_cpinfo(cpfile, cnop, ci, nci); | 523 | return nilfs_cpfile_do_get_cpinfo(cpfile, cnop, buf, cisz, nci); |
519 | case NILFS_SNAPSHOT: | 524 | case NILFS_SNAPSHOT: |
520 | return nilfs_cpfile_do_get_ssinfo(cpfile, cnop, ci, nci); | 525 | return nilfs_cpfile_do_get_ssinfo(cpfile, cnop, buf, cisz, nci); |
521 | default: | 526 | default: |
522 | return -EINVAL; | 527 | return -EINVAL; |
523 | } | 528 | } |
@@ -533,20 +538,14 @@ int nilfs_cpfile_delete_checkpoint(struct inode *cpfile, __u64 cno) | |||
533 | struct nilfs_cpinfo ci; | 538 | struct nilfs_cpinfo ci; |
534 | __u64 tcno = cno; | 539 | __u64 tcno = cno; |
535 | ssize_t nci; | 540 | ssize_t nci; |
536 | int ret; | ||
537 | 541 | ||
538 | nci = nilfs_cpfile_do_get_cpinfo(cpfile, &tcno, &ci, 1); | 542 | nci = nilfs_cpfile_do_get_cpinfo(cpfile, &tcno, &ci, sizeof(ci), 1); |
539 | if (nci < 0) | 543 | if (nci < 0) |
540 | return nci; | 544 | return nci; |
541 | else if (nci == 0 || ci.ci_cno != cno) | 545 | else if (nci == 0 || ci.ci_cno != cno) |
542 | return -ENOENT; | 546 | return -ENOENT; |
543 | 547 | else if (nilfs_cpinfo_snapshot(&ci)) | |
544 | /* cannot delete the latest checkpoint nor snapshots */ | 548 | return -EBUSY; |
545 | ret = nilfs_cpinfo_snapshot(&ci); | ||
546 | if (ret < 0) | ||
547 | return ret; | ||
548 | else if (ret > 0 || cno == nilfs_mdt_cno(cpfile) - 1) | ||
549 | return -EPERM; | ||
550 | 549 | ||
551 | return nilfs_cpfile_delete_checkpoints(cpfile, cno, cno + 1); | 550 | return nilfs_cpfile_delete_checkpoints(cpfile, cno, cno + 1); |
552 | } | 551 | } |