diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/btrfs/ctree.h | 4 | ||||
| -rw-r--r-- | fs/btrfs/dir-item.c | 2 | ||||
| -rw-r--r-- | fs/btrfs/disk-io.c | 10 | ||||
| -rw-r--r-- | fs/btrfs/extent-tree.c | 7 | ||||
| -rw-r--r-- | fs/btrfs/extent_io.c | 126 | ||||
| -rw-r--r-- | fs/btrfs/inode.c | 6 | ||||
| -rw-r--r-- | fs/dax.c | 23 | ||||
| -rw-r--r-- | fs/ext4/acl.c | 4 | ||||
| -rw-r--r-- | fs/ext4/ext4.h | 2 | ||||
| -rw-r--r-- | fs/ext4/extents.c | 85 | ||||
| -rw-r--r-- | fs/ext4/file.c | 54 | ||||
| -rw-r--r-- | fs/ext4/inline.c | 5 | ||||
| -rw-r--r-- | fs/ext4/inode.c | 30 | ||||
| -rw-r--r-- | fs/ext4/mballoc.c | 23 | ||||
| -rw-r--r-- | fs/ext4/namei.c | 13 | ||||
| -rw-r--r-- | fs/ext4/super.c | 17 | ||||
| -rw-r--r-- | fs/ext4/xattr.c | 8 | ||||
| -rw-r--r-- | fs/jbd2/transaction.c | 6 | ||||
| -rw-r--r-- | fs/nfs/flexfilelayout/flexfilelayout.c | 1 | ||||
| -rw-r--r-- | fs/nfs/internal.h | 2 | ||||
| -rw-r--r-- | fs/nfs/nfs42proc.c | 2 | ||||
| -rw-r--r-- | fs/nfs/nfs4client.c | 1 | ||||
| -rw-r--r-- | fs/nfs/pnfs.c | 25 | ||||
| -rw-r--r-- | fs/nfs/pnfs.h | 10 | ||||
| -rw-r--r-- | fs/nfs/super.c | 5 | ||||
| -rw-r--r-- | fs/quota/dquot.c | 16 | ||||
| -rw-r--r-- | fs/stat.c | 1 | ||||
| -rw-r--r-- | fs/ufs/balloc.c | 26 | ||||
| -rw-r--r-- | fs/ufs/inode.c | 28 | ||||
| -rw-r--r-- | fs/ufs/super.c | 23 | ||||
| -rw-r--r-- | fs/ufs/util.h | 10 | ||||
| -rw-r--r-- | fs/xfs/xfs_buf.c | 38 | ||||
| -rw-r--r-- | fs/xfs/xfs_buf.h | 5 |
33 files changed, 430 insertions, 188 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 643c70d2b2e6..4f8f75d9e839 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
| @@ -2563,7 +2563,7 @@ u64 btrfs_csum_bytes_to_leaves(struct btrfs_fs_info *fs_info, u64 csum_bytes); | |||
| 2563 | static inline u64 btrfs_calc_trans_metadata_size(struct btrfs_fs_info *fs_info, | 2563 | static inline u64 btrfs_calc_trans_metadata_size(struct btrfs_fs_info *fs_info, |
| 2564 | unsigned num_items) | 2564 | unsigned num_items) |
| 2565 | { | 2565 | { |
| 2566 | return fs_info->nodesize * BTRFS_MAX_LEVEL * 2 * num_items; | 2566 | return (u64)fs_info->nodesize * BTRFS_MAX_LEVEL * 2 * num_items; |
| 2567 | } | 2567 | } |
| 2568 | 2568 | ||
| 2569 | /* | 2569 | /* |
| @@ -2573,7 +2573,7 @@ static inline u64 btrfs_calc_trans_metadata_size(struct btrfs_fs_info *fs_info, | |||
| 2573 | static inline u64 btrfs_calc_trunc_metadata_size(struct btrfs_fs_info *fs_info, | 2573 | static inline u64 btrfs_calc_trunc_metadata_size(struct btrfs_fs_info *fs_info, |
| 2574 | unsigned num_items) | 2574 | unsigned num_items) |
| 2575 | { | 2575 | { |
| 2576 | return fs_info->nodesize * BTRFS_MAX_LEVEL * num_items; | 2576 | return (u64)fs_info->nodesize * BTRFS_MAX_LEVEL * num_items; |
| 2577 | } | 2577 | } |
| 2578 | 2578 | ||
| 2579 | int btrfs_should_throttle_delayed_refs(struct btrfs_trans_handle *trans, | 2579 | int btrfs_should_throttle_delayed_refs(struct btrfs_trans_handle *trans, |
diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c index 60a750678a82..c24d615e3d7f 100644 --- a/fs/btrfs/dir-item.c +++ b/fs/btrfs/dir-item.c | |||
| @@ -468,7 +468,7 @@ int verify_dir_item(struct btrfs_fs_info *fs_info, | |||
| 468 | 468 | ||
| 469 | if (btrfs_dir_name_len(leaf, dir_item) > namelen) { | 469 | if (btrfs_dir_name_len(leaf, dir_item) > namelen) { |
| 470 | btrfs_crit(fs_info, "invalid dir item name len: %u", | 470 | btrfs_crit(fs_info, "invalid dir item name len: %u", |
| 471 | (unsigned)btrfs_dir_data_len(leaf, dir_item)); | 471 | (unsigned)btrfs_dir_name_len(leaf, dir_item)); |
| 472 | return 1; | 472 | return 1; |
| 473 | } | 473 | } |
| 474 | 474 | ||
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 8685d67185d0..5f678dcb20e6 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
| @@ -3467,10 +3467,12 @@ static int write_dev_supers(struct btrfs_device *device, | |||
| 3467 | * we fua the first super. The others we allow | 3467 | * we fua the first super. The others we allow |
| 3468 | * to go down lazy. | 3468 | * to go down lazy. |
| 3469 | */ | 3469 | */ |
| 3470 | if (i == 0) | 3470 | if (i == 0) { |
| 3471 | ret = btrfsic_submit_bh(REQ_OP_WRITE, REQ_FUA, bh); | 3471 | ret = btrfsic_submit_bh(REQ_OP_WRITE, |
| 3472 | else | 3472 | REQ_SYNC | REQ_FUA, bh); |
| 3473 | } else { | ||
| 3473 | ret = btrfsic_submit_bh(REQ_OP_WRITE, REQ_SYNC, bh); | 3474 | ret = btrfsic_submit_bh(REQ_OP_WRITE, REQ_SYNC, bh); |
| 3475 | } | ||
| 3474 | if (ret) | 3476 | if (ret) |
| 3475 | errors++; | 3477 | errors++; |
| 3476 | } | 3478 | } |
| @@ -3535,7 +3537,7 @@ static int write_dev_flush(struct btrfs_device *device, int wait) | |||
| 3535 | 3537 | ||
| 3536 | bio->bi_end_io = btrfs_end_empty_barrier; | 3538 | bio->bi_end_io = btrfs_end_empty_barrier; |
| 3537 | bio->bi_bdev = device->bdev; | 3539 | bio->bi_bdev = device->bdev; |
| 3538 | bio->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH; | 3540 | bio->bi_opf = REQ_OP_WRITE | REQ_SYNC | REQ_PREFLUSH; |
| 3539 | init_completion(&device->flush_wait); | 3541 | init_completion(&device->flush_wait); |
| 3540 | bio->bi_private = &device->flush_wait; | 3542 | bio->bi_private = &device->flush_wait; |
| 3541 | device->flush_bio = bio; | 3543 | device->flush_bio = bio; |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index e390451c72e6..33d979e9ea2a 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
| @@ -3993,6 +3993,7 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags, | |||
| 3993 | info->space_info_kobj, "%s", | 3993 | info->space_info_kobj, "%s", |
| 3994 | alloc_name(found->flags)); | 3994 | alloc_name(found->flags)); |
| 3995 | if (ret) { | 3995 | if (ret) { |
| 3996 | percpu_counter_destroy(&found->total_bytes_pinned); | ||
| 3996 | kfree(found); | 3997 | kfree(found); |
| 3997 | return ret; | 3998 | return ret; |
| 3998 | } | 3999 | } |
| @@ -4844,7 +4845,7 @@ static int may_commit_transaction(struct btrfs_fs_info *fs_info, | |||
| 4844 | spin_unlock(&delayed_rsv->lock); | 4845 | spin_unlock(&delayed_rsv->lock); |
| 4845 | 4846 | ||
| 4846 | commit: | 4847 | commit: |
| 4847 | trans = btrfs_join_transaction(fs_info->fs_root); | 4848 | trans = btrfs_join_transaction(fs_info->extent_root); |
| 4848 | if (IS_ERR(trans)) | 4849 | if (IS_ERR(trans)) |
| 4849 | return -ENOSPC; | 4850 | return -ENOSPC; |
| 4850 | 4851 | ||
| @@ -4862,7 +4863,7 @@ static int flush_space(struct btrfs_fs_info *fs_info, | |||
| 4862 | struct btrfs_space_info *space_info, u64 num_bytes, | 4863 | struct btrfs_space_info *space_info, u64 num_bytes, |
| 4863 | u64 orig_bytes, int state) | 4864 | u64 orig_bytes, int state) |
| 4864 | { | 4865 | { |
| 4865 | struct btrfs_root *root = fs_info->fs_root; | 4866 | struct btrfs_root *root = fs_info->extent_root; |
| 4866 | struct btrfs_trans_handle *trans; | 4867 | struct btrfs_trans_handle *trans; |
| 4867 | int nr; | 4868 | int nr; |
| 4868 | int ret = 0; | 4869 | int ret = 0; |
| @@ -5062,7 +5063,7 @@ static void priority_reclaim_metadata_space(struct btrfs_fs_info *fs_info, | |||
| 5062 | int flush_state = FLUSH_DELAYED_ITEMS_NR; | 5063 | int flush_state = FLUSH_DELAYED_ITEMS_NR; |
| 5063 | 5064 | ||
| 5064 | spin_lock(&space_info->lock); | 5065 | spin_lock(&space_info->lock); |
| 5065 | to_reclaim = btrfs_calc_reclaim_metadata_size(fs_info->fs_root, | 5066 | to_reclaim = btrfs_calc_reclaim_metadata_size(fs_info->extent_root, |
| 5066 | space_info); | 5067 | space_info); |
| 5067 | if (!to_reclaim) { | 5068 | if (!to_reclaim) { |
| 5068 | spin_unlock(&space_info->lock); | 5069 | spin_unlock(&space_info->lock); |
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index d8da3edf2ac3..d3619e010005 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
| @@ -2458,7 +2458,7 @@ void end_extent_writepage(struct page *page, int err, u64 start, u64 end) | |||
| 2458 | if (!uptodate) { | 2458 | if (!uptodate) { |
| 2459 | ClearPageUptodate(page); | 2459 | ClearPageUptodate(page); |
| 2460 | SetPageError(page); | 2460 | SetPageError(page); |
| 2461 | ret = ret < 0 ? ret : -EIO; | 2461 | ret = err < 0 ? err : -EIO; |
| 2462 | mapping_set_error(page->mapping, ret); | 2462 | mapping_set_error(page->mapping, ret); |
| 2463 | } | 2463 | } |
| 2464 | } | 2464 | } |
| @@ -4377,6 +4377,123 @@ static struct extent_map *get_extent_skip_holes(struct inode *inode, | |||
| 4377 | return NULL; | 4377 | return NULL; |
| 4378 | } | 4378 | } |
| 4379 | 4379 | ||
| 4380 | /* | ||
| 4381 | * To cache previous fiemap extent | ||
| 4382 | * | ||
| 4383 | * Will be used for merging fiemap extent | ||
| 4384 | */ | ||
| 4385 | struct fiemap_cache { | ||
| 4386 | u64 offset; | ||
| 4387 | u64 phys; | ||
| 4388 | u64 len; | ||
| 4389 | u32 flags; | ||
| 4390 | bool cached; | ||
| 4391 | }; | ||
| 4392 | |||
| 4393 | /* | ||
| 4394 | * Helper to submit fiemap extent. | ||
| 4395 | * | ||
| 4396 | * Will try to merge current fiemap extent specified by @offset, @phys, | ||
| 4397 | * @len and @flags with cached one. | ||
| 4398 | * And only when we fails to merge, cached one will be submitted as | ||
| 4399 | * fiemap extent. | ||
| 4400 | * | ||
| 4401 | * Return value is the same as fiemap_fill_next_extent(). | ||
| 4402 | */ | ||
| 4403 | static int emit_fiemap_extent(struct fiemap_extent_info *fieinfo, | ||
| 4404 | struct fiemap_cache *cache, | ||
| 4405 | u64 offset, u64 phys, u64 len, u32 flags) | ||
| 4406 | { | ||
| 4407 | int ret = 0; | ||
| 4408 | |||
| 4409 | if (!cache->cached) | ||
| 4410 | goto assign; | ||
| 4411 | |||
| 4412 | /* | ||
| 4413 | * Sanity check, extent_fiemap() should have ensured that new | ||
| 4414 | * fiemap extent won't overlap with cahced one. | ||
| 4415 | * Not recoverable. | ||
| 4416 | * | ||
| 4417 | * NOTE: Physical address can overlap, due to compression | ||
| 4418 | */ | ||
| 4419 | if (cache->offset + cache->len > offset) { | ||
| 4420 | WARN_ON(1); | ||
| 4421 | return -EINVAL; | ||
| 4422 | } | ||
| 4423 | |||
| 4424 | /* | ||
| 4425 | * Only merges fiemap extents if | ||
| 4426 | * 1) Their logical addresses are continuous | ||
| 4427 | * | ||
| 4428 | * 2) Their physical addresses are continuous | ||
| 4429 | * So truly compressed (physical size smaller than logical size) | ||
| 4430 | * extents won't get merged with each other | ||
| 4431 | * | ||
| 4432 | * 3) Share same flags except FIEMAP_EXTENT_LAST | ||
| 4433 | * So regular extent won't get merged with prealloc extent | ||
| 4434 | */ | ||
| 4435 | if (cache->offset + cache->len == offset && | ||
| 4436 | cache->phys + cache->len == phys && | ||
| 4437 | (cache->flags & ~FIEMAP_EXTENT_LAST) == | ||
| 4438 | (flags & ~FIEMAP_EXTENT_LAST)) { | ||
| 4439 | cache->len += len; | ||
| 4440 | cache->flags |= flags; | ||
| 4441 | goto try_submit_last; | ||
| 4442 | } | ||
| 4443 | |||
| 4444 | /* Not mergeable, need to submit cached one */ | ||
| 4445 | ret = fiemap_fill_next_extent(fieinfo, cache->offset, cache->phys, | ||
| 4446 | cache->len, cache->flags); | ||
| 4447 | cache->cached = false; | ||
| 4448 | if (ret) | ||
| 4449 | return ret; | ||
| 4450 | assign: | ||
| 4451 | cache->cached = true; | ||
| 4452 | cache->offset = offset; | ||
| 4453 | cache->phys = phys; | ||
| 4454 | cache->len = len; | ||
| 4455 | cache->flags = flags; | ||
| 4456 | try_submit_last: | ||
| 4457 | if (cache->flags & FIEMAP_EXTENT_LAST) { | ||
| 4458 | ret = fiemap_fill_next_extent(fieinfo, cache->offset, | ||
| 4459 | cache->phys, cache->len, cache->flags); | ||
| 4460 | cache->cached = false; | ||
| 4461 | } | ||
| 4462 | return ret; | ||
| 4463 | } | ||
| 4464 | |||
| 4465 | /* | ||
| 4466 | * Sanity check for fiemap cache | ||
| 4467 | * | ||
| 4468 | * All fiemap cache should be submitted by emit_fiemap_extent() | ||
| 4469 | * Iteration should be terminated either by last fiemap extent or | ||
| 4470 | * fieinfo->fi_extents_max. | ||
| 4471 | * So no cached fiemap should exist. | ||
| 4472 | */ | ||
| 4473 | static int check_fiemap_cache(struct btrfs_fs_info *fs_info, | ||
| 4474 | struct fiemap_extent_info *fieinfo, | ||
| 4475 | struct fiemap_cache *cache) | ||
| 4476 | { | ||
| 4477 | int ret; | ||
| 4478 | |||
| 4479 | if (!cache->cached) | ||
| 4480 | return 0; | ||
| 4481 | |||
| 4482 | /* Small and recoverbale problem, only to info developer */ | ||
| 4483 | #ifdef CONFIG_BTRFS_DEBUG | ||
| 4484 | WARN_ON(1); | ||
| 4485 | #endif | ||
| 4486 | btrfs_warn(fs_info, | ||
| 4487 | "unhandled fiemap cache detected: offset=%llu phys=%llu len=%llu flags=0x%x", | ||
| 4488 | cache->offset, cache->phys, cache->len, cache->flags); | ||
| 4489 | ret = fiemap_fill_next_extent(fieinfo, cache->offset, cache->phys, | ||
| 4490 | cache->len, cache->flags); | ||
| 4491 | cache->cached = false; | ||
| 4492 | if (ret > 0) | ||
| 4493 | ret = 0; | ||
| 4494 | return ret; | ||
| 4495 | } | ||
| 4496 | |||
| 4380 | int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | 4497 | int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, |
| 4381 | __u64 start, __u64 len, get_extent_t *get_extent) | 4498 | __u64 start, __u64 len, get_extent_t *get_extent) |
| 4382 | { | 4499 | { |
| @@ -4394,6 +4511,7 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | |||
| 4394 | struct extent_state *cached_state = NULL; | 4511 | struct extent_state *cached_state = NULL; |
| 4395 | struct btrfs_path *path; | 4512 | struct btrfs_path *path; |
| 4396 | struct btrfs_root *root = BTRFS_I(inode)->root; | 4513 | struct btrfs_root *root = BTRFS_I(inode)->root; |
| 4514 | struct fiemap_cache cache = { 0 }; | ||
| 4397 | int end = 0; | 4515 | int end = 0; |
| 4398 | u64 em_start = 0; | 4516 | u64 em_start = 0; |
| 4399 | u64 em_len = 0; | 4517 | u64 em_len = 0; |
| @@ -4573,8 +4691,8 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | |||
| 4573 | flags |= FIEMAP_EXTENT_LAST; | 4691 | flags |= FIEMAP_EXTENT_LAST; |
| 4574 | end = 1; | 4692 | end = 1; |
| 4575 | } | 4693 | } |
| 4576 | ret = fiemap_fill_next_extent(fieinfo, em_start, disko, | 4694 | ret = emit_fiemap_extent(fieinfo, &cache, em_start, disko, |
| 4577 | em_len, flags); | 4695 | em_len, flags); |
| 4578 | if (ret) { | 4696 | if (ret) { |
| 4579 | if (ret == 1) | 4697 | if (ret == 1) |
| 4580 | ret = 0; | 4698 | ret = 0; |
| @@ -4582,6 +4700,8 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | |||
| 4582 | } | 4700 | } |
| 4583 | } | 4701 | } |
| 4584 | out_free: | 4702 | out_free: |
| 4703 | if (!ret) | ||
| 4704 | ret = check_fiemap_cache(root->fs_info, fieinfo, &cache); | ||
| 4585 | free_extent_map(em); | 4705 | free_extent_map(em); |
| 4586 | out: | 4706 | out: |
| 4587 | btrfs_free_path(path); | 4707 | btrfs_free_path(path); |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 17cbe9306faf..ef3c98c527c1 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
| @@ -2952,7 +2952,7 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent) | |||
| 2952 | 2952 | ||
| 2953 | ret = test_range_bit(io_tree, ordered_extent->file_offset, | 2953 | ret = test_range_bit(io_tree, ordered_extent->file_offset, |
| 2954 | ordered_extent->file_offset + ordered_extent->len - 1, | 2954 | ordered_extent->file_offset + ordered_extent->len - 1, |
| 2955 | EXTENT_DEFRAG, 1, cached_state); | 2955 | EXTENT_DEFRAG, 0, cached_state); |
| 2956 | if (ret) { | 2956 | if (ret) { |
| 2957 | u64 last_snapshot = btrfs_root_last_snapshot(&root->root_item); | 2957 | u64 last_snapshot = btrfs_root_last_snapshot(&root->root_item); |
| 2958 | if (0 && last_snapshot >= BTRFS_I(inode)->generation) | 2958 | if (0 && last_snapshot >= BTRFS_I(inode)->generation) |
| @@ -7483,8 +7483,8 @@ bool btrfs_page_exists_in_range(struct inode *inode, loff_t start, loff_t end) | |||
| 7483 | int found = false; | 7483 | int found = false; |
| 7484 | void **pagep = NULL; | 7484 | void **pagep = NULL; |
| 7485 | struct page *page = NULL; | 7485 | struct page *page = NULL; |
| 7486 | int start_idx; | 7486 | unsigned long start_idx; |
| 7487 | int end_idx; | 7487 | unsigned long end_idx; |
| 7488 | 7488 | ||
| 7489 | start_idx = start >> PAGE_SHIFT; | 7489 | start_idx = start >> PAGE_SHIFT; |
| 7490 | 7490 | ||
| @@ -1155,6 +1155,17 @@ static int dax_iomap_pte_fault(struct vm_fault *vmf, | |||
| 1155 | } | 1155 | } |
| 1156 | 1156 | ||
| 1157 | /* | 1157 | /* |
| 1158 | * It is possible, particularly with mixed reads & writes to private | ||
| 1159 | * mappings, that we have raced with a PMD fault that overlaps with | ||
| 1160 | * the PTE we need to set up. If so just return and the fault will be | ||
| 1161 | * retried. | ||
| 1162 | */ | ||
| 1163 | if (pmd_trans_huge(*vmf->pmd) || pmd_devmap(*vmf->pmd)) { | ||
| 1164 | vmf_ret = VM_FAULT_NOPAGE; | ||
| 1165 | goto unlock_entry; | ||
| 1166 | } | ||
| 1167 | |||
| 1168 | /* | ||
| 1158 | * Note that we don't bother to use iomap_apply here: DAX required | 1169 | * Note that we don't bother to use iomap_apply here: DAX required |
| 1159 | * the file system block size to be equal the page size, which means | 1170 | * the file system block size to be equal the page size, which means |
| 1160 | * that we never have to deal with more than a single extent here. | 1171 | * that we never have to deal with more than a single extent here. |
| @@ -1398,6 +1409,18 @@ static int dax_iomap_pmd_fault(struct vm_fault *vmf, | |||
| 1398 | goto fallback; | 1409 | goto fallback; |
| 1399 | 1410 | ||
| 1400 | /* | 1411 | /* |
| 1412 | * It is possible, particularly with mixed reads & writes to private | ||
| 1413 | * mappings, that we have raced with a PTE fault that overlaps with | ||
| 1414 | * the PMD we need to set up. If so just return and the fault will be | ||
| 1415 | * retried. | ||
| 1416 | */ | ||
| 1417 | if (!pmd_none(*vmf->pmd) && !pmd_trans_huge(*vmf->pmd) && | ||
| 1418 | !pmd_devmap(*vmf->pmd)) { | ||
| 1419 | result = 0; | ||
| 1420 | goto unlock_entry; | ||
| 1421 | } | ||
| 1422 | |||
| 1423 | /* | ||
| 1401 | * Note that we don't use iomap_apply here. We aren't doing I/O, only | 1424 | * Note that we don't use iomap_apply here. We aren't doing I/O, only |
| 1402 | * setting up a mapping, so really we're using iomap_begin() as a way | 1425 | * setting up a mapping, so really we're using iomap_begin() as a way |
| 1403 | * to look up our filesystem block. | 1426 | * to look up our filesystem block. |
diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c index fd389935ecd1..3ec0e46de95f 100644 --- a/fs/ext4/acl.c +++ b/fs/ext4/acl.c | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de> | 4 | * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de> |
| 5 | */ | 5 | */ |
| 6 | 6 | ||
| 7 | #include <linux/quotaops.h> | ||
| 7 | #include "ext4_jbd2.h" | 8 | #include "ext4_jbd2.h" |
| 8 | #include "ext4.h" | 9 | #include "ext4.h" |
| 9 | #include "xattr.h" | 10 | #include "xattr.h" |
| @@ -232,6 +233,9 @@ ext4_set_acl(struct inode *inode, struct posix_acl *acl, int type) | |||
| 232 | handle_t *handle; | 233 | handle_t *handle; |
| 233 | int error, retries = 0; | 234 | int error, retries = 0; |
| 234 | 235 | ||
| 236 | error = dquot_initialize(inode); | ||
| 237 | if (error) | ||
| 238 | return error; | ||
| 235 | retry: | 239 | retry: |
| 236 | handle = ext4_journal_start(inode, EXT4_HT_XATTR, | 240 | handle = ext4_journal_start(inode, EXT4_HT_XATTR, |
| 237 | ext4_jbd2_credits_xattr(inode)); | 241 | ext4_jbd2_credits_xattr(inode)); |
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 8e8046104f4d..32191548abed 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
| @@ -2523,7 +2523,6 @@ extern int ext4_search_dir(struct buffer_head *bh, | |||
| 2523 | int buf_size, | 2523 | int buf_size, |
| 2524 | struct inode *dir, | 2524 | struct inode *dir, |
| 2525 | struct ext4_filename *fname, | 2525 | struct ext4_filename *fname, |
| 2526 | const struct qstr *d_name, | ||
| 2527 | unsigned int offset, | 2526 | unsigned int offset, |
| 2528 | struct ext4_dir_entry_2 **res_dir); | 2527 | struct ext4_dir_entry_2 **res_dir); |
| 2529 | extern int ext4_generic_delete_entry(handle_t *handle, | 2528 | extern int ext4_generic_delete_entry(handle_t *handle, |
| @@ -3007,7 +3006,6 @@ extern int htree_inlinedir_to_tree(struct file *dir_file, | |||
| 3007 | int *has_inline_data); | 3006 | int *has_inline_data); |
| 3008 | extern struct buffer_head *ext4_find_inline_entry(struct inode *dir, | 3007 | extern struct buffer_head *ext4_find_inline_entry(struct inode *dir, |
| 3009 | struct ext4_filename *fname, | 3008 | struct ext4_filename *fname, |
| 3010 | const struct qstr *d_name, | ||
| 3011 | struct ext4_dir_entry_2 **res_dir, | 3009 | struct ext4_dir_entry_2 **res_dir, |
| 3012 | int *has_inline_data); | 3010 | int *has_inline_data); |
| 3013 | extern int ext4_delete_inline_entry(handle_t *handle, | 3011 | extern int ext4_delete_inline_entry(handle_t *handle, |
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 2a97dff87b96..3e36508610b7 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
| @@ -3413,13 +3413,13 @@ static int ext4_ext_convert_to_initialized(handle_t *handle, | |||
| 3413 | struct ext4_sb_info *sbi; | 3413 | struct ext4_sb_info *sbi; |
| 3414 | struct ext4_extent_header *eh; | 3414 | struct ext4_extent_header *eh; |
| 3415 | struct ext4_map_blocks split_map; | 3415 | struct ext4_map_blocks split_map; |
| 3416 | struct ext4_extent zero_ex; | 3416 | struct ext4_extent zero_ex1, zero_ex2; |
| 3417 | struct ext4_extent *ex, *abut_ex; | 3417 | struct ext4_extent *ex, *abut_ex; |
| 3418 | ext4_lblk_t ee_block, eof_block; | 3418 | ext4_lblk_t ee_block, eof_block; |
| 3419 | unsigned int ee_len, depth, map_len = map->m_len; | 3419 | unsigned int ee_len, depth, map_len = map->m_len; |
| 3420 | int allocated = 0, max_zeroout = 0; | 3420 | int allocated = 0, max_zeroout = 0; |
| 3421 | int err = 0; | 3421 | int err = 0; |
| 3422 | int split_flag = 0; | 3422 | int split_flag = EXT4_EXT_DATA_VALID2; |
| 3423 | 3423 | ||
| 3424 | ext_debug("ext4_ext_convert_to_initialized: inode %lu, logical" | 3424 | ext_debug("ext4_ext_convert_to_initialized: inode %lu, logical" |
| 3425 | "block %llu, max_blocks %u\n", inode->i_ino, | 3425 | "block %llu, max_blocks %u\n", inode->i_ino, |
| @@ -3436,7 +3436,8 @@ static int ext4_ext_convert_to_initialized(handle_t *handle, | |||
| 3436 | ex = path[depth].p_ext; | 3436 | ex = path[depth].p_ext; |
| 3437 | ee_block = le32_to_cpu(ex->ee_block); | 3437 | ee_block = le32_to_cpu(ex->ee_block); |
| 3438 | ee_len = ext4_ext_get_actual_len(ex); | 3438 | ee_len = ext4_ext_get_actual_len(ex); |
| 3439 | zero_ex.ee_len = 0; | 3439 | zero_ex1.ee_len = 0; |
| 3440 | zero_ex2.ee_len = 0; | ||
| 3440 | 3441 | ||
| 3441 | trace_ext4_ext_convert_to_initialized_enter(inode, map, ex); | 3442 | trace_ext4_ext_convert_to_initialized_enter(inode, map, ex); |
| 3442 | 3443 | ||
| @@ -3576,62 +3577,52 @@ static int ext4_ext_convert_to_initialized(handle_t *handle, | |||
| 3576 | if (ext4_encrypted_inode(inode)) | 3577 | if (ext4_encrypted_inode(inode)) |
| 3577 | max_zeroout = 0; | 3578 | max_zeroout = 0; |
| 3578 | 3579 | ||
| 3579 | /* If extent is less than s_max_zeroout_kb, zeroout directly */ | ||
| 3580 | if (max_zeroout && (ee_len <= max_zeroout)) { | ||
| 3581 | err = ext4_ext_zeroout(inode, ex); | ||
| 3582 | if (err) | ||
| 3583 | goto out; | ||
| 3584 | zero_ex.ee_block = ex->ee_block; | ||
| 3585 | zero_ex.ee_len = cpu_to_le16(ext4_ext_get_actual_len(ex)); | ||
| 3586 | ext4_ext_store_pblock(&zero_ex, ext4_ext_pblock(ex)); | ||
| 3587 | |||
| 3588 | err = ext4_ext_get_access(handle, inode, path + depth); | ||
| 3589 | if (err) | ||
| 3590 | goto out; | ||
| 3591 | ext4_ext_mark_initialized(ex); | ||
| 3592 | ext4_ext_try_to_merge(handle, inode, path, ex); | ||
| 3593 | err = ext4_ext_dirty(handle, inode, path + path->p_depth); | ||
| 3594 | goto out; | ||
| 3595 | } | ||
| 3596 | |||
| 3597 | /* | 3580 | /* |
| 3598 | * four cases: | 3581 | * five cases: |
| 3599 | * 1. split the extent into three extents. | 3582 | * 1. split the extent into three extents. |
| 3600 | * 2. split the extent into two extents, zeroout the first half. | 3583 | * 2. split the extent into two extents, zeroout the head of the first |
| 3601 | * 3. split the extent into two extents, zeroout the second half. | 3584 | * extent. |
| 3585 | * 3. split the extent into two extents, zeroout the tail of the second | ||
| 3586 | * extent. | ||
| 3602 | * 4. split the extent into two extents with out zeroout. | 3587 | * 4. split the extent into two extents with out zeroout. |
| 3588 | * 5. no splitting needed, just possibly zeroout the head and / or the | ||
| 3589 | * tail of the extent. | ||
| 3603 | */ | 3590 | */ |
| 3604 | split_map.m_lblk = map->m_lblk; | 3591 | split_map.m_lblk = map->m_lblk; |
| 3605 | split_map.m_len = map->m_len; | 3592 | split_map.m_len = map->m_len; |
| 3606 | 3593 | ||
| 3607 | if (max_zeroout && (allocated > map->m_len)) { | 3594 | if (max_zeroout && (allocated > split_map.m_len)) { |
| 3608 | if (allocated <= max_zeroout) { | 3595 | if (allocated <= max_zeroout) { |
| 3609 | /* case 3 */ | 3596 | /* case 3 or 5 */ |
| 3610 | zero_ex.ee_block = | 3597 | zero_ex1.ee_block = |
| 3611 | cpu_to_le32(map->m_lblk); | 3598 | cpu_to_le32(split_map.m_lblk + |
| 3612 | zero_ex.ee_len = cpu_to_le16(allocated); | 3599 | split_map.m_len); |
| 3613 | ext4_ext_store_pblock(&zero_ex, | 3600 | zero_ex1.ee_len = |
| 3614 | ext4_ext_pblock(ex) + map->m_lblk - ee_block); | 3601 | cpu_to_le16(allocated - split_map.m_len); |
| 3615 | err = ext4_ext_zeroout(inode, &zero_ex); | 3602 | ext4_ext_store_pblock(&zero_ex1, |
| 3603 | ext4_ext_pblock(ex) + split_map.m_lblk + | ||
| 3604 | split_map.m_len - ee_block); | ||
| 3605 | err = ext4_ext_zeroout(inode, &zero_ex1); | ||
| 3616 | if (err) | 3606 | if (err) |
| 3617 | goto out; | 3607 | goto out; |
| 3618 | split_map.m_lblk = map->m_lblk; | ||
| 3619 | split_map.m_len = allocated; | 3608 | split_map.m_len = allocated; |
| 3620 | } else if (map->m_lblk - ee_block + map->m_len < max_zeroout) { | 3609 | } |
| 3621 | /* case 2 */ | 3610 | if (split_map.m_lblk - ee_block + split_map.m_len < |
| 3622 | if (map->m_lblk != ee_block) { | 3611 | max_zeroout) { |
| 3623 | zero_ex.ee_block = ex->ee_block; | 3612 | /* case 2 or 5 */ |
| 3624 | zero_ex.ee_len = cpu_to_le16(map->m_lblk - | 3613 | if (split_map.m_lblk != ee_block) { |
| 3614 | zero_ex2.ee_block = ex->ee_block; | ||
| 3615 | zero_ex2.ee_len = cpu_to_le16(split_map.m_lblk - | ||
| 3625 | ee_block); | 3616 | ee_block); |
| 3626 | ext4_ext_store_pblock(&zero_ex, | 3617 | ext4_ext_store_pblock(&zero_ex2, |
| 3627 | ext4_ext_pblock(ex)); | 3618 | ext4_ext_pblock(ex)); |
| 3628 | err = ext4_ext_zeroout(inode, &zero_ex); | 3619 | err = ext4_ext_zeroout(inode, &zero_ex2); |
| 3629 | if (err) | 3620 | if (err) |
| 3630 | goto out; | 3621 | goto out; |
| 3631 | } | 3622 | } |
| 3632 | 3623 | ||
| 3624 | split_map.m_len += split_map.m_lblk - ee_block; | ||
| 3633 | split_map.m_lblk = ee_block; | 3625 | split_map.m_lblk = ee_block; |
| 3634 | split_map.m_len = map->m_lblk - ee_block + map->m_len; | ||
| 3635 | allocated = map->m_len; | 3626 | allocated = map->m_len; |
| 3636 | } | 3627 | } |
| 3637 | } | 3628 | } |
| @@ -3642,8 +3633,11 @@ static int ext4_ext_convert_to_initialized(handle_t *handle, | |||
| 3642 | err = 0; | 3633 | err = 0; |
| 3643 | out: | 3634 | out: |
| 3644 | /* If we have gotten a failure, don't zero out status tree */ | 3635 | /* If we have gotten a failure, don't zero out status tree */ |
| 3645 | if (!err) | 3636 | if (!err) { |
| 3646 | err = ext4_zeroout_es(inode, &zero_ex); | 3637 | err = ext4_zeroout_es(inode, &zero_ex1); |
| 3638 | if (!err) | ||
| 3639 | err = ext4_zeroout_es(inode, &zero_ex2); | ||
| 3640 | } | ||
| 3647 | return err ? err : allocated; | 3641 | return err ? err : allocated; |
| 3648 | } | 3642 | } |
| 3649 | 3643 | ||
| @@ -4883,6 +4877,8 @@ static long ext4_zero_range(struct file *file, loff_t offset, | |||
| 4883 | 4877 | ||
| 4884 | /* Zero out partial block at the edges of the range */ | 4878 | /* Zero out partial block at the edges of the range */ |
| 4885 | ret = ext4_zero_partial_blocks(handle, inode, offset, len); | 4879 | ret = ext4_zero_partial_blocks(handle, inode, offset, len); |
| 4880 | if (ret >= 0) | ||
| 4881 | ext4_update_inode_fsync_trans(handle, inode, 1); | ||
| 4886 | 4882 | ||
| 4887 | if (file->f_flags & O_SYNC) | 4883 | if (file->f_flags & O_SYNC) |
| 4888 | ext4_handle_sync(handle); | 4884 | ext4_handle_sync(handle); |
| @@ -5569,6 +5565,7 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len) | |||
| 5569 | ext4_handle_sync(handle); | 5565 | ext4_handle_sync(handle); |
| 5570 | inode->i_mtime = inode->i_ctime = current_time(inode); | 5566 | inode->i_mtime = inode->i_ctime = current_time(inode); |
| 5571 | ext4_mark_inode_dirty(handle, inode); | 5567 | ext4_mark_inode_dirty(handle, inode); |
| 5568 | ext4_update_inode_fsync_trans(handle, inode, 1); | ||
| 5572 | 5569 | ||
| 5573 | out_stop: | 5570 | out_stop: |
| 5574 | ext4_journal_stop(handle); | 5571 | ext4_journal_stop(handle); |
| @@ -5742,6 +5739,8 @@ int ext4_insert_range(struct inode *inode, loff_t offset, loff_t len) | |||
| 5742 | up_write(&EXT4_I(inode)->i_data_sem); | 5739 | up_write(&EXT4_I(inode)->i_data_sem); |
| 5743 | if (IS_SYNC(inode)) | 5740 | if (IS_SYNC(inode)) |
| 5744 | ext4_handle_sync(handle); | 5741 | ext4_handle_sync(handle); |
| 5742 | if (ret >= 0) | ||
| 5743 | ext4_update_inode_fsync_trans(handle, inode, 1); | ||
| 5745 | 5744 | ||
| 5746 | out_stop: | 5745 | out_stop: |
| 5747 | ext4_journal_stop(handle); | 5746 | ext4_journal_stop(handle); |
diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 831fd6beebf0..02ce7e7bbdf5 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c | |||
| @@ -474,57 +474,37 @@ static int ext4_find_unwritten_pgoff(struct inode *inode, | |||
| 474 | endoff = (loff_t)end_blk << blkbits; | 474 | endoff = (loff_t)end_blk << blkbits; |
| 475 | 475 | ||
| 476 | index = startoff >> PAGE_SHIFT; | 476 | index = startoff >> PAGE_SHIFT; |
| 477 | end = endoff >> PAGE_SHIFT; | 477 | end = (endoff - 1) >> PAGE_SHIFT; |
| 478 | 478 | ||
| 479 | pagevec_init(&pvec, 0); | 479 | pagevec_init(&pvec, 0); |
| 480 | do { | 480 | do { |
| 481 | int i, num; | 481 | int i, num; |
| 482 | unsigned long nr_pages; | 482 | unsigned long nr_pages; |
| 483 | 483 | ||
| 484 | num = min_t(pgoff_t, end - index, PAGEVEC_SIZE); | 484 | num = min_t(pgoff_t, end - index, PAGEVEC_SIZE - 1) + 1; |
| 485 | nr_pages = pagevec_lookup(&pvec, inode->i_mapping, index, | 485 | nr_pages = pagevec_lookup(&pvec, inode->i_mapping, index, |
| 486 | (pgoff_t)num); | 486 | (pgoff_t)num); |
| 487 | if (nr_pages == 0) { | 487 | if (nr_pages == 0) |
| 488 | if (whence == SEEK_DATA) | ||
| 489 | break; | ||
| 490 | |||
| 491 | BUG_ON(whence != SEEK_HOLE); | ||
| 492 | /* | ||
| 493 | * If this is the first time to go into the loop and | ||
| 494 | * offset is not beyond the end offset, it will be a | ||
| 495 | * hole at this offset | ||
| 496 | */ | ||
| 497 | if (lastoff == startoff || lastoff < endoff) | ||
| 498 | found = 1; | ||
| 499 | break; | ||
| 500 | } | ||
| 501 | |||
| 502 | /* | ||
| 503 | * If this is the first time to go into the loop and | ||
| 504 | * offset is smaller than the first page offset, it will be a | ||
| 505 | * hole at this offset. | ||
| 506 | */ | ||
| 507 | if (lastoff == startoff && whence == SEEK_HOLE && | ||
| 508 | lastoff < page_offset(pvec.pages[0])) { | ||
| 509 | found = 1; | ||
| 510 | break; | 488 | break; |
| 511 | } | ||
| 512 | 489 | ||
| 513 | for (i = 0; i < nr_pages; i++) { | 490 | for (i = 0; i < nr_pages; i++) { |
| 514 | struct page *page = pvec.pages[i]; | 491 | struct page *page = pvec.pages[i]; |
| 515 | struct buffer_head *bh, *head; | 492 | struct buffer_head *bh, *head; |
| 516 | 493 | ||
| 517 | /* | 494 | /* |
| 518 | * If the current offset is not beyond the end of given | 495 | * If current offset is smaller than the page offset, |
| 519 | * range, it will be a hole. | 496 | * there is a hole at this offset. |
| 520 | */ | 497 | */ |
| 521 | if (lastoff < endoff && whence == SEEK_HOLE && | 498 | if (whence == SEEK_HOLE && lastoff < endoff && |
| 522 | page->index > end) { | 499 | lastoff < page_offset(pvec.pages[i])) { |
| 523 | found = 1; | 500 | found = 1; |
| 524 | *offset = lastoff; | 501 | *offset = lastoff; |
| 525 | goto out; | 502 | goto out; |
| 526 | } | 503 | } |
| 527 | 504 | ||
| 505 | if (page->index > end) | ||
| 506 | goto out; | ||
| 507 | |||
| 528 | lock_page(page); | 508 | lock_page(page); |
| 529 | 509 | ||
| 530 | if (unlikely(page->mapping != inode->i_mapping)) { | 510 | if (unlikely(page->mapping != inode->i_mapping)) { |
| @@ -564,20 +544,18 @@ static int ext4_find_unwritten_pgoff(struct inode *inode, | |||
| 564 | unlock_page(page); | 544 | unlock_page(page); |
| 565 | } | 545 | } |
| 566 | 546 | ||
| 567 | /* | 547 | /* The no. of pages is less than our desired, we are done. */ |
| 568 | * The no. of pages is less than our desired, that would be a | 548 | if (nr_pages < num) |
| 569 | * hole in there. | ||
| 570 | */ | ||
| 571 | if (nr_pages < num && whence == SEEK_HOLE) { | ||
| 572 | found = 1; | ||
| 573 | *offset = lastoff; | ||
| 574 | break; | 549 | break; |
| 575 | } | ||
| 576 | 550 | ||
| 577 | index = pvec.pages[i - 1]->index + 1; | 551 | index = pvec.pages[i - 1]->index + 1; |
| 578 | pagevec_release(&pvec); | 552 | pagevec_release(&pvec); |
| 579 | } while (index <= end); | 553 | } while (index <= end); |
| 580 | 554 | ||
| 555 | if (whence == SEEK_HOLE && lastoff < endoff) { | ||
| 556 | found = 1; | ||
| 557 | *offset = lastoff; | ||
| 558 | } | ||
| 581 | out: | 559 | out: |
| 582 | pagevec_release(&pvec); | 560 | pagevec_release(&pvec); |
| 583 | return found; | 561 | return found; |
diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c index d5dea4c293ef..8d141c0c8ff9 100644 --- a/fs/ext4/inline.c +++ b/fs/ext4/inline.c | |||
| @@ -1627,7 +1627,6 @@ out: | |||
| 1627 | 1627 | ||
| 1628 | struct buffer_head *ext4_find_inline_entry(struct inode *dir, | 1628 | struct buffer_head *ext4_find_inline_entry(struct inode *dir, |
| 1629 | struct ext4_filename *fname, | 1629 | struct ext4_filename *fname, |
| 1630 | const struct qstr *d_name, | ||
| 1631 | struct ext4_dir_entry_2 **res_dir, | 1630 | struct ext4_dir_entry_2 **res_dir, |
| 1632 | int *has_inline_data) | 1631 | int *has_inline_data) |
| 1633 | { | 1632 | { |
| @@ -1649,7 +1648,7 @@ struct buffer_head *ext4_find_inline_entry(struct inode *dir, | |||
| 1649 | EXT4_INLINE_DOTDOT_SIZE; | 1648 | EXT4_INLINE_DOTDOT_SIZE; |
| 1650 | inline_size = EXT4_MIN_INLINE_DATA_SIZE - EXT4_INLINE_DOTDOT_SIZE; | 1649 | inline_size = EXT4_MIN_INLINE_DATA_SIZE - EXT4_INLINE_DOTDOT_SIZE; |
| 1651 | ret = ext4_search_dir(iloc.bh, inline_start, inline_size, | 1650 | ret = ext4_search_dir(iloc.bh, inline_start, inline_size, |
| 1652 | dir, fname, d_name, 0, res_dir); | 1651 | dir, fname, 0, res_dir); |
| 1653 | if (ret == 1) | 1652 | if (ret == 1) |
| 1654 | goto out_find; | 1653 | goto out_find; |
| 1655 | if (ret < 0) | 1654 | if (ret < 0) |
| @@ -1662,7 +1661,7 @@ struct buffer_head *ext4_find_inline_entry(struct inode *dir, | |||
| 1662 | inline_size = ext4_get_inline_size(dir) - EXT4_MIN_INLINE_DATA_SIZE; | 1661 | inline_size = ext4_get_inline_size(dir) - EXT4_MIN_INLINE_DATA_SIZE; |
| 1663 | 1662 | ||
| 1664 | ret = ext4_search_dir(iloc.bh, inline_start, inline_size, | 1663 | ret = ext4_search_dir(iloc.bh, inline_start, inline_size, |
| 1665 | dir, fname, d_name, 0, res_dir); | 1664 | dir, fname, 0, res_dir); |
| 1666 | if (ret == 1) | 1665 | if (ret == 1) |
| 1667 | goto out_find; | 1666 | goto out_find; |
| 1668 | 1667 | ||
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 1bd0bfa547f6..5cf82d03968c 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
| @@ -2124,15 +2124,29 @@ static int ext4_writepage(struct page *page, | |||
| 2124 | static int mpage_submit_page(struct mpage_da_data *mpd, struct page *page) | 2124 | static int mpage_submit_page(struct mpage_da_data *mpd, struct page *page) |
| 2125 | { | 2125 | { |
| 2126 | int len; | 2126 | int len; |
| 2127 | loff_t size = i_size_read(mpd->inode); | 2127 | loff_t size; |
| 2128 | int err; | 2128 | int err; |
| 2129 | 2129 | ||
| 2130 | BUG_ON(page->index != mpd->first_page); | 2130 | BUG_ON(page->index != mpd->first_page); |
| 2131 | clear_page_dirty_for_io(page); | ||
| 2132 | /* | ||
| 2133 | * We have to be very careful here! Nothing protects writeback path | ||
| 2134 | * against i_size changes and the page can be writeably mapped into | ||
| 2135 | * page tables. So an application can be growing i_size and writing | ||
| 2136 | * data through mmap while writeback runs. clear_page_dirty_for_io() | ||
| 2137 | * write-protects our page in page tables and the page cannot get | ||
| 2138 | * written to again until we release page lock. So only after | ||
| 2139 | * clear_page_dirty_for_io() we are safe to sample i_size for | ||
| 2140 | * ext4_bio_write_page() to zero-out tail of the written page. We rely | ||
| 2141 | * on the barrier provided by TestClearPageDirty in | ||
| 2142 | * clear_page_dirty_for_io() to make sure i_size is really sampled only | ||
| 2143 | * after page tables are updated. | ||
| 2144 | */ | ||
| 2145 | size = i_size_read(mpd->inode); | ||
| 2131 | if (page->index == size >> PAGE_SHIFT) | 2146 | if (page->index == size >> PAGE_SHIFT) |
| 2132 | len = size & ~PAGE_MASK; | 2147 | len = size & ~PAGE_MASK; |
| 2133 | else | 2148 | else |
| 2134 | len = PAGE_SIZE; | 2149 | len = PAGE_SIZE; |
| 2135 | clear_page_dirty_for_io(page); | ||
| 2136 | err = ext4_bio_write_page(&mpd->io_submit, page, len, mpd->wbc, false); | 2150 | err = ext4_bio_write_page(&mpd->io_submit, page, len, mpd->wbc, false); |
| 2137 | if (!err) | 2151 | if (!err) |
| 2138 | mpd->wbc->nr_to_write--; | 2152 | mpd->wbc->nr_to_write--; |
| @@ -3629,9 +3643,6 @@ static ssize_t ext4_direct_IO_write(struct kiocb *iocb, struct iov_iter *iter) | |||
| 3629 | get_block_func = ext4_dio_get_block_unwritten_async; | 3643 | get_block_func = ext4_dio_get_block_unwritten_async; |
| 3630 | dio_flags = DIO_LOCKING; | 3644 | dio_flags = DIO_LOCKING; |
| 3631 | } | 3645 | } |
| 3632 | #ifdef CONFIG_EXT4_FS_ENCRYPTION | ||
| 3633 | BUG_ON(ext4_encrypted_inode(inode) && S_ISREG(inode->i_mode)); | ||
| 3634 | #endif | ||
| 3635 | ret = __blockdev_direct_IO(iocb, inode, inode->i_sb->s_bdev, iter, | 3646 | ret = __blockdev_direct_IO(iocb, inode, inode->i_sb->s_bdev, iter, |
| 3636 | get_block_func, ext4_end_io_dio, NULL, | 3647 | get_block_func, ext4_end_io_dio, NULL, |
| 3637 | dio_flags); | 3648 | dio_flags); |
| @@ -3713,7 +3724,7 @@ static ssize_t ext4_direct_IO_read(struct kiocb *iocb, struct iov_iter *iter) | |||
| 3713 | */ | 3724 | */ |
| 3714 | inode_lock_shared(inode); | 3725 | inode_lock_shared(inode); |
| 3715 | ret = filemap_write_and_wait_range(mapping, iocb->ki_pos, | 3726 | ret = filemap_write_and_wait_range(mapping, iocb->ki_pos, |
| 3716 | iocb->ki_pos + count); | 3727 | iocb->ki_pos + count - 1); |
| 3717 | if (ret) | 3728 | if (ret) |
| 3718 | goto out_unlock; | 3729 | goto out_unlock; |
| 3719 | ret = __blockdev_direct_IO(iocb, inode, inode->i_sb->s_bdev, | 3730 | ret = __blockdev_direct_IO(iocb, inode, inode->i_sb->s_bdev, |
| @@ -4207,6 +4218,8 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length) | |||
| 4207 | 4218 | ||
| 4208 | inode->i_mtime = inode->i_ctime = current_time(inode); | 4219 | inode->i_mtime = inode->i_ctime = current_time(inode); |
| 4209 | ext4_mark_inode_dirty(handle, inode); | 4220 | ext4_mark_inode_dirty(handle, inode); |
| 4221 | if (ret >= 0) | ||
| 4222 | ext4_update_inode_fsync_trans(handle, inode, 1); | ||
| 4210 | out_stop: | 4223 | out_stop: |
| 4211 | ext4_journal_stop(handle); | 4224 | ext4_journal_stop(handle); |
| 4212 | out_dio: | 4225 | out_dio: |
| @@ -5637,8 +5650,9 @@ static int ext4_expand_extra_isize(struct inode *inode, | |||
| 5637 | /* No extended attributes present */ | 5650 | /* No extended attributes present */ |
| 5638 | if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR) || | 5651 | if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR) || |
| 5639 | header->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC)) { | 5652 | header->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC)) { |
| 5640 | memset((void *)raw_inode + EXT4_GOOD_OLD_INODE_SIZE, 0, | 5653 | memset((void *)raw_inode + EXT4_GOOD_OLD_INODE_SIZE + |
| 5641 | new_extra_isize); | 5654 | EXT4_I(inode)->i_extra_isize, 0, |
| 5655 | new_extra_isize - EXT4_I(inode)->i_extra_isize); | ||
| 5642 | EXT4_I(inode)->i_extra_isize = new_extra_isize; | 5656 | EXT4_I(inode)->i_extra_isize = new_extra_isize; |
| 5643 | return 0; | 5657 | return 0; |
| 5644 | } | 5658 | } |
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 5083bce20ac4..b7928cddd539 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c | |||
| @@ -3887,7 +3887,8 @@ ext4_mb_discard_group_preallocations(struct super_block *sb, | |||
| 3887 | 3887 | ||
| 3888 | err = ext4_mb_load_buddy(sb, group, &e4b); | 3888 | err = ext4_mb_load_buddy(sb, group, &e4b); |
| 3889 | if (err) { | 3889 | if (err) { |
| 3890 | ext4_error(sb, "Error loading buddy information for %u", group); | 3890 | ext4_warning(sb, "Error %d loading buddy information for %u", |
| 3891 | err, group); | ||
| 3891 | put_bh(bitmap_bh); | 3892 | put_bh(bitmap_bh); |
| 3892 | return 0; | 3893 | return 0; |
| 3893 | } | 3894 | } |
| @@ -4044,10 +4045,11 @@ repeat: | |||
| 4044 | BUG_ON(pa->pa_type != MB_INODE_PA); | 4045 | BUG_ON(pa->pa_type != MB_INODE_PA); |
| 4045 | group = ext4_get_group_number(sb, pa->pa_pstart); | 4046 | group = ext4_get_group_number(sb, pa->pa_pstart); |
| 4046 | 4047 | ||
| 4047 | err = ext4_mb_load_buddy(sb, group, &e4b); | 4048 | err = ext4_mb_load_buddy_gfp(sb, group, &e4b, |
| 4049 | GFP_NOFS|__GFP_NOFAIL); | ||
| 4048 | if (err) { | 4050 | if (err) { |
| 4049 | ext4_error(sb, "Error loading buddy information for %u", | 4051 | ext4_error(sb, "Error %d loading buddy information for %u", |
| 4050 | group); | 4052 | err, group); |
| 4051 | continue; | 4053 | continue; |
| 4052 | } | 4054 | } |
| 4053 | 4055 | ||
| @@ -4303,11 +4305,14 @@ ext4_mb_discard_lg_preallocations(struct super_block *sb, | |||
| 4303 | spin_unlock(&lg->lg_prealloc_lock); | 4305 | spin_unlock(&lg->lg_prealloc_lock); |
| 4304 | 4306 | ||
| 4305 | list_for_each_entry_safe(pa, tmp, &discard_list, u.pa_tmp_list) { | 4307 | list_for_each_entry_safe(pa, tmp, &discard_list, u.pa_tmp_list) { |
| 4308 | int err; | ||
| 4306 | 4309 | ||
| 4307 | group = ext4_get_group_number(sb, pa->pa_pstart); | 4310 | group = ext4_get_group_number(sb, pa->pa_pstart); |
| 4308 | if (ext4_mb_load_buddy(sb, group, &e4b)) { | 4311 | err = ext4_mb_load_buddy_gfp(sb, group, &e4b, |
| 4309 | ext4_error(sb, "Error loading buddy information for %u", | 4312 | GFP_NOFS|__GFP_NOFAIL); |
| 4310 | group); | 4313 | if (err) { |
| 4314 | ext4_error(sb, "Error %d loading buddy information for %u", | ||
| 4315 | err, group); | ||
| 4311 | continue; | 4316 | continue; |
| 4312 | } | 4317 | } |
| 4313 | ext4_lock_group(sb, group); | 4318 | ext4_lock_group(sb, group); |
| @@ -5127,8 +5132,8 @@ ext4_trim_all_free(struct super_block *sb, ext4_group_t group, | |||
| 5127 | 5132 | ||
| 5128 | ret = ext4_mb_load_buddy(sb, group, &e4b); | 5133 | ret = ext4_mb_load_buddy(sb, group, &e4b); |
| 5129 | if (ret) { | 5134 | if (ret) { |
| 5130 | ext4_error(sb, "Error in loading buddy " | 5135 | ext4_warning(sb, "Error %d loading buddy information for %u", |
| 5131 | "information for %u", group); | 5136 | ret, group); |
| 5132 | return ret; | 5137 | return ret; |
| 5133 | } | 5138 | } |
| 5134 | bitmap = e4b.bd_bitmap; | 5139 | bitmap = e4b.bd_bitmap; |
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index b81f7d46f344..404256caf9cf 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c | |||
| @@ -1155,12 +1155,11 @@ errout: | |||
| 1155 | static inline int search_dirblock(struct buffer_head *bh, | 1155 | static inline int search_dirblock(struct buffer_head *bh, |
| 1156 | struct inode *dir, | 1156 | struct inode *dir, |
| 1157 | struct ext4_filename *fname, | 1157 | struct ext4_filename *fname, |
| 1158 | const struct qstr *d_name, | ||
| 1159 | unsigned int offset, | 1158 | unsigned int offset, |
| 1160 | struct ext4_dir_entry_2 **res_dir) | 1159 | struct ext4_dir_entry_2 **res_dir) |
| 1161 | { | 1160 | { |
| 1162 | return ext4_search_dir(bh, bh->b_data, dir->i_sb->s_blocksize, dir, | 1161 | return ext4_search_dir(bh, bh->b_data, dir->i_sb->s_blocksize, dir, |
| 1163 | fname, d_name, offset, res_dir); | 1162 | fname, offset, res_dir); |
| 1164 | } | 1163 | } |
| 1165 | 1164 | ||
| 1166 | /* | 1165 | /* |
| @@ -1262,7 +1261,6 @@ static inline bool ext4_match(const struct ext4_filename *fname, | |||
| 1262 | */ | 1261 | */ |
| 1263 | int ext4_search_dir(struct buffer_head *bh, char *search_buf, int buf_size, | 1262 | int ext4_search_dir(struct buffer_head *bh, char *search_buf, int buf_size, |
| 1264 | struct inode *dir, struct ext4_filename *fname, | 1263 | struct inode *dir, struct ext4_filename *fname, |
| 1265 | const struct qstr *d_name, | ||
| 1266 | unsigned int offset, struct ext4_dir_entry_2 **res_dir) | 1264 | unsigned int offset, struct ext4_dir_entry_2 **res_dir) |
| 1267 | { | 1265 | { |
| 1268 | struct ext4_dir_entry_2 * de; | 1266 | struct ext4_dir_entry_2 * de; |
| @@ -1355,7 +1353,7 @@ static struct buffer_head * ext4_find_entry (struct inode *dir, | |||
| 1355 | 1353 | ||
| 1356 | if (ext4_has_inline_data(dir)) { | 1354 | if (ext4_has_inline_data(dir)) { |
| 1357 | int has_inline_data = 1; | 1355 | int has_inline_data = 1; |
| 1358 | ret = ext4_find_inline_entry(dir, &fname, d_name, res_dir, | 1356 | ret = ext4_find_inline_entry(dir, &fname, res_dir, |
| 1359 | &has_inline_data); | 1357 | &has_inline_data); |
| 1360 | if (has_inline_data) { | 1358 | if (has_inline_data) { |
| 1361 | if (inlined) | 1359 | if (inlined) |
| @@ -1447,7 +1445,7 @@ restart: | |||
| 1447 | goto next; | 1445 | goto next; |
| 1448 | } | 1446 | } |
| 1449 | set_buffer_verified(bh); | 1447 | set_buffer_verified(bh); |
| 1450 | i = search_dirblock(bh, dir, &fname, d_name, | 1448 | i = search_dirblock(bh, dir, &fname, |
| 1451 | block << EXT4_BLOCK_SIZE_BITS(sb), res_dir); | 1449 | block << EXT4_BLOCK_SIZE_BITS(sb), res_dir); |
| 1452 | if (i == 1) { | 1450 | if (i == 1) { |
| 1453 | EXT4_I(dir)->i_dir_start_lookup = block; | 1451 | EXT4_I(dir)->i_dir_start_lookup = block; |
| @@ -1488,7 +1486,6 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, | |||
| 1488 | { | 1486 | { |
| 1489 | struct super_block * sb = dir->i_sb; | 1487 | struct super_block * sb = dir->i_sb; |
| 1490 | struct dx_frame frames[2], *frame; | 1488 | struct dx_frame frames[2], *frame; |
| 1491 | const struct qstr *d_name = fname->usr_fname; | ||
| 1492 | struct buffer_head *bh; | 1489 | struct buffer_head *bh; |
| 1493 | ext4_lblk_t block; | 1490 | ext4_lblk_t block; |
| 1494 | int retval; | 1491 | int retval; |
| @@ -1505,7 +1502,7 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, | |||
| 1505 | if (IS_ERR(bh)) | 1502 | if (IS_ERR(bh)) |
| 1506 | goto errout; | 1503 | goto errout; |
| 1507 | 1504 | ||
| 1508 | retval = search_dirblock(bh, dir, fname, d_name, | 1505 | retval = search_dirblock(bh, dir, fname, |
| 1509 | block << EXT4_BLOCK_SIZE_BITS(sb), | 1506 | block << EXT4_BLOCK_SIZE_BITS(sb), |
| 1510 | res_dir); | 1507 | res_dir); |
| 1511 | if (retval == 1) | 1508 | if (retval == 1) |
| @@ -1530,7 +1527,7 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, | |||
| 1530 | 1527 | ||
| 1531 | bh = NULL; | 1528 | bh = NULL; |
| 1532 | errout: | 1529 | errout: |
| 1533 | dxtrace(printk(KERN_DEBUG "%s not found\n", d_name->name)); | 1530 | dxtrace(printk(KERN_DEBUG "%s not found\n", fname->usr_fname->name)); |
| 1534 | success: | 1531 | success: |
| 1535 | dx_release(frames); | 1532 | dx_release(frames); |
| 1536 | return bh; | 1533 | return bh; |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 0b177da9ea82..d37c81f327e7 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
| @@ -848,14 +848,9 @@ static inline void ext4_quota_off_umount(struct super_block *sb) | |||
| 848 | { | 848 | { |
| 849 | int type; | 849 | int type; |
| 850 | 850 | ||
| 851 | if (ext4_has_feature_quota(sb)) { | 851 | /* Use our quota_off function to clear inode flags etc. */ |
| 852 | dquot_disable(sb, -1, | 852 | for (type = 0; type < EXT4_MAXQUOTAS; type++) |
| 853 | DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED); | 853 | ext4_quota_off(sb, type); |
| 854 | } else { | ||
| 855 | /* Use our quota_off function to clear inode flags etc. */ | ||
| 856 | for (type = 0; type < EXT4_MAXQUOTAS; type++) | ||
| 857 | ext4_quota_off(sb, type); | ||
| 858 | } | ||
| 859 | } | 854 | } |
| 860 | #else | 855 | #else |
| 861 | static inline void ext4_quota_off_umount(struct super_block *sb) | 856 | static inline void ext4_quota_off_umount(struct super_block *sb) |
| @@ -1179,6 +1174,9 @@ static int ext4_set_context(struct inode *inode, const void *ctx, size_t len, | |||
| 1179 | return res; | 1174 | return res; |
| 1180 | } | 1175 | } |
| 1181 | 1176 | ||
| 1177 | res = dquot_initialize(inode); | ||
| 1178 | if (res) | ||
| 1179 | return res; | ||
| 1182 | retry: | 1180 | retry: |
| 1183 | handle = ext4_journal_start(inode, EXT4_HT_MISC, | 1181 | handle = ext4_journal_start(inode, EXT4_HT_MISC, |
| 1184 | ext4_jbd2_credits_xattr(inode)); | 1182 | ext4_jbd2_credits_xattr(inode)); |
| @@ -5485,7 +5483,7 @@ static int ext4_quota_off(struct super_block *sb, int type) | |||
| 5485 | goto out; | 5483 | goto out; |
| 5486 | 5484 | ||
| 5487 | err = dquot_quota_off(sb, type); | 5485 | err = dquot_quota_off(sb, type); |
| 5488 | if (err) | 5486 | if (err || ext4_has_feature_quota(sb)) |
| 5489 | goto out_put; | 5487 | goto out_put; |
| 5490 | 5488 | ||
| 5491 | inode_lock(inode); | 5489 | inode_lock(inode); |
| @@ -5505,6 +5503,7 @@ static int ext4_quota_off(struct super_block *sb, int type) | |||
| 5505 | out_unlock: | 5503 | out_unlock: |
| 5506 | inode_unlock(inode); | 5504 | inode_unlock(inode); |
| 5507 | out_put: | 5505 | out_put: |
| 5506 | lockdep_set_quota_inode(inode, I_DATA_SEM_NORMAL); | ||
| 5508 | iput(inode); | 5507 | iput(inode); |
| 5509 | return err; | 5508 | return err; |
| 5510 | out: | 5509 | out: |
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index 8fb7ce14e6eb..5d3c2536641c 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c | |||
| @@ -888,6 +888,8 @@ inserted: | |||
| 888 | else { | 888 | else { |
| 889 | u32 ref; | 889 | u32 ref; |
| 890 | 890 | ||
| 891 | WARN_ON_ONCE(dquot_initialize_needed(inode)); | ||
| 892 | |||
| 891 | /* The old block is released after updating | 893 | /* The old block is released after updating |
| 892 | the inode. */ | 894 | the inode. */ |
| 893 | error = dquot_alloc_block(inode, | 895 | error = dquot_alloc_block(inode, |
| @@ -954,6 +956,8 @@ inserted: | |||
| 954 | /* We need to allocate a new block */ | 956 | /* We need to allocate a new block */ |
| 955 | ext4_fsblk_t goal, block; | 957 | ext4_fsblk_t goal, block; |
| 956 | 958 | ||
| 959 | WARN_ON_ONCE(dquot_initialize_needed(inode)); | ||
| 960 | |||
| 957 | goal = ext4_group_first_block_no(sb, | 961 | goal = ext4_group_first_block_no(sb, |
| 958 | EXT4_I(inode)->i_block_group); | 962 | EXT4_I(inode)->i_block_group); |
| 959 | 963 | ||
| @@ -1166,6 +1170,7 @@ ext4_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index, | |||
| 1166 | return -EINVAL; | 1170 | return -EINVAL; |
| 1167 | if (strlen(name) > 255) | 1171 | if (strlen(name) > 255) |
| 1168 | return -ERANGE; | 1172 | return -ERANGE; |
| 1173 | |||
| 1169 | ext4_write_lock_xattr(inode, &no_expand); | 1174 | ext4_write_lock_xattr(inode, &no_expand); |
| 1170 | 1175 | ||
| 1171 | error = ext4_reserve_inode_write(handle, inode, &is.iloc); | 1176 | error = ext4_reserve_inode_write(handle, inode, &is.iloc); |
| @@ -1267,6 +1272,9 @@ ext4_xattr_set(struct inode *inode, int name_index, const char *name, | |||
| 1267 | int error, retries = 0; | 1272 | int error, retries = 0; |
| 1268 | int credits = ext4_jbd2_credits_xattr(inode); | 1273 | int credits = ext4_jbd2_credits_xattr(inode); |
| 1269 | 1274 | ||
| 1275 | error = dquot_initialize(inode); | ||
| 1276 | if (error) | ||
| 1277 | return error; | ||
| 1270 | retry: | 1278 | retry: |
| 1271 | handle = ext4_journal_start(inode, EXT4_HT_XATTR, credits); | 1279 | handle = ext4_journal_start(inode, EXT4_HT_XATTR, credits); |
| 1272 | if (IS_ERR(handle)) { | 1280 | if (IS_ERR(handle)) { |
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index 9ee4832b6f8b..2d30a6da7013 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c | |||
| @@ -680,6 +680,12 @@ int jbd2__journal_restart(handle_t *handle, int nblocks, gfp_t gfp_mask) | |||
| 680 | 680 | ||
| 681 | rwsem_release(&journal->j_trans_commit_map, 1, _THIS_IP_); | 681 | rwsem_release(&journal->j_trans_commit_map, 1, _THIS_IP_); |
| 682 | handle->h_buffer_credits = nblocks; | 682 | handle->h_buffer_credits = nblocks; |
| 683 | /* | ||
| 684 | * Restore the original nofs context because the journal restart | ||
| 685 | * is basically the same thing as journal stop and start. | ||
| 686 | * start_this_handle will start a new nofs context. | ||
| 687 | */ | ||
| 688 | memalloc_nofs_restore(handle->saved_alloc_context); | ||
| 683 | ret = start_this_handle(journal, handle, gfp_mask); | 689 | ret = start_this_handle(journal, handle, gfp_mask); |
| 684 | return ret; | 690 | return ret; |
| 685 | } | 691 | } |
diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c index f5714ee01000..23542dc44a25 100644 --- a/fs/nfs/flexfilelayout/flexfilelayout.c +++ b/fs/nfs/flexfilelayout/flexfilelayout.c | |||
| @@ -454,6 +454,7 @@ ff_layout_alloc_lseg(struct pnfs_layout_hdr *lh, | |||
| 454 | goto out_err_free; | 454 | goto out_err_free; |
| 455 | 455 | ||
| 456 | /* fh */ | 456 | /* fh */ |
| 457 | rc = -EIO; | ||
| 457 | p = xdr_inline_decode(&stream, 4); | 458 | p = xdr_inline_decode(&stream, 4); |
| 458 | if (!p) | 459 | if (!p) |
| 459 | goto out_err_free; | 460 | goto out_err_free; |
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index e9b4c3320e37..3e24392f2caa 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
| @@ -398,7 +398,6 @@ extern struct file_system_type nfs4_referral_fs_type; | |||
| 398 | bool nfs_auth_info_match(const struct nfs_auth_info *, rpc_authflavor_t); | 398 | bool nfs_auth_info_match(const struct nfs_auth_info *, rpc_authflavor_t); |
| 399 | struct dentry *nfs_try_mount(int, const char *, struct nfs_mount_info *, | 399 | struct dentry *nfs_try_mount(int, const char *, struct nfs_mount_info *, |
| 400 | struct nfs_subversion *); | 400 | struct nfs_subversion *); |
| 401 | void nfs_initialise_sb(struct super_block *); | ||
| 402 | int nfs_set_sb_security(struct super_block *, struct dentry *, struct nfs_mount_info *); | 401 | int nfs_set_sb_security(struct super_block *, struct dentry *, struct nfs_mount_info *); |
| 403 | int nfs_clone_sb_security(struct super_block *, struct dentry *, struct nfs_mount_info *); | 402 | int nfs_clone_sb_security(struct super_block *, struct dentry *, struct nfs_mount_info *); |
| 404 | struct dentry *nfs_fs_mount_common(struct nfs_server *, int, const char *, | 403 | struct dentry *nfs_fs_mount_common(struct nfs_server *, int, const char *, |
| @@ -458,7 +457,6 @@ extern void nfs_read_prepare(struct rpc_task *task, void *calldata); | |||
| 458 | extern void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio); | 457 | extern void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio); |
| 459 | 458 | ||
| 460 | /* super.c */ | 459 | /* super.c */ |
| 461 | void nfs_clone_super(struct super_block *, struct nfs_mount_info *); | ||
| 462 | void nfs_umount_begin(struct super_block *); | 460 | void nfs_umount_begin(struct super_block *); |
| 463 | int nfs_statfs(struct dentry *, struct kstatfs *); | 461 | int nfs_statfs(struct dentry *, struct kstatfs *); |
| 464 | int nfs_show_options(struct seq_file *, struct dentry *); | 462 | int nfs_show_options(struct seq_file *, struct dentry *); |
diff --git a/fs/nfs/nfs42proc.c b/fs/nfs/nfs42proc.c index 929d09a5310a..319a47db218d 100644 --- a/fs/nfs/nfs42proc.c +++ b/fs/nfs/nfs42proc.c | |||
| @@ -177,7 +177,7 @@ static ssize_t _nfs42_proc_copy(struct file *src, | |||
| 177 | if (status) | 177 | if (status) |
| 178 | goto out; | 178 | goto out; |
| 179 | 179 | ||
| 180 | if (!nfs_write_verifier_cmp(&res->write_res.verifier.verifier, | 180 | if (nfs_write_verifier_cmp(&res->write_res.verifier.verifier, |
| 181 | &res->commit_res.verf->verifier)) { | 181 | &res->commit_res.verf->verifier)) { |
| 182 | status = -EAGAIN; | 182 | status = -EAGAIN; |
| 183 | goto out; | 183 | goto out; |
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index 692a7a8bfc7a..66776f022111 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c | |||
| @@ -582,7 +582,6 @@ int nfs40_walk_client_list(struct nfs_client *new, | |||
| 582 | */ | 582 | */ |
| 583 | nfs4_schedule_path_down_recovery(pos); | 583 | nfs4_schedule_path_down_recovery(pos); |
| 584 | default: | 584 | default: |
| 585 | spin_lock(&nn->nfs_client_lock); | ||
| 586 | goto out; | 585 | goto out; |
| 587 | } | 586 | } |
| 588 | 587 | ||
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index adc6ec28d4b5..c383d0913b54 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
| @@ -2094,12 +2094,26 @@ pnfs_generic_pg_check_layout(struct nfs_pageio_descriptor *pgio) | |||
| 2094 | } | 2094 | } |
| 2095 | EXPORT_SYMBOL_GPL(pnfs_generic_pg_check_layout); | 2095 | EXPORT_SYMBOL_GPL(pnfs_generic_pg_check_layout); |
| 2096 | 2096 | ||
| 2097 | /* | ||
| 2098 | * Check for any intersection between the request and the pgio->pg_lseg, | ||
| 2099 | * and if none, put this pgio->pg_lseg away. | ||
| 2100 | */ | ||
| 2101 | static void | ||
| 2102 | pnfs_generic_pg_check_range(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) | ||
| 2103 | { | ||
| 2104 | if (pgio->pg_lseg && !pnfs_lseg_request_intersecting(pgio->pg_lseg, req)) { | ||
| 2105 | pnfs_put_lseg(pgio->pg_lseg); | ||
| 2106 | pgio->pg_lseg = NULL; | ||
| 2107 | } | ||
| 2108 | } | ||
| 2109 | |||
| 2097 | void | 2110 | void |
| 2098 | pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) | 2111 | pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) |
| 2099 | { | 2112 | { |
| 2100 | u64 rd_size = req->wb_bytes; | 2113 | u64 rd_size = req->wb_bytes; |
| 2101 | 2114 | ||
| 2102 | pnfs_generic_pg_check_layout(pgio); | 2115 | pnfs_generic_pg_check_layout(pgio); |
| 2116 | pnfs_generic_pg_check_range(pgio, req); | ||
| 2103 | if (pgio->pg_lseg == NULL) { | 2117 | if (pgio->pg_lseg == NULL) { |
| 2104 | if (pgio->pg_dreq == NULL) | 2118 | if (pgio->pg_dreq == NULL) |
| 2105 | rd_size = i_size_read(pgio->pg_inode) - req_offset(req); | 2119 | rd_size = i_size_read(pgio->pg_inode) - req_offset(req); |
| @@ -2131,6 +2145,7 @@ pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio, | |||
| 2131 | struct nfs_page *req, u64 wb_size) | 2145 | struct nfs_page *req, u64 wb_size) |
| 2132 | { | 2146 | { |
| 2133 | pnfs_generic_pg_check_layout(pgio); | 2147 | pnfs_generic_pg_check_layout(pgio); |
| 2148 | pnfs_generic_pg_check_range(pgio, req); | ||
| 2134 | if (pgio->pg_lseg == NULL) { | 2149 | if (pgio->pg_lseg == NULL) { |
| 2135 | pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, | 2150 | pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, |
| 2136 | req->wb_context, | 2151 | req->wb_context, |
| @@ -2191,16 +2206,10 @@ pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, | |||
| 2191 | seg_end = pnfs_end_offset(pgio->pg_lseg->pls_range.offset, | 2206 | seg_end = pnfs_end_offset(pgio->pg_lseg->pls_range.offset, |
| 2192 | pgio->pg_lseg->pls_range.length); | 2207 | pgio->pg_lseg->pls_range.length); |
| 2193 | req_start = req_offset(req); | 2208 | req_start = req_offset(req); |
| 2194 | WARN_ON_ONCE(req_start >= seg_end); | 2209 | |
| 2195 | /* start of request is past the last byte of this segment */ | 2210 | /* start of request is past the last byte of this segment */ |
| 2196 | if (req_start >= seg_end) { | 2211 | if (req_start >= seg_end) |
| 2197 | /* reference the new lseg */ | ||
| 2198 | if (pgio->pg_ops->pg_cleanup) | ||
| 2199 | pgio->pg_ops->pg_cleanup(pgio); | ||
| 2200 | if (pgio->pg_ops->pg_init) | ||
| 2201 | pgio->pg_ops->pg_init(pgio, req); | ||
| 2202 | return 0; | 2212 | return 0; |
| 2203 | } | ||
| 2204 | 2213 | ||
| 2205 | /* adjust 'size' iff there are fewer bytes left in the | 2214 | /* adjust 'size' iff there are fewer bytes left in the |
| 2206 | * segment than what nfs_generic_pg_test returned */ | 2215 | * segment than what nfs_generic_pg_test returned */ |
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 2d05b756a8d6..99731e3e332f 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h | |||
| @@ -593,6 +593,16 @@ pnfs_lseg_range_intersecting(const struct pnfs_layout_range *l1, | |||
| 593 | return pnfs_is_range_intersecting(l1->offset, end1, l2->offset, end2); | 593 | return pnfs_is_range_intersecting(l1->offset, end1, l2->offset, end2); |
| 594 | } | 594 | } |
| 595 | 595 | ||
| 596 | static inline bool | ||
| 597 | pnfs_lseg_request_intersecting(struct pnfs_layout_segment *lseg, struct nfs_page *req) | ||
| 598 | { | ||
| 599 | u64 seg_last = pnfs_end_offset(lseg->pls_range.offset, lseg->pls_range.length); | ||
| 600 | u64 req_last = req_offset(req) + req->wb_bytes; | ||
| 601 | |||
| 602 | return pnfs_is_range_intersecting(lseg->pls_range.offset, seg_last, | ||
| 603 | req_offset(req), req_last); | ||
| 604 | } | ||
| 605 | |||
| 596 | extern unsigned int layoutstats_timer; | 606 | extern unsigned int layoutstats_timer; |
| 597 | 607 | ||
| 598 | #ifdef NFS_DEBUG | 608 | #ifdef NFS_DEBUG |
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 2f3822a4a7d5..eceb4eabb064 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
| @@ -2301,7 +2301,7 @@ EXPORT_SYMBOL_GPL(nfs_remount); | |||
| 2301 | /* | 2301 | /* |
| 2302 | * Initialise the common bits of the superblock | 2302 | * Initialise the common bits of the superblock |
| 2303 | */ | 2303 | */ |
| 2304 | inline void nfs_initialise_sb(struct super_block *sb) | 2304 | static void nfs_initialise_sb(struct super_block *sb) |
| 2305 | { | 2305 | { |
| 2306 | struct nfs_server *server = NFS_SB(sb); | 2306 | struct nfs_server *server = NFS_SB(sb); |
| 2307 | 2307 | ||
| @@ -2348,7 +2348,8 @@ EXPORT_SYMBOL_GPL(nfs_fill_super); | |||
| 2348 | /* | 2348 | /* |
| 2349 | * Finish setting up a cloned NFS2/3/4 superblock | 2349 | * Finish setting up a cloned NFS2/3/4 superblock |
| 2350 | */ | 2350 | */ |
| 2351 | void nfs_clone_super(struct super_block *sb, struct nfs_mount_info *mount_info) | 2351 | static void nfs_clone_super(struct super_block *sb, |
| 2352 | struct nfs_mount_info *mount_info) | ||
| 2352 | { | 2353 | { |
| 2353 | const struct super_block *old_sb = mount_info->cloned->sb; | 2354 | const struct super_block *old_sb = mount_info->cloned->sb; |
| 2354 | struct nfs_server *server = NFS_SB(sb); | 2355 | struct nfs_server *server = NFS_SB(sb); |
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index ebf80c7739e1..48813aeaab80 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c | |||
| @@ -1512,6 +1512,22 @@ int dquot_initialize(struct inode *inode) | |||
| 1512 | } | 1512 | } |
| 1513 | EXPORT_SYMBOL(dquot_initialize); | 1513 | EXPORT_SYMBOL(dquot_initialize); |
| 1514 | 1514 | ||
| 1515 | bool dquot_initialize_needed(struct inode *inode) | ||
| 1516 | { | ||
| 1517 | struct dquot **dquots; | ||
| 1518 | int i; | ||
| 1519 | |||
| 1520 | if (!dquot_active(inode)) | ||
| 1521 | return false; | ||
| 1522 | |||
| 1523 | dquots = i_dquot(inode); | ||
| 1524 | for (i = 0; i < MAXQUOTAS; i++) | ||
| 1525 | if (!dquots[i] && sb_has_quota_active(inode->i_sb, i)) | ||
| 1526 | return true; | ||
| 1527 | return false; | ||
| 1528 | } | ||
| 1529 | EXPORT_SYMBOL(dquot_initialize_needed); | ||
| 1530 | |||
| 1515 | /* | 1531 | /* |
| 1516 | * Release all quotas referenced by inode. | 1532 | * Release all quotas referenced by inode. |
| 1517 | * | 1533 | * |
| @@ -672,6 +672,7 @@ void __inode_add_bytes(struct inode *inode, loff_t bytes) | |||
| 672 | inode->i_bytes -= 512; | 672 | inode->i_bytes -= 512; |
| 673 | } | 673 | } |
| 674 | } | 674 | } |
| 675 | EXPORT_SYMBOL(__inode_add_bytes); | ||
| 675 | 676 | ||
| 676 | void inode_add_bytes(struct inode *inode, loff_t bytes) | 677 | void inode_add_bytes(struct inode *inode, loff_t bytes) |
| 677 | { | 678 | { |
diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c index a0376a2c1c29..d642cc0a8271 100644 --- a/fs/ufs/balloc.c +++ b/fs/ufs/balloc.c | |||
| @@ -82,7 +82,8 @@ void ufs_free_fragments(struct inode *inode, u64 fragment, unsigned count) | |||
| 82 | ufs_error (sb, "ufs_free_fragments", | 82 | ufs_error (sb, "ufs_free_fragments", |
| 83 | "bit already cleared for fragment %u", i); | 83 | "bit already cleared for fragment %u", i); |
| 84 | } | 84 | } |
| 85 | 85 | ||
| 86 | inode_sub_bytes(inode, count << uspi->s_fshift); | ||
| 86 | fs32_add(sb, &ucg->cg_cs.cs_nffree, count); | 87 | fs32_add(sb, &ucg->cg_cs.cs_nffree, count); |
| 87 | uspi->cs_total.cs_nffree += count; | 88 | uspi->cs_total.cs_nffree += count; |
| 88 | fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, count); | 89 | fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, count); |
| @@ -184,6 +185,7 @@ do_more: | |||
| 184 | ufs_error(sb, "ufs_free_blocks", "freeing free fragment"); | 185 | ufs_error(sb, "ufs_free_blocks", "freeing free fragment"); |
| 185 | } | 186 | } |
| 186 | ubh_setblock(UCPI_UBH(ucpi), ucpi->c_freeoff, blkno); | 187 | ubh_setblock(UCPI_UBH(ucpi), ucpi->c_freeoff, blkno); |
| 188 | inode_sub_bytes(inode, uspi->s_fpb << uspi->s_fshift); | ||
| 187 | if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD) | 189 | if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD) |
| 188 | ufs_clusteracct (sb, ucpi, blkno, 1); | 190 | ufs_clusteracct (sb, ucpi, blkno, 1); |
| 189 | 191 | ||
| @@ -494,6 +496,20 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment, | |||
| 494 | return 0; | 496 | return 0; |
| 495 | } | 497 | } |
| 496 | 498 | ||
| 499 | static bool try_add_frags(struct inode *inode, unsigned frags) | ||
| 500 | { | ||
| 501 | unsigned size = frags * i_blocksize(inode); | ||
| 502 | spin_lock(&inode->i_lock); | ||
| 503 | __inode_add_bytes(inode, size); | ||
| 504 | if (unlikely((u32)inode->i_blocks != inode->i_blocks)) { | ||
| 505 | __inode_sub_bytes(inode, size); | ||
| 506 | spin_unlock(&inode->i_lock); | ||
| 507 | return false; | ||
| 508 | } | ||
| 509 | spin_unlock(&inode->i_lock); | ||
| 510 | return true; | ||
| 511 | } | ||
| 512 | |||
| 497 | static u64 ufs_add_fragments(struct inode *inode, u64 fragment, | 513 | static u64 ufs_add_fragments(struct inode *inode, u64 fragment, |
| 498 | unsigned oldcount, unsigned newcount) | 514 | unsigned oldcount, unsigned newcount) |
| 499 | { | 515 | { |
| @@ -530,6 +546,9 @@ static u64 ufs_add_fragments(struct inode *inode, u64 fragment, | |||
| 530 | for (i = oldcount; i < newcount; i++) | 546 | for (i = oldcount; i < newcount; i++) |
| 531 | if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_freeoff, fragno + i)) | 547 | if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_freeoff, fragno + i)) |
| 532 | return 0; | 548 | return 0; |
| 549 | |||
| 550 | if (!try_add_frags(inode, count)) | ||
| 551 | return 0; | ||
| 533 | /* | 552 | /* |
| 534 | * Block can be extended | 553 | * Block can be extended |
| 535 | */ | 554 | */ |
| @@ -647,6 +666,7 @@ cg_found: | |||
| 647 | ubh_setbit (UCPI_UBH(ucpi), ucpi->c_freeoff, goal + i); | 666 | ubh_setbit (UCPI_UBH(ucpi), ucpi->c_freeoff, goal + i); |
| 648 | i = uspi->s_fpb - count; | 667 | i = uspi->s_fpb - count; |
| 649 | 668 | ||
| 669 | inode_sub_bytes(inode, i << uspi->s_fshift); | ||
| 650 | fs32_add(sb, &ucg->cg_cs.cs_nffree, i); | 670 | fs32_add(sb, &ucg->cg_cs.cs_nffree, i); |
| 651 | uspi->cs_total.cs_nffree += i; | 671 | uspi->cs_total.cs_nffree += i; |
| 652 | fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, i); | 672 | fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, i); |
| @@ -657,6 +677,8 @@ cg_found: | |||
| 657 | result = ufs_bitmap_search (sb, ucpi, goal, allocsize); | 677 | result = ufs_bitmap_search (sb, ucpi, goal, allocsize); |
| 658 | if (result == INVBLOCK) | 678 | if (result == INVBLOCK) |
| 659 | return 0; | 679 | return 0; |
| 680 | if (!try_add_frags(inode, count)) | ||
| 681 | return 0; | ||
| 660 | for (i = 0; i < count; i++) | 682 | for (i = 0; i < count; i++) |
| 661 | ubh_clrbit (UCPI_UBH(ucpi), ucpi->c_freeoff, result + i); | 683 | ubh_clrbit (UCPI_UBH(ucpi), ucpi->c_freeoff, result + i); |
| 662 | 684 | ||
| @@ -716,6 +738,8 @@ norot: | |||
| 716 | return INVBLOCK; | 738 | return INVBLOCK; |
| 717 | ucpi->c_rotor = result; | 739 | ucpi->c_rotor = result; |
| 718 | gotit: | 740 | gotit: |
| 741 | if (!try_add_frags(inode, uspi->s_fpb)) | ||
| 742 | return 0; | ||
| 719 | blkno = ufs_fragstoblks(result); | 743 | blkno = ufs_fragstoblks(result); |
| 720 | ubh_clrblock (UCPI_UBH(ucpi), ucpi->c_freeoff, blkno); | 744 | ubh_clrblock (UCPI_UBH(ucpi), ucpi->c_freeoff, blkno); |
| 721 | if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD) | 745 | if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD) |
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index 7e41aee7b69a..da553ffec85b 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c | |||
| @@ -235,7 +235,8 @@ ufs_extend_tail(struct inode *inode, u64 writes_to, | |||
| 235 | 235 | ||
| 236 | p = ufs_get_direct_data_ptr(uspi, ufsi, block); | 236 | p = ufs_get_direct_data_ptr(uspi, ufsi, block); |
| 237 | tmp = ufs_new_fragments(inode, p, lastfrag, ufs_data_ptr_to_cpu(sb, p), | 237 | tmp = ufs_new_fragments(inode, p, lastfrag, ufs_data_ptr_to_cpu(sb, p), |
| 238 | new_size, err, locked_page); | 238 | new_size - (lastfrag & uspi->s_fpbmask), err, |
| 239 | locked_page); | ||
| 239 | return tmp != 0; | 240 | return tmp != 0; |
| 240 | } | 241 | } |
| 241 | 242 | ||
| @@ -284,7 +285,7 @@ ufs_inode_getfrag(struct inode *inode, unsigned index, | |||
| 284 | goal += uspi->s_fpb; | 285 | goal += uspi->s_fpb; |
| 285 | } | 286 | } |
| 286 | tmp = ufs_new_fragments(inode, p, ufs_blknum(new_fragment), | 287 | tmp = ufs_new_fragments(inode, p, ufs_blknum(new_fragment), |
| 287 | goal, uspi->s_fpb, err, locked_page); | 288 | goal, nfrags, err, locked_page); |
| 288 | 289 | ||
| 289 | if (!tmp) { | 290 | if (!tmp) { |
| 290 | *err = -ENOSPC; | 291 | *err = -ENOSPC; |
| @@ -402,7 +403,9 @@ static int ufs_getfrag_block(struct inode *inode, sector_t fragment, struct buff | |||
| 402 | 403 | ||
| 403 | if (!create) { | 404 | if (!create) { |
| 404 | phys64 = ufs_frag_map(inode, offsets, depth); | 405 | phys64 = ufs_frag_map(inode, offsets, depth); |
| 405 | goto out; | 406 | if (phys64) |
| 407 | map_bh(bh_result, sb, phys64 + frag); | ||
| 408 | return 0; | ||
| 406 | } | 409 | } |
| 407 | 410 | ||
| 408 | /* This code entered only while writing ....? */ | 411 | /* This code entered only while writing ....? */ |
| @@ -841,8 +844,11 @@ void ufs_evict_inode(struct inode * inode) | |||
| 841 | truncate_inode_pages_final(&inode->i_data); | 844 | truncate_inode_pages_final(&inode->i_data); |
| 842 | if (want_delete) { | 845 | if (want_delete) { |
| 843 | inode->i_size = 0; | 846 | inode->i_size = 0; |
| 844 | if (inode->i_blocks) | 847 | if (inode->i_blocks && |
| 848 | (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || | ||
| 849 | S_ISLNK(inode->i_mode))) | ||
| 845 | ufs_truncate_blocks(inode); | 850 | ufs_truncate_blocks(inode); |
| 851 | ufs_update_inode(inode, inode_needs_sync(inode)); | ||
| 846 | } | 852 | } |
| 847 | 853 | ||
| 848 | invalidate_inode_buffers(inode); | 854 | invalidate_inode_buffers(inode); |
| @@ -1100,7 +1106,7 @@ out: | |||
| 1100 | return err; | 1106 | return err; |
| 1101 | } | 1107 | } |
| 1102 | 1108 | ||
| 1103 | static void __ufs_truncate_blocks(struct inode *inode) | 1109 | static void ufs_truncate_blocks(struct inode *inode) |
| 1104 | { | 1110 | { |
| 1105 | struct ufs_inode_info *ufsi = UFS_I(inode); | 1111 | struct ufs_inode_info *ufsi = UFS_I(inode); |
| 1106 | struct super_block *sb = inode->i_sb; | 1112 | struct super_block *sb = inode->i_sb; |
| @@ -1183,7 +1189,7 @@ static int ufs_truncate(struct inode *inode, loff_t size) | |||
| 1183 | 1189 | ||
| 1184 | truncate_setsize(inode, size); | 1190 | truncate_setsize(inode, size); |
| 1185 | 1191 | ||
| 1186 | __ufs_truncate_blocks(inode); | 1192 | ufs_truncate_blocks(inode); |
| 1187 | inode->i_mtime = inode->i_ctime = current_time(inode); | 1193 | inode->i_mtime = inode->i_ctime = current_time(inode); |
| 1188 | mark_inode_dirty(inode); | 1194 | mark_inode_dirty(inode); |
| 1189 | out: | 1195 | out: |
| @@ -1191,16 +1197,6 @@ out: | |||
| 1191 | return err; | 1197 | return err; |
| 1192 | } | 1198 | } |
| 1193 | 1199 | ||
| 1194 | static void ufs_truncate_blocks(struct inode *inode) | ||
| 1195 | { | ||
| 1196 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || | ||
| 1197 | S_ISLNK(inode->i_mode))) | ||
| 1198 | return; | ||
| 1199 | if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) | ||
| 1200 | return; | ||
| 1201 | __ufs_truncate_blocks(inode); | ||
| 1202 | } | ||
| 1203 | |||
| 1204 | int ufs_setattr(struct dentry *dentry, struct iattr *attr) | 1200 | int ufs_setattr(struct dentry *dentry, struct iattr *attr) |
| 1205 | { | 1201 | { |
| 1206 | struct inode *inode = d_inode(dentry); | 1202 | struct inode *inode = d_inode(dentry); |
diff --git a/fs/ufs/super.c b/fs/ufs/super.c index 131b2b77c818..878cc6264f1a 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c | |||
| @@ -746,6 +746,23 @@ static void ufs_put_super(struct super_block *sb) | |||
| 746 | return; | 746 | return; |
| 747 | } | 747 | } |
| 748 | 748 | ||
| 749 | static u64 ufs_max_bytes(struct super_block *sb) | ||
| 750 | { | ||
| 751 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; | ||
| 752 | int bits = uspi->s_apbshift; | ||
| 753 | u64 res; | ||
| 754 | |||
| 755 | if (bits > 21) | ||
| 756 | res = ~0ULL; | ||
| 757 | else | ||
| 758 | res = UFS_NDADDR + (1LL << bits) + (1LL << (2*bits)) + | ||
| 759 | (1LL << (3*bits)); | ||
| 760 | |||
| 761 | if (res >= (MAX_LFS_FILESIZE >> uspi->s_bshift)) | ||
| 762 | return MAX_LFS_FILESIZE; | ||
| 763 | return res << uspi->s_bshift; | ||
| 764 | } | ||
| 765 | |||
| 749 | static int ufs_fill_super(struct super_block *sb, void *data, int silent) | 766 | static int ufs_fill_super(struct super_block *sb, void *data, int silent) |
| 750 | { | 767 | { |
| 751 | struct ufs_sb_info * sbi; | 768 | struct ufs_sb_info * sbi; |
| @@ -812,9 +829,8 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) | |||
| 812 | uspi->s_dirblksize = UFS_SECTOR_SIZE; | 829 | uspi->s_dirblksize = UFS_SECTOR_SIZE; |
| 813 | super_block_offset=UFS_SBLOCK; | 830 | super_block_offset=UFS_SBLOCK; |
| 814 | 831 | ||
| 815 | /* Keep 2Gig file limit. Some UFS variants need to override | 832 | sb->s_maxbytes = MAX_LFS_FILESIZE; |
| 816 | this but as I don't know which I'll let those in the know loosen | 833 | |
| 817 | the rules */ | ||
| 818 | switch (sbi->s_mount_opt & UFS_MOUNT_UFSTYPE) { | 834 | switch (sbi->s_mount_opt & UFS_MOUNT_UFSTYPE) { |
| 819 | case UFS_MOUNT_UFSTYPE_44BSD: | 835 | case UFS_MOUNT_UFSTYPE_44BSD: |
| 820 | UFSD("ufstype=44bsd\n"); | 836 | UFSD("ufstype=44bsd\n"); |
| @@ -1212,6 +1228,7 @@ magic_found: | |||
| 1212 | "fast symlink size (%u)\n", uspi->s_maxsymlinklen); | 1228 | "fast symlink size (%u)\n", uspi->s_maxsymlinklen); |
| 1213 | uspi->s_maxsymlinklen = maxsymlen; | 1229 | uspi->s_maxsymlinklen = maxsymlen; |
| 1214 | } | 1230 | } |
| 1231 | sb->s_maxbytes = ufs_max_bytes(sb); | ||
| 1215 | sb->s_max_links = UFS_LINK_MAX; | 1232 | sb->s_max_links = UFS_LINK_MAX; |
| 1216 | 1233 | ||
| 1217 | inode = ufs_iget(sb, UFS_ROOTINO); | 1234 | inode = ufs_iget(sb, UFS_ROOTINO); |
diff --git a/fs/ufs/util.h b/fs/ufs/util.h index b7fbf53dbc81..398019fb1448 100644 --- a/fs/ufs/util.h +++ b/fs/ufs/util.h | |||
| @@ -473,15 +473,19 @@ static inline unsigned _ubh_find_last_zero_bit_( | |||
| 473 | static inline int _ubh_isblockset_(struct ufs_sb_private_info * uspi, | 473 | static inline int _ubh_isblockset_(struct ufs_sb_private_info * uspi, |
| 474 | struct ufs_buffer_head * ubh, unsigned begin, unsigned block) | 474 | struct ufs_buffer_head * ubh, unsigned begin, unsigned block) |
| 475 | { | 475 | { |
| 476 | u8 mask; | ||
| 476 | switch (uspi->s_fpb) { | 477 | switch (uspi->s_fpb) { |
| 477 | case 8: | 478 | case 8: |
| 478 | return (*ubh_get_addr (ubh, begin + block) == 0xff); | 479 | return (*ubh_get_addr (ubh, begin + block) == 0xff); |
| 479 | case 4: | 480 | case 4: |
| 480 | return (*ubh_get_addr (ubh, begin + (block >> 1)) == (0x0f << ((block & 0x01) << 2))); | 481 | mask = 0x0f << ((block & 0x01) << 2); |
| 482 | return (*ubh_get_addr (ubh, begin + (block >> 1)) & mask) == mask; | ||
| 481 | case 2: | 483 | case 2: |
| 482 | return (*ubh_get_addr (ubh, begin + (block >> 2)) == (0x03 << ((block & 0x03) << 1))); | 484 | mask = 0x03 << ((block & 0x03) << 1); |
| 485 | return (*ubh_get_addr (ubh, begin + (block >> 2)) & mask) == mask; | ||
| 483 | case 1: | 486 | case 1: |
| 484 | return (*ubh_get_addr (ubh, begin + (block >> 3)) == (0x01 << (block & 0x07))); | 487 | mask = 0x01 << (block & 0x07); |
| 488 | return (*ubh_get_addr (ubh, begin + (block >> 3)) & mask) == mask; | ||
| 485 | } | 489 | } |
| 486 | return 0; | 490 | return 0; |
| 487 | } | 491 | } |
diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index 62fa39276a24..07b77b73b024 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c | |||
| @@ -97,12 +97,16 @@ static inline void | |||
| 97 | xfs_buf_ioacct_inc( | 97 | xfs_buf_ioacct_inc( |
| 98 | struct xfs_buf *bp) | 98 | struct xfs_buf *bp) |
| 99 | { | 99 | { |
| 100 | if (bp->b_flags & (XBF_NO_IOACCT|_XBF_IN_FLIGHT)) | 100 | if (bp->b_flags & XBF_NO_IOACCT) |
| 101 | return; | 101 | return; |
| 102 | 102 | ||
| 103 | ASSERT(bp->b_flags & XBF_ASYNC); | 103 | ASSERT(bp->b_flags & XBF_ASYNC); |
| 104 | bp->b_flags |= _XBF_IN_FLIGHT; | 104 | spin_lock(&bp->b_lock); |
| 105 | percpu_counter_inc(&bp->b_target->bt_io_count); | 105 | if (!(bp->b_state & XFS_BSTATE_IN_FLIGHT)) { |
| 106 | bp->b_state |= XFS_BSTATE_IN_FLIGHT; | ||
| 107 | percpu_counter_inc(&bp->b_target->bt_io_count); | ||
| 108 | } | ||
| 109 | spin_unlock(&bp->b_lock); | ||
| 106 | } | 110 | } |
| 107 | 111 | ||
| 108 | /* | 112 | /* |
| @@ -110,14 +114,24 @@ xfs_buf_ioacct_inc( | |||
| 110 | * freed and unaccount from the buftarg. | 114 | * freed and unaccount from the buftarg. |
| 111 | */ | 115 | */ |
| 112 | static inline void | 116 | static inline void |
| 113 | xfs_buf_ioacct_dec( | 117 | __xfs_buf_ioacct_dec( |
| 114 | struct xfs_buf *bp) | 118 | struct xfs_buf *bp) |
| 115 | { | 119 | { |
| 116 | if (!(bp->b_flags & _XBF_IN_FLIGHT)) | 120 | ASSERT(spin_is_locked(&bp->b_lock)); |
| 117 | return; | ||
| 118 | 121 | ||
| 119 | bp->b_flags &= ~_XBF_IN_FLIGHT; | 122 | if (bp->b_state & XFS_BSTATE_IN_FLIGHT) { |
| 120 | percpu_counter_dec(&bp->b_target->bt_io_count); | 123 | bp->b_state &= ~XFS_BSTATE_IN_FLIGHT; |
| 124 | percpu_counter_dec(&bp->b_target->bt_io_count); | ||
| 125 | } | ||
| 126 | } | ||
| 127 | |||
| 128 | static inline void | ||
| 129 | xfs_buf_ioacct_dec( | ||
| 130 | struct xfs_buf *bp) | ||
| 131 | { | ||
| 132 | spin_lock(&bp->b_lock); | ||
| 133 | __xfs_buf_ioacct_dec(bp); | ||
| 134 | spin_unlock(&bp->b_lock); | ||
| 121 | } | 135 | } |
| 122 | 136 | ||
| 123 | /* | 137 | /* |
| @@ -149,9 +163,9 @@ xfs_buf_stale( | |||
| 149 | * unaccounted (released to LRU) before that occurs. Drop in-flight | 163 | * unaccounted (released to LRU) before that occurs. Drop in-flight |
| 150 | * status now to preserve accounting consistency. | 164 | * status now to preserve accounting consistency. |
| 151 | */ | 165 | */ |
| 152 | xfs_buf_ioacct_dec(bp); | ||
| 153 | |||
| 154 | spin_lock(&bp->b_lock); | 166 | spin_lock(&bp->b_lock); |
| 167 | __xfs_buf_ioacct_dec(bp); | ||
| 168 | |||
| 155 | atomic_set(&bp->b_lru_ref, 0); | 169 | atomic_set(&bp->b_lru_ref, 0); |
| 156 | if (!(bp->b_state & XFS_BSTATE_DISPOSE) && | 170 | if (!(bp->b_state & XFS_BSTATE_DISPOSE) && |
| 157 | (list_lru_del(&bp->b_target->bt_lru, &bp->b_lru))) | 171 | (list_lru_del(&bp->b_target->bt_lru, &bp->b_lru))) |
| @@ -979,12 +993,12 @@ xfs_buf_rele( | |||
| 979 | * ensures the decrement occurs only once per-buf. | 993 | * ensures the decrement occurs only once per-buf. |
| 980 | */ | 994 | */ |
| 981 | if ((atomic_read(&bp->b_hold) == 1) && !list_empty(&bp->b_lru)) | 995 | if ((atomic_read(&bp->b_hold) == 1) && !list_empty(&bp->b_lru)) |
| 982 | xfs_buf_ioacct_dec(bp); | 996 | __xfs_buf_ioacct_dec(bp); |
| 983 | goto out_unlock; | 997 | goto out_unlock; |
| 984 | } | 998 | } |
| 985 | 999 | ||
| 986 | /* the last reference has been dropped ... */ | 1000 | /* the last reference has been dropped ... */ |
| 987 | xfs_buf_ioacct_dec(bp); | 1001 | __xfs_buf_ioacct_dec(bp); |
| 988 | if (!(bp->b_flags & XBF_STALE) && atomic_read(&bp->b_lru_ref)) { | 1002 | if (!(bp->b_flags & XBF_STALE) && atomic_read(&bp->b_lru_ref)) { |
| 989 | /* | 1003 | /* |
| 990 | * If the buffer is added to the LRU take a new reference to the | 1004 | * If the buffer is added to the LRU take a new reference to the |
diff --git a/fs/xfs/xfs_buf.h b/fs/xfs/xfs_buf.h index 8d1d44f87ce9..1508121f29f2 100644 --- a/fs/xfs/xfs_buf.h +++ b/fs/xfs/xfs_buf.h | |||
| @@ -63,7 +63,6 @@ typedef enum { | |||
| 63 | #define _XBF_KMEM (1 << 21)/* backed by heap memory */ | 63 | #define _XBF_KMEM (1 << 21)/* backed by heap memory */ |
| 64 | #define _XBF_DELWRI_Q (1 << 22)/* buffer on a delwri queue */ | 64 | #define _XBF_DELWRI_Q (1 << 22)/* buffer on a delwri queue */ |
| 65 | #define _XBF_COMPOUND (1 << 23)/* compound buffer */ | 65 | #define _XBF_COMPOUND (1 << 23)/* compound buffer */ |
| 66 | #define _XBF_IN_FLIGHT (1 << 25) /* I/O in flight, for accounting purposes */ | ||
| 67 | 66 | ||
| 68 | typedef unsigned int xfs_buf_flags_t; | 67 | typedef unsigned int xfs_buf_flags_t; |
| 69 | 68 | ||
| @@ -84,14 +83,14 @@ typedef unsigned int xfs_buf_flags_t; | |||
| 84 | { _XBF_PAGES, "PAGES" }, \ | 83 | { _XBF_PAGES, "PAGES" }, \ |
| 85 | { _XBF_KMEM, "KMEM" }, \ | 84 | { _XBF_KMEM, "KMEM" }, \ |
| 86 | { _XBF_DELWRI_Q, "DELWRI_Q" }, \ | 85 | { _XBF_DELWRI_Q, "DELWRI_Q" }, \ |
| 87 | { _XBF_COMPOUND, "COMPOUND" }, \ | 86 | { _XBF_COMPOUND, "COMPOUND" } |
| 88 | { _XBF_IN_FLIGHT, "IN_FLIGHT" } | ||
| 89 | 87 | ||
| 90 | 88 | ||
| 91 | /* | 89 | /* |
| 92 | * Internal state flags. | 90 | * Internal state flags. |
| 93 | */ | 91 | */ |
| 94 | #define XFS_BSTATE_DISPOSE (1 << 0) /* buffer being discarded */ | 92 | #define XFS_BSTATE_DISPOSE (1 << 0) /* buffer being discarded */ |
| 93 | #define XFS_BSTATE_IN_FLIGHT (1 << 1) /* I/O in flight */ | ||
| 95 | 94 | ||
| 96 | /* | 95 | /* |
| 97 | * The xfs_buftarg contains 2 notions of "sector size" - | 96 | * The xfs_buftarg contains 2 notions of "sector size" - |
