aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nilfs2/cpfile.c24
-rw-r--r--fs/nilfs2/cpfile.h2
-rw-r--r--fs/nilfs2/ioctl.c38
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
425static ssize_t nilfs_cpfile_do_get_ssinfo(struct inode *cpfile, __u64 cno, 425static 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 */
497ssize_t nilfs_cpfile_get_cpinfo(struct inode *cpfile, 501
498 __u64 cno, int mode, 502ssize_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);
39int nilfs_cpfile_change_cpmode(struct inode *, __u64, int); 39int nilfs_cpfile_change_cpmode(struct inode *, __u64, int);
40int nilfs_cpfile_is_snapshot(struct inode *, __u64); 40int nilfs_cpfile_is_snapshot(struct inode *, __u64);
41int nilfs_cpfile_get_stat(struct inode *, struct nilfs_cpstat *); 41int nilfs_cpfile_get_stat(struct inode *, struct nilfs_cpstat *);
42ssize_t nilfs_cpfile_get_cpinfo(struct inode *, __u64, int, 42ssize_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 @@
37static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs, 37static 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
140static ssize_t 147static ssize_t
141nilfs_ioctl_do_get_cpinfo(struct the_nilfs *nilfs, int index, int flags, 148nilfs_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
188static ssize_t 195static ssize_t
189nilfs_ioctl_do_get_suinfo(struct the_nilfs *nilfs, int index, int flags, 196nilfs_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
195static int nilfs_ioctl_get_suinfo(struct inode *inode, struct file *filp, 202static 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
235static ssize_t 242static ssize_t
236nilfs_ioctl_do_get_vinfo(struct the_nilfs *nilfs, int index, int flags, 243nilfs_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
264static ssize_t 271static ssize_t
265nilfs_ioctl_do_get_bdescs(struct the_nilfs *nilfs, int index, int flags, 272nilfs_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
343static ssize_t 350static ssize_t
344nilfs_ioctl_do_move_blocks(struct the_nilfs *nilfs, int index, int flags, 351nilfs_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
415static ssize_t 422static ssize_t
416nilfs_ioctl_do_delete_checkpoints(struct the_nilfs *nilfs, int index, 423nilfs_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
441static ssize_t 448static ssize_t
442nilfs_ioctl_do_free_vblocknrs(struct the_nilfs *nilfs, int index, int flags, 449nilfs_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
458static ssize_t 465static ssize_t
459nilfs_ioctl_do_mark_blocks_dirty(struct the_nilfs *nilfs, int index, int flags, 466nilfs_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
508static ssize_t 516static ssize_t
509nilfs_ioctl_do_free_segments(struct the_nilfs *nilfs, int index, int flags, 517nilfs_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);