diff options
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_buf.c | 37 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_file.c | 129 | ||||
-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/linux-2.6/xfs_iops.c | 8 | ||||
-rw-r--r-- | fs/xfs/quota/xfs_qm.c | 3 | ||||
-rw-r--r-- | fs/xfs/xfs_dir2_block.c | 6 | ||||
-rw-r--r-- | fs/xfs/xfs_dir2_leaf.c | 2 | ||||
-rw-r--r-- | fs/xfs/xfs_dir2_sf.c | 9 | ||||
-rw-r--r-- | fs/xfs/xfs_iget.c | 2 | ||||
-rw-r--r-- | fs/xfs/xfs_inode.c | 6 | ||||
-rw-r--r-- | fs/xfs/xfs_itable.c | 43 |
12 files changed, 202 insertions, 66 deletions
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index b9c8589e05c2..a49dd8d4b069 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c | |||
@@ -725,15 +725,15 @@ xfs_buf_associate_memory( | |||
725 | { | 725 | { |
726 | int rval; | 726 | int rval; |
727 | int i = 0; | 727 | int i = 0; |
728 | size_t ptr; | 728 | unsigned long pageaddr; |
729 | size_t end, end_cur; | 729 | unsigned long offset; |
730 | off_t offset; | 730 | size_t buflen; |
731 | int page_count; | 731 | int page_count; |
732 | 732 | ||
733 | page_count = PAGE_CACHE_ALIGN(len) >> PAGE_CACHE_SHIFT; | 733 | pageaddr = (unsigned long)mem & PAGE_CACHE_MASK; |
734 | offset = (off_t) mem - ((off_t)mem & PAGE_CACHE_MASK); | 734 | offset = (unsigned long)mem - pageaddr; |
735 | if (offset && (len > PAGE_CACHE_SIZE)) | 735 | buflen = PAGE_CACHE_ALIGN(len + offset); |
736 | page_count++; | 736 | page_count = buflen >> PAGE_CACHE_SHIFT; |
737 | 737 | ||
738 | /* Free any previous set of page pointers */ | 738 | /* Free any previous set of page pointers */ |
739 | if (bp->b_pages) | 739 | if (bp->b_pages) |
@@ -747,22 +747,15 @@ xfs_buf_associate_memory( | |||
747 | return rval; | 747 | return rval; |
748 | 748 | ||
749 | bp->b_offset = offset; | 749 | bp->b_offset = offset; |
750 | ptr = (size_t) mem & PAGE_CACHE_MASK; | 750 | |
751 | end = PAGE_CACHE_ALIGN((size_t) mem + len); | 751 | for (i = 0; i < bp->b_page_count; i++) { |
752 | end_cur = end; | 752 | bp->b_pages[i] = mem_to_page((void *)pageaddr); |
753 | /* set up first page */ | 753 | pageaddr += PAGE_CACHE_SIZE; |
754 | bp->b_pages[0] = mem_to_page(mem); | ||
755 | |||
756 | ptr += PAGE_CACHE_SIZE; | ||
757 | bp->b_page_count = ++i; | ||
758 | while (ptr < end) { | ||
759 | bp->b_pages[i] = mem_to_page((void *)ptr); | ||
760 | bp->b_page_count = ++i; | ||
761 | ptr += PAGE_CACHE_SIZE; | ||
762 | } | 754 | } |
763 | bp->b_locked = 0; | 755 | bp->b_locked = 0; |
764 | 756 | ||
765 | bp->b_count_desired = bp->b_buffer_length = len; | 757 | bp->b_count_desired = len; |
758 | bp->b_buffer_length = buflen; | ||
766 | bp->b_flags |= XBF_MAPPED; | 759 | bp->b_flags |= XBF_MAPPED; |
767 | 760 | ||
768 | return 0; | 761 | return 0; |
@@ -1032,7 +1025,7 @@ xfs_buf_ioend( | |||
1032 | xfs_buf_t *bp, | 1025 | xfs_buf_t *bp, |
1033 | int schedule) | 1026 | int schedule) |
1034 | { | 1027 | { |
1035 | bp->b_flags &= ~(XBF_READ | XBF_WRITE); | 1028 | bp->b_flags &= ~(XBF_READ | XBF_WRITE | XBF_READ_AHEAD); |
1036 | if (bp->b_error == 0) | 1029 | if (bp->b_error == 0) |
1037 | bp->b_flags |= XBF_DONE; | 1030 | bp->b_flags |= XBF_DONE; |
1038 | 1031 | ||
@@ -1750,6 +1743,8 @@ xfsbufd( | |||
1750 | 1743 | ||
1751 | current->flags |= PF_MEMALLOC; | 1744 | current->flags |= PF_MEMALLOC; |
1752 | 1745 | ||
1746 | set_freezable(); | ||
1747 | |||
1753 | do { | 1748 | do { |
1754 | if (unlikely(freezing(current))) { | 1749 | if (unlikely(freezing(current))) { |
1755 | set_bit(XBT_FORCE_SLEEP, &target->bt_flags); | 1750 | set_bit(XBT_FORCE_SLEEP, &target->bt_flags); |
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index fb8dd34041eb..21a1c2b1c5fc 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c | |||
@@ -218,6 +218,15 @@ xfs_vm_fault( | |||
218 | } | 218 | } |
219 | #endif /* CONFIG_XFS_DMAPI */ | 219 | #endif /* CONFIG_XFS_DMAPI */ |
220 | 220 | ||
221 | /* | ||
222 | * Unfortunately we can't just use the clean and simple readdir implementation | ||
223 | * below, because nfs might call back into ->lookup from the filldir callback | ||
224 | * and that will deadlock the low-level btree code. | ||
225 | * | ||
226 | * Hopefully we'll find a better workaround that allows to use the optimal | ||
227 | * version at least for local readdirs for 2.6.25. | ||
228 | */ | ||
229 | #if 0 | ||
221 | STATIC int | 230 | STATIC int |
222 | xfs_file_readdir( | 231 | xfs_file_readdir( |
223 | struct file *filp, | 232 | struct file *filp, |
@@ -249,6 +258,126 @@ xfs_file_readdir( | |||
249 | return -error; | 258 | return -error; |
250 | return 0; | 259 | return 0; |
251 | } | 260 | } |
261 | #else | ||
262 | |||
263 | struct hack_dirent { | ||
264 | u64 ino; | ||
265 | loff_t offset; | ||
266 | int namlen; | ||
267 | unsigned int d_type; | ||
268 | char name[]; | ||
269 | }; | ||
270 | |||
271 | struct hack_callback { | ||
272 | char *dirent; | ||
273 | size_t len; | ||
274 | size_t used; | ||
275 | }; | ||
276 | |||
277 | STATIC int | ||
278 | xfs_hack_filldir( | ||
279 | void *__buf, | ||
280 | const char *name, | ||
281 | int namlen, | ||
282 | loff_t offset, | ||
283 | u64 ino, | ||
284 | unsigned int d_type) | ||
285 | { | ||
286 | struct hack_callback *buf = __buf; | ||
287 | struct hack_dirent *de = (struct hack_dirent *)(buf->dirent + buf->used); | ||
288 | unsigned int reclen; | ||
289 | |||
290 | reclen = ALIGN(sizeof(struct hack_dirent) + namlen, sizeof(u64)); | ||
291 | if (buf->used + reclen > buf->len) | ||
292 | return -EINVAL; | ||
293 | |||
294 | de->namlen = namlen; | ||
295 | de->offset = offset; | ||
296 | de->ino = ino; | ||
297 | de->d_type = d_type; | ||
298 | memcpy(de->name, name, namlen); | ||
299 | buf->used += reclen; | ||
300 | return 0; | ||
301 | } | ||
302 | |||
303 | STATIC int | ||
304 | xfs_file_readdir( | ||
305 | struct file *filp, | ||
306 | void *dirent, | ||
307 | filldir_t filldir) | ||
308 | { | ||
309 | struct inode *inode = filp->f_path.dentry->d_inode; | ||
310 | xfs_inode_t *ip = XFS_I(inode); | ||
311 | struct hack_callback buf; | ||
312 | struct hack_dirent *de; | ||
313 | int error; | ||
314 | loff_t size; | ||
315 | int eof = 0; | ||
316 | xfs_off_t start_offset, curr_offset, offset; | ||
317 | |||
318 | /* | ||
319 | * Try fairly hard to get memory | ||
320 | */ | ||
321 | buf.len = PAGE_CACHE_SIZE; | ||
322 | do { | ||
323 | buf.dirent = kmalloc(buf.len, GFP_KERNEL); | ||
324 | if (buf.dirent) | ||
325 | break; | ||
326 | buf.len >>= 1; | ||
327 | } while (buf.len >= 1024); | ||
328 | |||
329 | if (!buf.dirent) | ||
330 | return -ENOMEM; | ||
331 | |||
332 | curr_offset = filp->f_pos; | ||
333 | if (curr_offset == 0x7fffffff) | ||
334 | offset = 0xffffffff; | ||
335 | else | ||
336 | offset = filp->f_pos; | ||
337 | |||
338 | while (!eof) { | ||
339 | unsigned int reclen; | ||
340 | |||
341 | start_offset = offset; | ||
342 | |||
343 | buf.used = 0; | ||
344 | error = -xfs_readdir(ip, &buf, buf.len, &offset, | ||
345 | xfs_hack_filldir); | ||
346 | if (error || offset == start_offset) { | ||
347 | size = 0; | ||
348 | break; | ||
349 | } | ||
350 | |||
351 | size = buf.used; | ||
352 | de = (struct hack_dirent *)buf.dirent; | ||
353 | curr_offset = de->offset /* & 0x7fffffff */; | ||
354 | while (size > 0) { | ||
355 | if (filldir(dirent, de->name, de->namlen, | ||
356 | curr_offset & 0x7fffffff, | ||
357 | de->ino, de->d_type)) { | ||
358 | goto done; | ||
359 | } | ||
360 | |||
361 | reclen = ALIGN(sizeof(struct hack_dirent) + de->namlen, | ||
362 | sizeof(u64)); | ||
363 | size -= reclen; | ||
364 | de = (struct hack_dirent *)((char *)de + reclen); | ||
365 | curr_offset = de->offset /* & 0x7fffffff */; | ||
366 | } | ||
367 | } | ||
368 | |||
369 | done: | ||
370 | if (!error) { | ||
371 | if (size == 0) | ||
372 | filp->f_pos = offset & 0x7fffffff; | ||
373 | else if (de) | ||
374 | filp->f_pos = curr_offset; | ||
375 | } | ||
376 | |||
377 | kfree(buf.dirent); | ||
378 | return error; | ||
379 | } | ||
380 | #endif | ||
252 | 381 | ||
253 | STATIC int | 382 | STATIC int |
254 | xfs_file_mmap( | 383 | xfs_file_mmap( |
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/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index ac50f8a37582..5e8bb7f71b5a 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c | |||
@@ -117,7 +117,7 @@ xfs_ichgtime( | |||
117 | */ | 117 | */ |
118 | SYNCHRONIZE(); | 118 | SYNCHRONIZE(); |
119 | ip->i_update_core = 1; | 119 | ip->i_update_core = 1; |
120 | if (!(inode->i_state & I_SYNC)) | 120 | if (!(inode->i_state & I_NEW)) |
121 | mark_inode_dirty_sync(inode); | 121 | mark_inode_dirty_sync(inode); |
122 | } | 122 | } |
123 | 123 | ||
@@ -169,7 +169,7 @@ xfs_ichgtime_fast( | |||
169 | */ | 169 | */ |
170 | SYNCHRONIZE(); | 170 | SYNCHRONIZE(); |
171 | ip->i_update_core = 1; | 171 | ip->i_update_core = 1; |
172 | if (!(inode->i_state & I_SYNC)) | 172 | if (!(inode->i_state & I_NEW)) |
173 | mark_inode_dirty_sync(inode); | 173 | mark_inode_dirty_sync(inode); |
174 | } | 174 | } |
175 | 175 | ||
@@ -332,9 +332,7 @@ xfs_vn_mknod( | |||
332 | ASSERT(vp); | 332 | ASSERT(vp); |
333 | ip = vn_to_inode(vp); | 333 | ip = vn_to_inode(vp); |
334 | 334 | ||
335 | if (S_ISCHR(mode) || S_ISBLK(mode)) | 335 | if (S_ISDIR(mode)) |
336 | ip->i_rdev = rdev; | ||
337 | else if (S_ISDIR(mode)) | ||
338 | xfs_validate_fields(ip); | 336 | xfs_validate_fields(ip); |
339 | d_instantiate(dentry, ip); | 337 | d_instantiate(dentry, ip); |
340 | xfs_validate_fields(dir); | 338 | xfs_validate_fields(dir); |
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c index b5f91281b707..d488645f833d 100644 --- a/fs/xfs/quota/xfs_qm.c +++ b/fs/xfs/quota/xfs_qm.c | |||
@@ -1008,6 +1008,9 @@ xfs_qm_sync( | |||
1008 | boolean_t nowait; | 1008 | boolean_t nowait; |
1009 | int error; | 1009 | int error; |
1010 | 1010 | ||
1011 | if (! XFS_IS_QUOTA_ON(mp)) | ||
1012 | return 0; | ||
1013 | |||
1011 | restarts = 0; | 1014 | restarts = 0; |
1012 | /* | 1015 | /* |
1013 | * We won't block unless we are asked to. | 1016 | * We won't block unless we are asked to. |
diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c index c171767e242a..a5f4f4fb8868 100644 --- a/fs/xfs/xfs_dir2_block.c +++ b/fs/xfs/xfs_dir2_block.c | |||
@@ -508,7 +508,7 @@ xfs_dir2_block_getdents( | |||
508 | continue; | 508 | continue; |
509 | 509 | ||
510 | cook = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, | 510 | cook = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, |
511 | ptr - (char *)block); | 511 | (char *)dep - (char *)block); |
512 | ino = be64_to_cpu(dep->inumber); | 512 | ino = be64_to_cpu(dep->inumber); |
513 | #if XFS_BIG_INUMS | 513 | #if XFS_BIG_INUMS |
514 | ino += mp->m_inoadd; | 514 | ino += mp->m_inoadd; |
@@ -519,9 +519,7 @@ xfs_dir2_block_getdents( | |||
519 | */ | 519 | */ |
520 | if (filldir(dirent, dep->name, dep->namelen, cook, | 520 | if (filldir(dirent, dep->name, dep->namelen, cook, |
521 | ino, DT_UNKNOWN)) { | 521 | ino, DT_UNKNOWN)) { |
522 | *offset = xfs_dir2_db_off_to_dataptr(mp, | 522 | *offset = cook; |
523 | mp->m_dirdatablk, | ||
524 | (char *)dep - (char *)block); | ||
525 | xfs_da_brelse(NULL, bp); | 523 | xfs_da_brelse(NULL, bp); |
526 | return 0; | 524 | return 0; |
527 | } | 525 | } |
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c index e7c12fa1303e..0ca0020ba09f 100644 --- a/fs/xfs/xfs_dir2_leaf.c +++ b/fs/xfs/xfs_dir2_leaf.c | |||
@@ -1091,7 +1091,7 @@ xfs_dir2_leaf_getdents( | |||
1091 | * Won't fit. Return to caller. | 1091 | * Won't fit. Return to caller. |
1092 | */ | 1092 | */ |
1093 | if (filldir(dirent, dep->name, dep->namelen, | 1093 | if (filldir(dirent, dep->name, dep->namelen, |
1094 | xfs_dir2_byte_to_dataptr(mp, curoff + length), | 1094 | xfs_dir2_byte_to_dataptr(mp, curoff), |
1095 | ino, DT_UNKNOWN)) | 1095 | ino, DT_UNKNOWN)) |
1096 | break; | 1096 | break; |
1097 | 1097 | ||
diff --git a/fs/xfs/xfs_dir2_sf.c b/fs/xfs/xfs_dir2_sf.c index 182c70315ad1..919d275a1cef 100644 --- a/fs/xfs/xfs_dir2_sf.c +++ b/fs/xfs/xfs_dir2_sf.c | |||
@@ -752,7 +752,7 @@ xfs_dir2_sf_getdents( | |||
752 | #if XFS_BIG_INUMS | 752 | #if XFS_BIG_INUMS |
753 | ino += mp->m_inoadd; | 753 | ino += mp->m_inoadd; |
754 | #endif | 754 | #endif |
755 | if (filldir(dirent, ".", 1, dotdot_offset, ino, DT_DIR)) { | 755 | if (filldir(dirent, ".", 1, dot_offset, ino, DT_DIR)) { |
756 | *offset = dot_offset; | 756 | *offset = dot_offset; |
757 | return 0; | 757 | return 0; |
758 | } | 758 | } |
@@ -762,13 +762,11 @@ xfs_dir2_sf_getdents( | |||
762 | * Put .. entry unless we're starting past it. | 762 | * Put .. entry unless we're starting past it. |
763 | */ | 763 | */ |
764 | if (*offset <= dotdot_offset) { | 764 | if (*offset <= dotdot_offset) { |
765 | off = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, | ||
766 | XFS_DIR2_DATA_FIRST_OFFSET); | ||
767 | ino = xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent); | 765 | ino = xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent); |
768 | #if XFS_BIG_INUMS | 766 | #if XFS_BIG_INUMS |
769 | ino += mp->m_inoadd; | 767 | ino += mp->m_inoadd; |
770 | #endif | 768 | #endif |
771 | if (filldir(dirent, "..", 2, off, ino, DT_DIR)) { | 769 | if (filldir(dirent, "..", 2, dotdot_offset, ino, DT_DIR)) { |
772 | *offset = dotdot_offset; | 770 | *offset = dotdot_offset; |
773 | return 0; | 771 | return 0; |
774 | } | 772 | } |
@@ -793,8 +791,7 @@ xfs_dir2_sf_getdents( | |||
793 | #endif | 791 | #endif |
794 | 792 | ||
795 | if (filldir(dirent, sfep->name, sfep->namelen, | 793 | if (filldir(dirent, sfep->name, sfep->namelen, |
796 | off + xfs_dir2_data_entsize(sfep->namelen), | 794 | off, ino, DT_UNKNOWN)) { |
797 | ino, DT_UNKNOWN)) { | ||
798 | *offset = off; | 795 | *offset = off; |
799 | return 0; | 796 | return 0; |
800 | } | 797 | } |
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index 488836e204a3..fb69ef180b27 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c | |||
@@ -267,7 +267,7 @@ finish_inode: | |||
267 | icl = NULL; | 267 | icl = NULL; |
268 | if (radix_tree_gang_lookup(&pag->pag_ici_root, (void**)&iq, | 268 | if (radix_tree_gang_lookup(&pag->pag_ici_root, (void**)&iq, |
269 | first_index, 1)) { | 269 | first_index, 1)) { |
270 | if ((iq->i_ino & mask) == first_index) | 270 | if ((XFS_INO_TO_AGINO(mp, iq->i_ino) & mask) == first_index) |
271 | icl = iq->i_cluster; | 271 | icl = iq->i_cluster; |
272 | } | 272 | } |
273 | 273 | ||
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index abf509a88915..344948082819 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
@@ -1459,8 +1459,10 @@ xfs_itruncate_start( | |||
1459 | mp = ip->i_mount; | 1459 | mp = ip->i_mount; |
1460 | vp = XFS_ITOV(ip); | 1460 | vp = XFS_ITOV(ip); |
1461 | 1461 | ||
1462 | vn_iowait(ip); /* wait for the completion of any pending DIOs */ | 1462 | /* wait for the completion of any pending DIOs */ |
1463 | 1463 | if (new_size < ip->i_size) | |
1464 | vn_iowait(ip); | ||
1465 | |||
1464 | /* | 1466 | /* |
1465 | * Call toss_pages or flushinval_pages to get rid of pages | 1467 | * Call toss_pages or flushinval_pages to get rid of pages |
1466 | * overlapping the region being removed. We have to use | 1468 | * overlapping the region being removed. We have to use |
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 |