diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/btrfs/volumes.c | 9 | ||||
| -rw-r--r-- | fs/nilfs2/btree.c | 47 | ||||
| -rw-r--r-- | fs/xfs/xfs_file.c | 14 | ||||
| -rw-r--r-- | fs/xfs/xfs_inode.c | 4 | ||||
| -rw-r--r-- | fs/xfs/xfs_inode.h | 9 | ||||
| -rw-r--r-- | fs/xfs/xfs_iops.c | 36 | ||||
| -rw-r--r-- | fs/xfs/xfs_pnfs.c | 4 | ||||
| -rw-r--r-- | fs/xfs/xfs_qm.c | 5 |
8 files changed, 93 insertions, 35 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index cd4d1315aaa9..8222f6f74147 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
| @@ -4903,10 +4903,17 @@ static void sort_parity_stripes(struct btrfs_bio *bbio, int num_stripes) | |||
| 4903 | static struct btrfs_bio *alloc_btrfs_bio(int total_stripes, int real_stripes) | 4903 | static struct btrfs_bio *alloc_btrfs_bio(int total_stripes, int real_stripes) |
| 4904 | { | 4904 | { |
| 4905 | struct btrfs_bio *bbio = kzalloc( | 4905 | struct btrfs_bio *bbio = kzalloc( |
| 4906 | /* the size of the btrfs_bio */ | ||
| 4906 | sizeof(struct btrfs_bio) + | 4907 | sizeof(struct btrfs_bio) + |
| 4908 | /* plus the variable array for the stripes */ | ||
| 4907 | sizeof(struct btrfs_bio_stripe) * (total_stripes) + | 4909 | sizeof(struct btrfs_bio_stripe) * (total_stripes) + |
| 4910 | /* plus the variable array for the tgt dev */ | ||
| 4908 | sizeof(int) * (real_stripes) + | 4911 | sizeof(int) * (real_stripes) + |
| 4909 | sizeof(u64) * (real_stripes), | 4912 | /* |
| 4913 | * plus the raid_map, which includes both the tgt dev | ||
| 4914 | * and the stripes | ||
| 4915 | */ | ||
| 4916 | sizeof(u64) * (total_stripes), | ||
| 4910 | GFP_NOFS); | 4917 | GFP_NOFS); |
| 4911 | if (!bbio) | 4918 | if (!bbio) |
| 4912 | return NULL; | 4919 | return NULL; |
diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c index b2e3ff347620..ecdbae19a766 100644 --- a/fs/nilfs2/btree.c +++ b/fs/nilfs2/btree.c | |||
| @@ -31,6 +31,8 @@ | |||
| 31 | #include "alloc.h" | 31 | #include "alloc.h" |
| 32 | #include "dat.h" | 32 | #include "dat.h" |
| 33 | 33 | ||
| 34 | static void __nilfs_btree_init(struct nilfs_bmap *bmap); | ||
| 35 | |||
| 34 | static struct nilfs_btree_path *nilfs_btree_alloc_path(void) | 36 | static struct nilfs_btree_path *nilfs_btree_alloc_path(void) |
| 35 | { | 37 | { |
| 36 | struct nilfs_btree_path *path; | 38 | struct nilfs_btree_path *path; |
| @@ -368,6 +370,34 @@ static int nilfs_btree_node_broken(const struct nilfs_btree_node *node, | |||
| 368 | return ret; | 370 | return ret; |
| 369 | } | 371 | } |
| 370 | 372 | ||
| 373 | /** | ||
| 374 | * nilfs_btree_root_broken - verify consistency of btree root node | ||
| 375 | * @node: btree root node to be examined | ||
| 376 | * @ino: inode number | ||
| 377 | * | ||
| 378 | * Return Value: If node is broken, 1 is returned. Otherwise, 0 is returned. | ||
| 379 | */ | ||
| 380 | static int nilfs_btree_root_broken(const struct nilfs_btree_node *node, | ||
| 381 | unsigned long ino) | ||
| 382 | { | ||
| 383 | int level, flags, nchildren; | ||
| 384 | int ret = 0; | ||
| 385 | |||
| 386 | level = nilfs_btree_node_get_level(node); | ||
| 387 | flags = nilfs_btree_node_get_flags(node); | ||
| 388 | nchildren = nilfs_btree_node_get_nchildren(node); | ||
| 389 | |||
| 390 | if (unlikely(level < NILFS_BTREE_LEVEL_NODE_MIN || | ||
| 391 | level > NILFS_BTREE_LEVEL_MAX || | ||
| 392 | nchildren < 0 || | ||
| 393 | nchildren > NILFS_BTREE_ROOT_NCHILDREN_MAX)) { | ||
| 394 | pr_crit("NILFS: bad btree root (inode number=%lu): level = %d, flags = 0x%x, nchildren = %d\n", | ||
| 395 | ino, level, flags, nchildren); | ||
| 396 | ret = 1; | ||
| 397 | } | ||
| 398 | return ret; | ||
| 399 | } | ||
| 400 | |||
| 371 | int nilfs_btree_broken_node_block(struct buffer_head *bh) | 401 | int nilfs_btree_broken_node_block(struct buffer_head *bh) |
| 372 | { | 402 | { |
| 373 | int ret; | 403 | int ret; |
| @@ -1713,7 +1743,7 @@ nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *btree, | |||
| 1713 | 1743 | ||
| 1714 | /* convert and insert */ | 1744 | /* convert and insert */ |
| 1715 | dat = NILFS_BMAP_USE_VBN(btree) ? nilfs_bmap_get_dat(btree) : NULL; | 1745 | dat = NILFS_BMAP_USE_VBN(btree) ? nilfs_bmap_get_dat(btree) : NULL; |
| 1716 | nilfs_btree_init(btree); | 1746 | __nilfs_btree_init(btree); |
| 1717 | if (nreq != NULL) { | 1747 | if (nreq != NULL) { |
| 1718 | nilfs_bmap_commit_alloc_ptr(btree, dreq, dat); | 1748 | nilfs_bmap_commit_alloc_ptr(btree, dreq, dat); |
| 1719 | nilfs_bmap_commit_alloc_ptr(btree, nreq, dat); | 1749 | nilfs_bmap_commit_alloc_ptr(btree, nreq, dat); |
| @@ -2294,12 +2324,23 @@ static const struct nilfs_bmap_operations nilfs_btree_ops_gc = { | |||
| 2294 | .bop_gather_data = NULL, | 2324 | .bop_gather_data = NULL, |
| 2295 | }; | 2325 | }; |
| 2296 | 2326 | ||
| 2297 | int nilfs_btree_init(struct nilfs_bmap *bmap) | 2327 | static void __nilfs_btree_init(struct nilfs_bmap *bmap) |
| 2298 | { | 2328 | { |
| 2299 | bmap->b_ops = &nilfs_btree_ops; | 2329 | bmap->b_ops = &nilfs_btree_ops; |
| 2300 | bmap->b_nchildren_per_block = | 2330 | bmap->b_nchildren_per_block = |
| 2301 | NILFS_BTREE_NODE_NCHILDREN_MAX(nilfs_btree_node_size(bmap)); | 2331 | NILFS_BTREE_NODE_NCHILDREN_MAX(nilfs_btree_node_size(bmap)); |
| 2302 | return 0; | 2332 | } |
| 2333 | |||
| 2334 | int nilfs_btree_init(struct nilfs_bmap *bmap) | ||
| 2335 | { | ||
| 2336 | int ret = 0; | ||
| 2337 | |||
| 2338 | __nilfs_btree_init(bmap); | ||
| 2339 | |||
| 2340 | if (nilfs_btree_root_broken(nilfs_btree_get_root(bmap), | ||
| 2341 | bmap->b_inode->i_ino)) | ||
| 2342 | ret = -EIO; | ||
| 2343 | return ret; | ||
| 2303 | } | 2344 | } |
| 2304 | 2345 | ||
| 2305 | void nilfs_btree_init_gc(struct nilfs_bmap *bmap) | 2346 | void nilfs_btree_init_gc(struct nilfs_bmap *bmap) |
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index ce615d12fb44..a2e1cb8a568b 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c | |||
| @@ -397,7 +397,8 @@ STATIC int /* error (positive) */ | |||
| 397 | xfs_zero_last_block( | 397 | xfs_zero_last_block( |
| 398 | struct xfs_inode *ip, | 398 | struct xfs_inode *ip, |
| 399 | xfs_fsize_t offset, | 399 | xfs_fsize_t offset, |
| 400 | xfs_fsize_t isize) | 400 | xfs_fsize_t isize, |
| 401 | bool *did_zeroing) | ||
| 401 | { | 402 | { |
| 402 | struct xfs_mount *mp = ip->i_mount; | 403 | struct xfs_mount *mp = ip->i_mount; |
| 403 | xfs_fileoff_t last_fsb = XFS_B_TO_FSBT(mp, isize); | 404 | xfs_fileoff_t last_fsb = XFS_B_TO_FSBT(mp, isize); |
| @@ -425,6 +426,7 @@ xfs_zero_last_block( | |||
| 425 | zero_len = mp->m_sb.sb_blocksize - zero_offset; | 426 | zero_len = mp->m_sb.sb_blocksize - zero_offset; |
| 426 | if (isize + zero_len > offset) | 427 | if (isize + zero_len > offset) |
| 427 | zero_len = offset - isize; | 428 | zero_len = offset - isize; |
| 429 | *did_zeroing = true; | ||
| 428 | return xfs_iozero(ip, isize, zero_len); | 430 | return xfs_iozero(ip, isize, zero_len); |
| 429 | } | 431 | } |
| 430 | 432 | ||
| @@ -443,7 +445,8 @@ int /* error (positive) */ | |||
| 443 | xfs_zero_eof( | 445 | xfs_zero_eof( |
| 444 | struct xfs_inode *ip, | 446 | struct xfs_inode *ip, |
| 445 | xfs_off_t offset, /* starting I/O offset */ | 447 | xfs_off_t offset, /* starting I/O offset */ |
| 446 | xfs_fsize_t isize) /* current inode size */ | 448 | xfs_fsize_t isize, /* current inode size */ |
| 449 | bool *did_zeroing) | ||
| 447 | { | 450 | { |
| 448 | struct xfs_mount *mp = ip->i_mount; | 451 | struct xfs_mount *mp = ip->i_mount; |
| 449 | xfs_fileoff_t start_zero_fsb; | 452 | xfs_fileoff_t start_zero_fsb; |
| @@ -465,7 +468,7 @@ xfs_zero_eof( | |||
| 465 | * We only zero a part of that block so it is handled specially. | 468 | * We only zero a part of that block so it is handled specially. |
| 466 | */ | 469 | */ |
| 467 | if (XFS_B_FSB_OFFSET(mp, isize) != 0) { | 470 | if (XFS_B_FSB_OFFSET(mp, isize) != 0) { |
| 468 | error = xfs_zero_last_block(ip, offset, isize); | 471 | error = xfs_zero_last_block(ip, offset, isize, did_zeroing); |
| 469 | if (error) | 472 | if (error) |
| 470 | return error; | 473 | return error; |
| 471 | } | 474 | } |
| @@ -525,6 +528,7 @@ xfs_zero_eof( | |||
| 525 | if (error) | 528 | if (error) |
| 526 | return error; | 529 | return error; |
| 527 | 530 | ||
| 531 | *did_zeroing = true; | ||
| 528 | start_zero_fsb = imap.br_startoff + imap.br_blockcount; | 532 | start_zero_fsb = imap.br_startoff + imap.br_blockcount; |
| 529 | ASSERT(start_zero_fsb <= (end_zero_fsb + 1)); | 533 | ASSERT(start_zero_fsb <= (end_zero_fsb + 1)); |
| 530 | } | 534 | } |
| @@ -567,13 +571,15 @@ restart: | |||
| 567 | * having to redo all checks before. | 571 | * having to redo all checks before. |
| 568 | */ | 572 | */ |
| 569 | if (*pos > i_size_read(inode)) { | 573 | if (*pos > i_size_read(inode)) { |
| 574 | bool zero = false; | ||
| 575 | |||
| 570 | if (*iolock == XFS_IOLOCK_SHARED) { | 576 | if (*iolock == XFS_IOLOCK_SHARED) { |
| 571 | xfs_rw_iunlock(ip, *iolock); | 577 | xfs_rw_iunlock(ip, *iolock); |
| 572 | *iolock = XFS_IOLOCK_EXCL; | 578 | *iolock = XFS_IOLOCK_EXCL; |
| 573 | xfs_rw_ilock(ip, *iolock); | 579 | xfs_rw_ilock(ip, *iolock); |
| 574 | goto restart; | 580 | goto restart; |
| 575 | } | 581 | } |
| 576 | error = xfs_zero_eof(ip, *pos, i_size_read(inode)); | 582 | error = xfs_zero_eof(ip, *pos, i_size_read(inode), &zero); |
| 577 | if (error) | 583 | if (error) |
| 578 | return error; | 584 | return error; |
| 579 | } | 585 | } |
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index daafa1f6d260..6163767aa856 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
| @@ -2867,6 +2867,10 @@ xfs_rename( | |||
| 2867 | * Handle RENAME_EXCHANGE flags | 2867 | * Handle RENAME_EXCHANGE flags |
| 2868 | */ | 2868 | */ |
| 2869 | if (flags & RENAME_EXCHANGE) { | 2869 | if (flags & RENAME_EXCHANGE) { |
| 2870 | if (target_ip == NULL) { | ||
| 2871 | error = -EINVAL; | ||
| 2872 | goto error_return; | ||
| 2873 | } | ||
| 2870 | error = xfs_cross_rename(tp, src_dp, src_name, src_ip, | 2874 | error = xfs_cross_rename(tp, src_dp, src_name, src_ip, |
| 2871 | target_dp, target_name, target_ip, | 2875 | target_dp, target_name, target_ip, |
| 2872 | &free_list, &first_block, spaceres); | 2876 | &free_list, &first_block, spaceres); |
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 86cd6b39bed7..a1cd55f3f351 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h | |||
| @@ -384,10 +384,11 @@ enum xfs_prealloc_flags { | |||
| 384 | XFS_PREALLOC_INVISIBLE = (1 << 4), | 384 | XFS_PREALLOC_INVISIBLE = (1 << 4), |
| 385 | }; | 385 | }; |
| 386 | 386 | ||
| 387 | int xfs_update_prealloc_flags(struct xfs_inode *, | 387 | int xfs_update_prealloc_flags(struct xfs_inode *ip, |
| 388 | enum xfs_prealloc_flags); | 388 | enum xfs_prealloc_flags flags); |
| 389 | int xfs_zero_eof(struct xfs_inode *, xfs_off_t, xfs_fsize_t); | 389 | int xfs_zero_eof(struct xfs_inode *ip, xfs_off_t offset, |
| 390 | int xfs_iozero(struct xfs_inode *, loff_t, size_t); | 390 | xfs_fsize_t isize, bool *did_zeroing); |
| 391 | int xfs_iozero(struct xfs_inode *ip, loff_t pos, size_t count); | ||
| 391 | 392 | ||
| 392 | 393 | ||
| 393 | #define IHOLD(ip) \ | 394 | #define IHOLD(ip) \ |
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index d919ad7b16bf..e53a90331422 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c | |||
| @@ -751,6 +751,7 @@ xfs_setattr_size( | |||
| 751 | int error; | 751 | int error; |
| 752 | uint lock_flags = 0; | 752 | uint lock_flags = 0; |
| 753 | uint commit_flags = 0; | 753 | uint commit_flags = 0; |
| 754 | bool did_zeroing = false; | ||
| 754 | 755 | ||
| 755 | trace_xfs_setattr(ip); | 756 | trace_xfs_setattr(ip); |
| 756 | 757 | ||
| @@ -794,20 +795,16 @@ xfs_setattr_size( | |||
| 794 | return error; | 795 | return error; |
| 795 | 796 | ||
| 796 | /* | 797 | /* |
| 797 | * Now we can make the changes. Before we join the inode to the | 798 | * File data changes must be complete before we start the transaction to |
| 798 | * transaction, take care of the part of the truncation that must be | 799 | * modify the inode. This needs to be done before joining the inode to |
| 799 | * done without the inode lock. This needs to be done before joining | 800 | * the transaction because the inode cannot be unlocked once it is a |
| 800 | * the inode to the transaction, because the inode cannot be unlocked | 801 | * part of the transaction. |
| 801 | * once it is a part of the transaction. | 802 | * |
| 803 | * Start with zeroing any data block beyond EOF that we may expose on | ||
| 804 | * file extension. | ||
| 802 | */ | 805 | */ |
| 803 | if (newsize > oldsize) { | 806 | if (newsize > oldsize) { |
| 804 | /* | 807 | error = xfs_zero_eof(ip, newsize, oldsize, &did_zeroing); |
| 805 | * Do the first part of growing a file: zero any data in the | ||
| 806 | * last block that is beyond the old EOF. We need to do this | ||
| 807 | * before the inode is joined to the transaction to modify | ||
| 808 | * i_size. | ||
| 809 | */ | ||
| 810 | error = xfs_zero_eof(ip, newsize, oldsize); | ||
| 811 | if (error) | 808 | if (error) |
| 812 | return error; | 809 | return error; |
| 813 | } | 810 | } |
| @@ -817,23 +814,18 @@ xfs_setattr_size( | |||
| 817 | * any previous writes that are beyond the on disk EOF and the new | 814 | * any previous writes that are beyond the on disk EOF and the new |
| 818 | * EOF that have not been written out need to be written here. If we | 815 | * EOF that have not been written out need to be written here. If we |
| 819 | * do not write the data out, we expose ourselves to the null files | 816 | * do not write the data out, we expose ourselves to the null files |
| 820 | * problem. | 817 | * problem. Note that this includes any block zeroing we did above; |
| 821 | * | 818 | * otherwise those blocks may not be zeroed after a crash. |
| 822 | * Only flush from the on disk size to the smaller of the in memory | ||
| 823 | * file size or the new size as that's the range we really care about | ||
| 824 | * here and prevents waiting for other data not within the range we | ||
| 825 | * care about here. | ||
| 826 | */ | 819 | */ |
| 827 | if (oldsize != ip->i_d.di_size && newsize > ip->i_d.di_size) { | 820 | if (newsize > ip->i_d.di_size && |
| 821 | (oldsize != ip->i_d.di_size || did_zeroing)) { | ||
| 828 | error = filemap_write_and_wait_range(VFS_I(ip)->i_mapping, | 822 | error = filemap_write_and_wait_range(VFS_I(ip)->i_mapping, |
| 829 | ip->i_d.di_size, newsize); | 823 | ip->i_d.di_size, newsize); |
| 830 | if (error) | 824 | if (error) |
| 831 | return error; | 825 | return error; |
| 832 | } | 826 | } |
| 833 | 827 | ||
| 834 | /* | 828 | /* Now wait for all direct I/O to complete. */ |
| 835 | * Wait for all direct I/O to complete. | ||
| 836 | */ | ||
| 837 | inode_dio_wait(inode); | 829 | inode_dio_wait(inode); |
| 838 | 830 | ||
| 839 | /* | 831 | /* |
diff --git a/fs/xfs/xfs_pnfs.c b/fs/xfs/xfs_pnfs.c index 4b33ef112400..365dd57ea760 100644 --- a/fs/xfs/xfs_pnfs.c +++ b/fs/xfs/xfs_pnfs.c | |||
| @@ -300,8 +300,10 @@ xfs_fs_commit_blocks( | |||
| 300 | 300 | ||
| 301 | tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_NOT_SIZE); | 301 | tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_NOT_SIZE); |
| 302 | error = xfs_trans_reserve(tp, &M_RES(mp)->tr_ichange, 0, 0); | 302 | error = xfs_trans_reserve(tp, &M_RES(mp)->tr_ichange, 0, 0); |
| 303 | if (error) | 303 | if (error) { |
| 304 | xfs_trans_cancel(tp, 0); | ||
| 304 | goto out_drop_iolock; | 305 | goto out_drop_iolock; |
| 306 | } | ||
| 305 | 307 | ||
| 306 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 308 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
| 307 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | 309 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); |
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c index 53cc2aaf8d2b..fbbb9e62e274 100644 --- a/fs/xfs/xfs_qm.c +++ b/fs/xfs/xfs_qm.c | |||
| @@ -836,6 +836,11 @@ xfs_qm_reset_dqcounts( | |||
| 836 | */ | 836 | */ |
| 837 | xfs_dqcheck(mp, ddq, id+j, type, XFS_QMOPT_DQREPAIR, | 837 | xfs_dqcheck(mp, ddq, id+j, type, XFS_QMOPT_DQREPAIR, |
| 838 | "xfs_quotacheck"); | 838 | "xfs_quotacheck"); |
| 839 | /* | ||
| 840 | * Reset type in case we are reusing group quota file for | ||
| 841 | * project quotas or vice versa | ||
| 842 | */ | ||
| 843 | ddq->d_flags = type; | ||
| 839 | ddq->d_bcount = 0; | 844 | ddq->d_bcount = 0; |
| 840 | ddq->d_icount = 0; | 845 | ddq->d_icount = 0; |
| 841 | ddq->d_rtbcount = 0; | 846 | ddq->d_rtbcount = 0; |
