diff options
-rw-r--r-- | fs/xfs/linux-2.6/xfs_ioctl.c | 20 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_ioctl32.c | 3 | ||||
-rw-r--r-- | fs/xfs/xfs_itable.c | 43 |
3 files changed, 40 insertions, 26 deletions
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c index 2b34bad48b07..98a56568bb24 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/linux-2.6/xfs_ioctl.c | |||
@@ -1047,24 +1047,20 @@ xfs_ioc_bulkstat( | |||
1047 | if ((count = bulkreq.icount) <= 0) | 1047 | if ((count = bulkreq.icount) <= 0) |
1048 | return -XFS_ERROR(EINVAL); | 1048 | return -XFS_ERROR(EINVAL); |
1049 | 1049 | ||
1050 | if (bulkreq.ubuffer == NULL) | ||
1051 | return -XFS_ERROR(EINVAL); | ||
1052 | |||
1050 | if (cmd == XFS_IOC_FSINUMBERS) | 1053 | if (cmd == XFS_IOC_FSINUMBERS) |
1051 | error = xfs_inumbers(mp, &inlast, &count, | 1054 | error = xfs_inumbers(mp, &inlast, &count, |
1052 | bulkreq.ubuffer, xfs_inumbers_fmt); | 1055 | bulkreq.ubuffer, xfs_inumbers_fmt); |
1053 | else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE) | 1056 | else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE) |
1054 | error = xfs_bulkstat_single(mp, &inlast, | 1057 | error = xfs_bulkstat_single(mp, &inlast, |
1055 | bulkreq.ubuffer, &done); | 1058 | bulkreq.ubuffer, &done); |
1056 | else { /* XFS_IOC_FSBULKSTAT */ | 1059 | else /* XFS_IOC_FSBULKSTAT */ |
1057 | if (count == 1 && inlast != 0) { | 1060 | error = xfs_bulkstat(mp, &inlast, &count, |
1058 | inlast++; | 1061 | (bulkstat_one_pf)xfs_bulkstat_one, NULL, |
1059 | error = xfs_bulkstat_single(mp, &inlast, | 1062 | sizeof(xfs_bstat_t), bulkreq.ubuffer, |
1060 | bulkreq.ubuffer, &done); | 1063 | BULKSTAT_FG_QUICK, &done); |
1061 | } else { | ||
1062 | error = xfs_bulkstat(mp, &inlast, &count, | ||
1063 | (bulkstat_one_pf)xfs_bulkstat_one, NULL, | ||
1064 | sizeof(xfs_bstat_t), bulkreq.ubuffer, | ||
1065 | BULKSTAT_FG_QUICK, &done); | ||
1066 | } | ||
1067 | } | ||
1068 | 1064 | ||
1069 | if (error) | 1065 | if (error) |
1070 | return -error; | 1066 | return -error; |
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c index 0046bdd5b7f1..bf2a956b63c2 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl32.c +++ b/fs/xfs/linux-2.6/xfs_ioctl32.c | |||
@@ -291,6 +291,9 @@ xfs_ioc_bulkstat_compat( | |||
291 | if ((count = bulkreq.icount) <= 0) | 291 | if ((count = bulkreq.icount) <= 0) |
292 | return -XFS_ERROR(EINVAL); | 292 | return -XFS_ERROR(EINVAL); |
293 | 293 | ||
294 | if (bulkreq.ubuffer == NULL) | ||
295 | return -XFS_ERROR(EINVAL); | ||
296 | |||
294 | if (cmd == XFS_IOC_FSINUMBERS) | 297 | if (cmd == XFS_IOC_FSINUMBERS) |
295 | error = xfs_inumbers(mp, &inlast, &count, | 298 | error = xfs_inumbers(mp, &inlast, &count, |
296 | bulkreq.ubuffer, xfs_inumbers_fmt_compat); | 299 | bulkreq.ubuffer, xfs_inumbers_fmt_compat); |
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c index 9972992fd3c3..9fc4c2886529 100644 --- a/fs/xfs/xfs_itable.c +++ b/fs/xfs/xfs_itable.c | |||
@@ -316,6 +316,8 @@ xfs_bulkstat_use_dinode( | |||
316 | return 1; | 316 | return 1; |
317 | } | 317 | } |
318 | 318 | ||
319 | #define XFS_BULKSTAT_UBLEFT(ubleft) ((ubleft) >= statstruct_size) | ||
320 | |||
319 | /* | 321 | /* |
320 | * Return stat information in bulk (by-inode) for the filesystem. | 322 | * Return stat information in bulk (by-inode) for the filesystem. |
321 | */ | 323 | */ |
@@ -353,7 +355,7 @@ xfs_bulkstat( | |||
353 | xfs_inobt_rec_incore_t *irbp; /* current irec buffer pointer */ | 355 | xfs_inobt_rec_incore_t *irbp; /* current irec buffer pointer */ |
354 | xfs_inobt_rec_incore_t *irbuf; /* start of irec buffer */ | 356 | xfs_inobt_rec_incore_t *irbuf; /* start of irec buffer */ |
355 | xfs_inobt_rec_incore_t *irbufend; /* end of good irec buffer entries */ | 357 | xfs_inobt_rec_incore_t *irbufend; /* end of good irec buffer entries */ |
356 | xfs_ino_t lastino=0; /* last inode number returned */ | 358 | xfs_ino_t lastino; /* last inode number returned */ |
357 | int nbcluster; /* # of blocks in a cluster */ | 359 | int nbcluster; /* # of blocks in a cluster */ |
358 | int nicluster; /* # of inodes in a cluster */ | 360 | int nicluster; /* # of inodes in a cluster */ |
359 | int nimask; /* mask for inode clusters */ | 361 | int nimask; /* mask for inode clusters */ |
@@ -373,6 +375,7 @@ xfs_bulkstat( | |||
373 | * Get the last inode value, see if there's nothing to do. | 375 | * Get the last inode value, see if there's nothing to do. |
374 | */ | 376 | */ |
375 | ino = (xfs_ino_t)*lastinop; | 377 | ino = (xfs_ino_t)*lastinop; |
378 | lastino = ino; | ||
376 | dip = NULL; | 379 | dip = NULL; |
377 | agno = XFS_INO_TO_AGNO(mp, ino); | 380 | agno = XFS_INO_TO_AGNO(mp, ino); |
378 | agino = XFS_INO_TO_AGINO(mp, ino); | 381 | agino = XFS_INO_TO_AGINO(mp, ino); |
@@ -382,6 +385,9 @@ xfs_bulkstat( | |||
382 | *ubcountp = 0; | 385 | *ubcountp = 0; |
383 | return 0; | 386 | return 0; |
384 | } | 387 | } |
388 | if (!ubcountp || *ubcountp <= 0) { | ||
389 | return EINVAL; | ||
390 | } | ||
385 | ubcount = *ubcountp; /* statstruct's */ | 391 | ubcount = *ubcountp; /* statstruct's */ |
386 | ubleft = ubcount * statstruct_size; /* bytes */ | 392 | ubleft = ubcount * statstruct_size; /* bytes */ |
387 | *ubcountp = ubelem = 0; | 393 | *ubcountp = ubelem = 0; |
@@ -402,7 +408,8 @@ xfs_bulkstat( | |||
402 | * inode returned; 0 means start of the allocation group. | 408 | * inode returned; 0 means start of the allocation group. |
403 | */ | 409 | */ |
404 | rval = 0; | 410 | rval = 0; |
405 | while (ubleft >= statstruct_size && agno < mp->m_sb.sb_agcount) { | 411 | while (XFS_BULKSTAT_UBLEFT(ubleft) && agno < mp->m_sb.sb_agcount) { |
412 | cond_resched(); | ||
406 | bp = NULL; | 413 | bp = NULL; |
407 | down_read(&mp->m_peraglock); | 414 | down_read(&mp->m_peraglock); |
408 | error = xfs_ialloc_read_agi(mp, NULL, agno, &agbp); | 415 | error = xfs_ialloc_read_agi(mp, NULL, agno, &agbp); |
@@ -499,6 +506,7 @@ xfs_bulkstat( | |||
499 | break; | 506 | break; |
500 | error = xfs_inobt_lookup_ge(cur, agino, 0, 0, | 507 | error = xfs_inobt_lookup_ge(cur, agino, 0, 0, |
501 | &tmp); | 508 | &tmp); |
509 | cond_resched(); | ||
502 | } | 510 | } |
503 | /* | 511 | /* |
504 | * If ran off the end of the ag either with an error, | 512 | * If ran off the end of the ag either with an error, |
@@ -542,6 +550,7 @@ xfs_bulkstat( | |||
542 | */ | 550 | */ |
543 | agino = gino + XFS_INODES_PER_CHUNK; | 551 | agino = gino + XFS_INODES_PER_CHUNK; |
544 | error = xfs_inobt_increment(cur, 0, &tmp); | 552 | error = xfs_inobt_increment(cur, 0, &tmp); |
553 | cond_resched(); | ||
545 | } | 554 | } |
546 | /* | 555 | /* |
547 | * Drop the btree buffers and the agi buffer. | 556 | * Drop the btree buffers and the agi buffer. |
@@ -555,12 +564,12 @@ xfs_bulkstat( | |||
555 | */ | 564 | */ |
556 | irbufend = irbp; | 565 | irbufend = irbp; |
557 | for (irbp = irbuf; | 566 | for (irbp = irbuf; |
558 | irbp < irbufend && ubleft >= statstruct_size; irbp++) { | 567 | irbp < irbufend && XFS_BULKSTAT_UBLEFT(ubleft); irbp++) { |
559 | /* | 568 | /* |
560 | * Now process this chunk of inodes. | 569 | * Now process this chunk of inodes. |
561 | */ | 570 | */ |
562 | for (agino = irbp->ir_startino, chunkidx = clustidx = 0; | 571 | for (agino = irbp->ir_startino, chunkidx = clustidx = 0; |
563 | ubleft > 0 && | 572 | XFS_BULKSTAT_UBLEFT(ubleft) && |
564 | irbp->ir_freecount < XFS_INODES_PER_CHUNK; | 573 | irbp->ir_freecount < XFS_INODES_PER_CHUNK; |
565 | chunkidx++, clustidx++, agino++) { | 574 | chunkidx++, clustidx++, agino++) { |
566 | ASSERT(chunkidx < XFS_INODES_PER_CHUNK); | 575 | ASSERT(chunkidx < XFS_INODES_PER_CHUNK); |
@@ -663,15 +672,13 @@ xfs_bulkstat( | |||
663 | ubleft, private_data, | 672 | ubleft, private_data, |
664 | bno, &ubused, dip, &fmterror); | 673 | bno, &ubused, dip, &fmterror); |
665 | if (fmterror == BULKSTAT_RV_NOTHING) { | 674 | if (fmterror == BULKSTAT_RV_NOTHING) { |
666 | if (error == EFAULT) { | 675 | if (error && error != ENOENT && |
667 | ubleft = 0; | 676 | error != EINVAL) { |
668 | rval = error; | ||
669 | break; | ||
670 | } | ||
671 | else if (error == ENOMEM) | ||
672 | ubleft = 0; | 677 | ubleft = 0; |
673 | else | 678 | rval = error; |
674 | lastino = ino; | 679 | break; |
680 | } | ||
681 | lastino = ino; | ||
675 | continue; | 682 | continue; |
676 | } | 683 | } |
677 | if (fmterror == BULKSTAT_RV_GIVEUP) { | 684 | if (fmterror == BULKSTAT_RV_GIVEUP) { |
@@ -686,6 +693,8 @@ xfs_bulkstat( | |||
686 | ubelem++; | 693 | ubelem++; |
687 | lastino = ino; | 694 | lastino = ino; |
688 | } | 695 | } |
696 | |||
697 | cond_resched(); | ||
689 | } | 698 | } |
690 | 699 | ||
691 | if (bp) | 700 | if (bp) |
@@ -694,11 +703,12 @@ xfs_bulkstat( | |||
694 | /* | 703 | /* |
695 | * Set up for the next loop iteration. | 704 | * Set up for the next loop iteration. |
696 | */ | 705 | */ |
697 | if (ubleft > 0) { | 706 | if (XFS_BULKSTAT_UBLEFT(ubleft)) { |
698 | if (end_of_ag) { | 707 | if (end_of_ag) { |
699 | agno++; | 708 | agno++; |
700 | agino = 0; | 709 | agino = 0; |
701 | } | 710 | } else |
711 | agino = XFS_INO_TO_AGINO(mp, lastino); | ||
702 | } else | 712 | } else |
703 | break; | 713 | break; |
704 | } | 714 | } |
@@ -707,6 +717,11 @@ xfs_bulkstat( | |||
707 | */ | 717 | */ |
708 | kmem_free(irbuf, irbsize); | 718 | kmem_free(irbuf, irbsize); |
709 | *ubcountp = ubelem; | 719 | *ubcountp = ubelem; |
720 | /* | ||
721 | * Found some inodes, return them now and return the error next time. | ||
722 | */ | ||
723 | if (ubelem) | ||
724 | rval = 0; | ||
710 | if (agno >= mp->m_sb.sb_agcount) { | 725 | if (agno >= mp->m_sb.sb_agcount) { |
711 | /* | 726 | /* |
712 | * If we ran out of filesystem, mark lastino as off | 727 | * If we ran out of filesystem, mark lastino as off |