aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl.c20
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl32.c3
-rw-r--r--fs/xfs/xfs_itable.c43
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