diff options
-rw-r--r-- | fs/nilfs2/cpfile.c | 24 | ||||
-rw-r--r-- | fs/nilfs2/cpfile.h | 2 | ||||
-rw-r--r-- | fs/nilfs2/ioctl.c | 38 |
3 files changed, 38 insertions, 26 deletions
diff --git a/fs/nilfs2/cpfile.c b/fs/nilfs2/cpfile.c index 82462acd06ee..a4c9550fd774 100644 --- a/fs/nilfs2/cpfile.c +++ b/fs/nilfs2/cpfile.c | |||
@@ -422,20 +422,20 @@ static ssize_t nilfs_cpfile_do_get_cpinfo(struct inode *cpfile, __u64 cno, | |||
422 | return ret; | 422 | return ret; |
423 | } | 423 | } |
424 | 424 | ||
425 | static ssize_t nilfs_cpfile_do_get_ssinfo(struct inode *cpfile, __u64 cno, | 425 | static ssize_t nilfs_cpfile_do_get_ssinfo(struct inode *cpfile, __u64 *cnop, |
426 | struct nilfs_cpinfo *ci, size_t nci) | 426 | struct nilfs_cpinfo *ci, size_t nci) |
427 | { | 427 | { |
428 | struct buffer_head *bh; | 428 | struct buffer_head *bh; |
429 | struct nilfs_cpfile_header *header; | 429 | struct nilfs_cpfile_header *header; |
430 | struct nilfs_checkpoint *cp; | 430 | struct nilfs_checkpoint *cp; |
431 | __u64 curr, next; | 431 | __u64 curr = *cnop, next; |
432 | unsigned long curr_blkoff, next_blkoff; | 432 | unsigned long curr_blkoff, next_blkoff; |
433 | void *kaddr; | 433 | void *kaddr; |
434 | int n, ret; | 434 | int n, ret; |
435 | 435 | ||
436 | down_read(&NILFS_MDT(cpfile)->mi_sem); | 436 | down_read(&NILFS_MDT(cpfile)->mi_sem); |
437 | 437 | ||
438 | if (cno == 0) { | 438 | if (curr == 0) { |
439 | ret = nilfs_cpfile_get_header_block(cpfile, &bh); | 439 | ret = nilfs_cpfile_get_header_block(cpfile, &bh); |
440 | if (ret < 0) | 440 | if (ret < 0) |
441 | goto out; | 441 | goto out; |
@@ -448,8 +448,11 @@ static ssize_t nilfs_cpfile_do_get_ssinfo(struct inode *cpfile, __u64 cno, | |||
448 | ret = 0; | 448 | ret = 0; |
449 | goto out; | 449 | goto out; |
450 | } | 450 | } |
451 | } else | 451 | } else if (unlikely(curr == ~(__u64)0)) { |
452 | curr = cno; | 452 | ret = 0; |
453 | goto out; | ||
454 | } | ||
455 | |||
453 | curr_blkoff = nilfs_cpfile_get_blkoff(cpfile, curr); | 456 | curr_blkoff = nilfs_cpfile_get_blkoff(cpfile, curr); |
454 | ret = nilfs_cpfile_get_checkpoint_block(cpfile, curr, 0, &bh); | 457 | ret = nilfs_cpfile_get_checkpoint_block(cpfile, curr, 0, &bh); |
455 | if (ret < 0) | 458 | if (ret < 0) |
@@ -461,7 +464,7 @@ static ssize_t nilfs_cpfile_do_get_ssinfo(struct inode *cpfile, __u64 cno, | |||
461 | nilfs_cpfile_checkpoint_to_cpinfo(cpfile, cp, &ci[n]); | 464 | nilfs_cpfile_checkpoint_to_cpinfo(cpfile, cp, &ci[n]); |
462 | next = le64_to_cpu(cp->cp_snapshot_list.ssl_next); | 465 | next = le64_to_cpu(cp->cp_snapshot_list.ssl_next); |
463 | if (next == 0) { | 466 | if (next == 0) { |
464 | curr = next; | 467 | curr = ~(__u64)0; /* Terminator */ |
465 | n++; | 468 | n++; |
466 | break; | 469 | break; |
467 | } | 470 | } |
@@ -480,6 +483,7 @@ static ssize_t nilfs_cpfile_do_get_ssinfo(struct inode *cpfile, __u64 cno, | |||
480 | } | 483 | } |
481 | kunmap_atomic(kaddr, KM_USER0); | 484 | kunmap_atomic(kaddr, KM_USER0); |
482 | brelse(bh); | 485 | brelse(bh); |
486 | *cnop = curr; | ||
483 | ret = n; | 487 | ret = n; |
484 | 488 | ||
485 | out: | 489 | out: |
@@ -494,15 +498,15 @@ static ssize_t nilfs_cpfile_do_get_ssinfo(struct inode *cpfile, __u64 cno, | |||
494 | * @ci: | 498 | * @ci: |
495 | * @nci: | 499 | * @nci: |
496 | */ | 500 | */ |
497 | ssize_t nilfs_cpfile_get_cpinfo(struct inode *cpfile, | 501 | |
498 | __u64 cno, int mode, | 502 | ssize_t nilfs_cpfile_get_cpinfo(struct inode *cpfile, __u64 *cnop, int mode, |
499 | struct nilfs_cpinfo *ci, size_t nci) | 503 | struct nilfs_cpinfo *ci, size_t nci) |
500 | { | 504 | { |
501 | switch (mode) { | 505 | switch (mode) { |
502 | case NILFS_CHECKPOINT: | 506 | case NILFS_CHECKPOINT: |
503 | return nilfs_cpfile_do_get_cpinfo(cpfile, cno, ci, nci); | 507 | return nilfs_cpfile_do_get_cpinfo(cpfile, *cnop, ci, nci); |
504 | case NILFS_SNAPSHOT: | 508 | case NILFS_SNAPSHOT: |
505 | return nilfs_cpfile_do_get_ssinfo(cpfile, cno, ci, nci); | 509 | return nilfs_cpfile_do_get_ssinfo(cpfile, cnop, ci, nci); |
506 | default: | 510 | default: |
507 | return -EINVAL; | 511 | return -EINVAL; |
508 | } | 512 | } |
diff --git a/fs/nilfs2/cpfile.h b/fs/nilfs2/cpfile.h index f097e90fcb20..1a8a1008c342 100644 --- a/fs/nilfs2/cpfile.h +++ b/fs/nilfs2/cpfile.h | |||
@@ -39,7 +39,7 @@ int nilfs_cpfile_delete_checkpoint(struct inode *, __u64); | |||
39 | int nilfs_cpfile_change_cpmode(struct inode *, __u64, int); | 39 | int nilfs_cpfile_change_cpmode(struct inode *, __u64, int); |
40 | int nilfs_cpfile_is_snapshot(struct inode *, __u64); | 40 | int nilfs_cpfile_is_snapshot(struct inode *, __u64); |
41 | int nilfs_cpfile_get_stat(struct inode *, struct nilfs_cpstat *); | 41 | int nilfs_cpfile_get_stat(struct inode *, struct nilfs_cpstat *); |
42 | ssize_t nilfs_cpfile_get_cpinfo(struct inode *, __u64, int, | 42 | ssize_t nilfs_cpfile_get_cpinfo(struct inode *, __u64 *, int, |
43 | struct nilfs_cpinfo *, size_t); | 43 | struct nilfs_cpinfo *, size_t); |
44 | 44 | ||
45 | #endif /* _NILFS_CPFILE_H */ | 45 | #endif /* _NILFS_CPFILE_H */ |
diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index 5ce06a01c7ec..d9e3990f9589 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c | |||
@@ -37,13 +37,14 @@ | |||
37 | static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs, | 37 | static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs, |
38 | struct nilfs_argv *argv, int dir, | 38 | struct nilfs_argv *argv, int dir, |
39 | ssize_t (*dofunc)(struct the_nilfs *, | 39 | ssize_t (*dofunc)(struct the_nilfs *, |
40 | int, int, | 40 | __u64 *, int, |
41 | void *, size_t, size_t)) | 41 | void *, size_t, size_t)) |
42 | { | 42 | { |
43 | void *buf; | 43 | void *buf; |
44 | size_t maxmembs, total, n; | 44 | size_t maxmembs, total, n; |
45 | ssize_t nr; | 45 | ssize_t nr; |
46 | int ret, i; | 46 | int ret, i; |
47 | __u64 pos, ppos; | ||
47 | 48 | ||
48 | if (argv->v_nmembs == 0) | 49 | if (argv->v_nmembs == 0) |
49 | return 0; | 50 | return 0; |
@@ -58,6 +59,7 @@ static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs, | |||
58 | 59 | ||
59 | ret = 0; | 60 | ret = 0; |
60 | total = 0; | 61 | total = 0; |
62 | pos = argv->v_index; | ||
61 | for (i = 0; i < argv->v_nmembs; i += n) { | 63 | for (i = 0; i < argv->v_nmembs; i += n) { |
62 | n = (argv->v_nmembs - i < maxmembs) ? | 64 | n = (argv->v_nmembs - i < maxmembs) ? |
63 | argv->v_nmembs - i : maxmembs; | 65 | argv->v_nmembs - i : maxmembs; |
@@ -68,8 +70,9 @@ static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs, | |||
68 | ret = -EFAULT; | 70 | ret = -EFAULT; |
69 | break; | 71 | break; |
70 | } | 72 | } |
71 | nr = (*dofunc)(nilfs, argv->v_index + i, argv->v_flags, buf, | 73 | ppos = pos; |
72 | argv->v_size, n); | 74 | nr = (*dofunc)(nilfs, &pos, argv->v_flags, buf, argv->v_size, |
75 | n); | ||
73 | if (nr < 0) { | 76 | if (nr < 0) { |
74 | ret = nr; | 77 | ret = nr; |
75 | break; | 78 | break; |
@@ -82,6 +85,10 @@ static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs, | |||
82 | break; | 85 | break; |
83 | } | 86 | } |
84 | total += nr; | 87 | total += nr; |
88 | if ((size_t)nr < n) | ||
89 | break; | ||
90 | if (pos == ppos) | ||
91 | pos += n; | ||
85 | } | 92 | } |
86 | argv->v_nmembs = total; | 93 | argv->v_nmembs = total; |
87 | 94 | ||
@@ -138,10 +145,10 @@ nilfs_ioctl_delete_checkpoint(struct inode *inode, struct file *filp, | |||
138 | } | 145 | } |
139 | 146 | ||
140 | static ssize_t | 147 | static ssize_t |
141 | nilfs_ioctl_do_get_cpinfo(struct the_nilfs *nilfs, int index, int flags, | 148 | nilfs_ioctl_do_get_cpinfo(struct the_nilfs *nilfs, __u64 *posp, int flags, |
142 | void *buf, size_t size, size_t nmembs) | 149 | void *buf, size_t size, size_t nmembs) |
143 | { | 150 | { |
144 | return nilfs_cpfile_get_cpinfo(nilfs->ns_cpfile, index, flags, buf, | 151 | return nilfs_cpfile_get_cpinfo(nilfs->ns_cpfile, posp, flags, buf, |
145 | nmembs); | 152 | nmembs); |
146 | } | 153 | } |
147 | 154 | ||
@@ -186,10 +193,10 @@ static int nilfs_ioctl_get_cpstat(struct inode *inode, struct file *filp, | |||
186 | } | 193 | } |
187 | 194 | ||
188 | static ssize_t | 195 | static ssize_t |
189 | nilfs_ioctl_do_get_suinfo(struct the_nilfs *nilfs, int index, int flags, | 196 | nilfs_ioctl_do_get_suinfo(struct the_nilfs *nilfs, __u64 *posp, int flags, |
190 | void *buf, size_t size, size_t nmembs) | 197 | void *buf, size_t size, size_t nmembs) |
191 | { | 198 | { |
192 | return nilfs_sufile_get_suinfo(nilfs->ns_sufile, index, buf, nmembs); | 199 | return nilfs_sufile_get_suinfo(nilfs->ns_sufile, *posp, buf, nmembs); |
193 | } | 200 | } |
194 | 201 | ||
195 | static int nilfs_ioctl_get_suinfo(struct inode *inode, struct file *filp, | 202 | static int nilfs_ioctl_get_suinfo(struct inode *inode, struct file *filp, |
@@ -233,7 +240,7 @@ static int nilfs_ioctl_get_sustat(struct inode *inode, struct file *filp, | |||
233 | } | 240 | } |
234 | 241 | ||
235 | static ssize_t | 242 | static ssize_t |
236 | nilfs_ioctl_do_get_vinfo(struct the_nilfs *nilfs, int index, int flags, | 243 | nilfs_ioctl_do_get_vinfo(struct the_nilfs *nilfs, __u64 *posp, int flags, |
237 | void *buf, size_t size, size_t nmembs) | 244 | void *buf, size_t size, size_t nmembs) |
238 | { | 245 | { |
239 | return nilfs_dat_get_vinfo(nilfs_dat_inode(nilfs), buf, nmembs); | 246 | return nilfs_dat_get_vinfo(nilfs_dat_inode(nilfs), buf, nmembs); |
@@ -262,7 +269,7 @@ static int nilfs_ioctl_get_vinfo(struct inode *inode, struct file *filp, | |||
262 | } | 269 | } |
263 | 270 | ||
264 | static ssize_t | 271 | static ssize_t |
265 | nilfs_ioctl_do_get_bdescs(struct the_nilfs *nilfs, int index, int flags, | 272 | nilfs_ioctl_do_get_bdescs(struct the_nilfs *nilfs, __u64 *posp, int flags, |
266 | void *buf, size_t size, size_t nmembs) | 273 | void *buf, size_t size, size_t nmembs) |
267 | { | 274 | { |
268 | struct inode *dat = nilfs_dat_inode(nilfs); | 275 | struct inode *dat = nilfs_dat_inode(nilfs); |
@@ -341,7 +348,7 @@ static int nilfs_ioctl_move_inode_block(struct inode *inode, | |||
341 | } | 348 | } |
342 | 349 | ||
343 | static ssize_t | 350 | static ssize_t |
344 | nilfs_ioctl_do_move_blocks(struct the_nilfs *nilfs, int index, int flags, | 351 | nilfs_ioctl_do_move_blocks(struct the_nilfs *nilfs, __u64 *posp, int flags, |
345 | void *buf, size_t size, size_t nmembs) | 352 | void *buf, size_t size, size_t nmembs) |
346 | { | 353 | { |
347 | struct inode *inode; | 354 | struct inode *inode; |
@@ -413,7 +420,7 @@ static inline int nilfs_ioctl_move_blocks(struct the_nilfs *nilfs, | |||
413 | } | 420 | } |
414 | 421 | ||
415 | static ssize_t | 422 | static ssize_t |
416 | nilfs_ioctl_do_delete_checkpoints(struct the_nilfs *nilfs, int index, | 423 | nilfs_ioctl_do_delete_checkpoints(struct the_nilfs *nilfs, __u64 *posp, |
417 | int flags, void *buf, size_t size, | 424 | int flags, void *buf, size_t size, |
418 | size_t nmembs) | 425 | size_t nmembs) |
419 | { | 426 | { |
@@ -439,7 +446,7 @@ static inline int nilfs_ioctl_delete_checkpoints(struct the_nilfs *nilfs, | |||
439 | } | 446 | } |
440 | 447 | ||
441 | static ssize_t | 448 | static ssize_t |
442 | nilfs_ioctl_do_free_vblocknrs(struct the_nilfs *nilfs, int index, int flags, | 449 | nilfs_ioctl_do_free_vblocknrs(struct the_nilfs *nilfs, __u64 *posp, int flags, |
443 | void *buf, size_t size, size_t nmembs) | 450 | void *buf, size_t size, size_t nmembs) |
444 | { | 451 | { |
445 | int ret = nilfs_dat_freev(nilfs_dat_inode(nilfs), buf, nmembs); | 452 | int ret = nilfs_dat_freev(nilfs_dat_inode(nilfs), buf, nmembs); |
@@ -456,8 +463,9 @@ static inline int nilfs_ioctl_free_vblocknrs(struct the_nilfs *nilfs, | |||
456 | } | 463 | } |
457 | 464 | ||
458 | static ssize_t | 465 | static ssize_t |
459 | nilfs_ioctl_do_mark_blocks_dirty(struct the_nilfs *nilfs, int index, int flags, | 466 | nilfs_ioctl_do_mark_blocks_dirty(struct the_nilfs *nilfs, __u64 *posp, |
460 | void *buf, size_t size, size_t nmembs) | 467 | int flags, void *buf, size_t size, |
468 | size_t nmembs) | ||
461 | { | 469 | { |
462 | struct inode *dat = nilfs_dat_inode(nilfs); | 470 | struct inode *dat = nilfs_dat_inode(nilfs); |
463 | struct nilfs_bmap *bmap = NILFS_I(dat)->i_bmap; | 471 | struct nilfs_bmap *bmap = NILFS_I(dat)->i_bmap; |
@@ -506,7 +514,7 @@ static inline int nilfs_ioctl_mark_blocks_dirty(struct the_nilfs *nilfs, | |||
506 | } | 514 | } |
507 | 515 | ||
508 | static ssize_t | 516 | static ssize_t |
509 | nilfs_ioctl_do_free_segments(struct the_nilfs *nilfs, int index, int flags, | 517 | nilfs_ioctl_do_free_segments(struct the_nilfs *nilfs, __u64 *posp, int flags, |
510 | void *buf, size_t size, size_t nmembs) | 518 | void *buf, size_t size, size_t nmembs) |
511 | { | 519 | { |
512 | struct nilfs_sb_info *sbi = nilfs_get_writer(nilfs); | 520 | struct nilfs_sb_info *sbi = nilfs_get_writer(nilfs); |