diff options
Diffstat (limited to 'fs')
46 files changed, 457 insertions, 214 deletions
diff --git a/fs/bio-integrity.c b/fs/bio-integrity.c index 0bad24ddc2e7..0129b78a6908 100644 --- a/fs/bio-integrity.c +++ b/fs/bio-integrity.c | |||
@@ -114,6 +114,14 @@ void bio_integrity_free(struct bio *bio) | |||
114 | } | 114 | } |
115 | EXPORT_SYMBOL(bio_integrity_free); | 115 | EXPORT_SYMBOL(bio_integrity_free); |
116 | 116 | ||
117 | static inline unsigned int bip_integrity_vecs(struct bio_integrity_payload *bip) | ||
118 | { | ||
119 | if (bip->bip_slab == BIO_POOL_NONE) | ||
120 | return BIP_INLINE_VECS; | ||
121 | |||
122 | return bvec_nr_vecs(bip->bip_slab); | ||
123 | } | ||
124 | |||
117 | /** | 125 | /** |
118 | * bio_integrity_add_page - Attach integrity metadata | 126 | * bio_integrity_add_page - Attach integrity metadata |
119 | * @bio: bio to update | 127 | * @bio: bio to update |
@@ -129,7 +137,7 @@ int bio_integrity_add_page(struct bio *bio, struct page *page, | |||
129 | struct bio_integrity_payload *bip = bio->bi_integrity; | 137 | struct bio_integrity_payload *bip = bio->bi_integrity; |
130 | struct bio_vec *iv; | 138 | struct bio_vec *iv; |
131 | 139 | ||
132 | if (bip->bip_vcnt >= bvec_nr_vecs(bip->bip_slab)) { | 140 | if (bip->bip_vcnt >= bip_integrity_vecs(bip)) { |
133 | printk(KERN_ERR "%s: bip_vec full\n", __func__); | 141 | printk(KERN_ERR "%s: bip_vec full\n", __func__); |
134 | return 0; | 142 | return 0; |
135 | } | 143 | } |
@@ -226,7 +234,8 @@ unsigned int bio_integrity_tag_size(struct bio *bio) | |||
226 | } | 234 | } |
227 | EXPORT_SYMBOL(bio_integrity_tag_size); | 235 | EXPORT_SYMBOL(bio_integrity_tag_size); |
228 | 236 | ||
229 | int bio_integrity_tag(struct bio *bio, void *tag_buf, unsigned int len, int set) | 237 | static int bio_integrity_tag(struct bio *bio, void *tag_buf, unsigned int len, |
238 | int set) | ||
230 | { | 239 | { |
231 | struct bio_integrity_payload *bip = bio->bi_integrity; | 240 | struct bio_integrity_payload *bip = bio->bi_integrity; |
232 | struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev); | 241 | struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev); |
@@ -611,7 +611,6 @@ EXPORT_SYMBOL(bio_clone_fast); | |||
611 | struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask, | 611 | struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask, |
612 | struct bio_set *bs) | 612 | struct bio_set *bs) |
613 | { | 613 | { |
614 | unsigned nr_iovecs = 0; | ||
615 | struct bvec_iter iter; | 614 | struct bvec_iter iter; |
616 | struct bio_vec bv; | 615 | struct bio_vec bv; |
617 | struct bio *bio; | 616 | struct bio *bio; |
@@ -638,10 +637,7 @@ struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask, | |||
638 | * __bio_clone_fast() anyways. | 637 | * __bio_clone_fast() anyways. |
639 | */ | 638 | */ |
640 | 639 | ||
641 | bio_for_each_segment(bv, bio_src, iter) | 640 | bio = bio_alloc_bioset(gfp_mask, bio_segments(bio_src), bs); |
642 | nr_iovecs++; | ||
643 | |||
644 | bio = bio_alloc_bioset(gfp_mask, nr_iovecs, bs); | ||
645 | if (!bio) | 641 | if (!bio) |
646 | return NULL; | 642 | return NULL; |
647 | 643 | ||
@@ -650,9 +646,18 @@ struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask, | |||
650 | bio->bi_iter.bi_sector = bio_src->bi_iter.bi_sector; | 646 | bio->bi_iter.bi_sector = bio_src->bi_iter.bi_sector; |
651 | bio->bi_iter.bi_size = bio_src->bi_iter.bi_size; | 647 | bio->bi_iter.bi_size = bio_src->bi_iter.bi_size; |
652 | 648 | ||
649 | if (bio->bi_rw & REQ_DISCARD) | ||
650 | goto integrity_clone; | ||
651 | |||
652 | if (bio->bi_rw & REQ_WRITE_SAME) { | ||
653 | bio->bi_io_vec[bio->bi_vcnt++] = bio_src->bi_io_vec[0]; | ||
654 | goto integrity_clone; | ||
655 | } | ||
656 | |||
653 | bio_for_each_segment(bv, bio_src, iter) | 657 | bio_for_each_segment(bv, bio_src, iter) |
654 | bio->bi_io_vec[bio->bi_vcnt++] = bv; | 658 | bio->bi_io_vec[bio->bi_vcnt++] = bv; |
655 | 659 | ||
660 | integrity_clone: | ||
656 | if (bio_integrity(bio_src)) { | 661 | if (bio_integrity(bio_src)) { |
657 | int ret; | 662 | int ret; |
658 | 663 | ||
diff --git a/fs/btrfs/check-integrity.c b/fs/btrfs/check-integrity.c index 49a62b4dda3b..0e8388e72d8d 100644 --- a/fs/btrfs/check-integrity.c +++ b/fs/btrfs/check-integrity.c | |||
@@ -92,11 +92,11 @@ | |||
92 | #include <linux/slab.h> | 92 | #include <linux/slab.h> |
93 | #include <linux/buffer_head.h> | 93 | #include <linux/buffer_head.h> |
94 | #include <linux/mutex.h> | 94 | #include <linux/mutex.h> |
95 | #include <linux/crc32c.h> | ||
96 | #include <linux/genhd.h> | 95 | #include <linux/genhd.h> |
97 | #include <linux/blkdev.h> | 96 | #include <linux/blkdev.h> |
98 | #include "ctree.h" | 97 | #include "ctree.h" |
99 | #include "disk-io.h" | 98 | #include "disk-io.h" |
99 | #include "hash.h" | ||
100 | #include "transaction.h" | 100 | #include "transaction.h" |
101 | #include "extent_io.h" | 101 | #include "extent_io.h" |
102 | #include "volumes.h" | 102 | #include "volumes.h" |
@@ -1823,7 +1823,7 @@ static int btrfsic_test_for_metadata(struct btrfsic_state *state, | |||
1823 | size_t sublen = i ? PAGE_CACHE_SIZE : | 1823 | size_t sublen = i ? PAGE_CACHE_SIZE : |
1824 | (PAGE_CACHE_SIZE - BTRFS_CSUM_SIZE); | 1824 | (PAGE_CACHE_SIZE - BTRFS_CSUM_SIZE); |
1825 | 1825 | ||
1826 | crc = crc32c(crc, data, sublen); | 1826 | crc = btrfs_crc32c(crc, data, sublen); |
1827 | } | 1827 | } |
1828 | btrfs_csum_final(crc, csum); | 1828 | btrfs_csum_final(crc, csum); |
1829 | if (memcmp(csum, h->csum, state->csum_size)) | 1829 | if (memcmp(csum, h->csum, state->csum_size)) |
diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c index e2600cdb6c25..b01fb6c527e3 100644 --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c | |||
@@ -1010,6 +1010,8 @@ int btrfs_decompress_buf2page(char *buf, unsigned long buf_start, | |||
1010 | bytes = min(bytes, working_bytes); | 1010 | bytes = min(bytes, working_bytes); |
1011 | kaddr = kmap_atomic(page_out); | 1011 | kaddr = kmap_atomic(page_out); |
1012 | memcpy(kaddr + *pg_offset, buf + buf_offset, bytes); | 1012 | memcpy(kaddr + *pg_offset, buf + buf_offset, bytes); |
1013 | if (*pg_index == (vcnt - 1) && *pg_offset == 0) | ||
1014 | memset(kaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); | ||
1013 | kunmap_atomic(kaddr); | 1015 | kunmap_atomic(kaddr); |
1014 | flush_dcache_page(page_out); | 1016 | flush_dcache_page(page_out); |
1015 | 1017 | ||
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 0e69295d0031..81ea55314b1f 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #include <linux/workqueue.h> | 26 | #include <linux/workqueue.h> |
27 | #include <linux/kthread.h> | 27 | #include <linux/kthread.h> |
28 | #include <linux/freezer.h> | 28 | #include <linux/freezer.h> |
29 | #include <linux/crc32c.h> | ||
30 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
31 | #include <linux/migrate.h> | 30 | #include <linux/migrate.h> |
32 | #include <linux/ratelimit.h> | 31 | #include <linux/ratelimit.h> |
@@ -35,6 +34,7 @@ | |||
35 | #include <asm/unaligned.h> | 34 | #include <asm/unaligned.h> |
36 | #include "ctree.h" | 35 | #include "ctree.h" |
37 | #include "disk-io.h" | 36 | #include "disk-io.h" |
37 | #include "hash.h" | ||
38 | #include "transaction.h" | 38 | #include "transaction.h" |
39 | #include "btrfs_inode.h" | 39 | #include "btrfs_inode.h" |
40 | #include "volumes.h" | 40 | #include "volumes.h" |
@@ -244,7 +244,7 @@ out: | |||
244 | 244 | ||
245 | u32 btrfs_csum_data(char *data, u32 seed, size_t len) | 245 | u32 btrfs_csum_data(char *data, u32 seed, size_t len) |
246 | { | 246 | { |
247 | return crc32c(seed, data, len); | 247 | return btrfs_crc32c(seed, data, len); |
248 | } | 248 | } |
249 | 249 | ||
250 | void btrfs_csum_final(u32 crc, char *result) | 250 | void btrfs_csum_final(u32 crc, char *result) |
@@ -3839,7 +3839,6 @@ static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans, | |||
3839 | rb_erase(&ref->rb_node, &head->ref_root); | 3839 | rb_erase(&ref->rb_node, &head->ref_root); |
3840 | atomic_dec(&delayed_refs->num_entries); | 3840 | atomic_dec(&delayed_refs->num_entries); |
3841 | btrfs_put_delayed_ref(ref); | 3841 | btrfs_put_delayed_ref(ref); |
3842 | cond_resched_lock(&head->lock); | ||
3843 | } | 3842 | } |
3844 | if (head->must_insert_reserved) | 3843 | if (head->must_insert_reserved) |
3845 | pin_bytes = true; | 3844 | pin_bytes = true; |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 9c9ecc93ae2c..32312e09f0f5 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -2385,6 +2385,7 @@ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, | |||
2385 | spin_unlock(&delayed_refs->lock); | 2385 | spin_unlock(&delayed_refs->lock); |
2386 | locked_ref = NULL; | 2386 | locked_ref = NULL; |
2387 | cond_resched(); | 2387 | cond_resched(); |
2388 | count++; | ||
2388 | continue; | 2389 | continue; |
2389 | } | 2390 | } |
2390 | 2391 | ||
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 5c4ab9c18940..d3d44486290b 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -2629,7 +2629,7 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent) | |||
2629 | EXTENT_DEFRAG, 1, cached_state); | 2629 | EXTENT_DEFRAG, 1, cached_state); |
2630 | if (ret) { | 2630 | if (ret) { |
2631 | u64 last_snapshot = btrfs_root_last_snapshot(&root->root_item); | 2631 | u64 last_snapshot = btrfs_root_last_snapshot(&root->root_item); |
2632 | if (last_snapshot >= BTRFS_I(inode)->generation) | 2632 | if (0 && last_snapshot >= BTRFS_I(inode)->generation) |
2633 | /* the inode is shared */ | 2633 | /* the inode is shared */ |
2634 | new = record_old_file_extents(inode, ordered_extent); | 2634 | new = record_old_file_extents(inode, ordered_extent); |
2635 | 2635 | ||
@@ -5154,7 +5154,7 @@ static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry, | |||
5154 | return ERR_CAST(inode); | 5154 | return ERR_CAST(inode); |
5155 | } | 5155 | } |
5156 | 5156 | ||
5157 | return d_splice_alias(inode, dentry); | 5157 | return d_materialise_unique(dentry, inode); |
5158 | } | 5158 | } |
5159 | 5159 | ||
5160 | unsigned char btrfs_filetype_table[] = { | 5160 | unsigned char btrfs_filetype_table[] = { |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index b0134892dc70..a6d8efa46bfe 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -3537,20 +3537,6 @@ out: | |||
3537 | return ret; | 3537 | return ret; |
3538 | } | 3538 | } |
3539 | 3539 | ||
3540 | static long btrfs_ioctl_global_rsv(struct btrfs_root *root, void __user *arg) | ||
3541 | { | ||
3542 | struct btrfs_block_rsv *block_rsv = &root->fs_info->global_block_rsv; | ||
3543 | u64 reserved; | ||
3544 | |||
3545 | spin_lock(&block_rsv->lock); | ||
3546 | reserved = block_rsv->reserved; | ||
3547 | spin_unlock(&block_rsv->lock); | ||
3548 | |||
3549 | if (arg && copy_to_user(arg, &reserved, sizeof(reserved))) | ||
3550 | return -EFAULT; | ||
3551 | return 0; | ||
3552 | } | ||
3553 | |||
3554 | /* | 3540 | /* |
3555 | * there are many ways the trans_start and trans_end ioctls can lead | 3541 | * there are many ways the trans_start and trans_end ioctls can lead |
3556 | * to deadlocks. They should only be used by applications that | 3542 | * to deadlocks. They should only be used by applications that |
@@ -4525,7 +4511,7 @@ static int btrfs_ioctl_set_fslabel(struct file *file, void __user *arg) | |||
4525 | spin_lock(&root->fs_info->super_lock); | 4511 | spin_lock(&root->fs_info->super_lock); |
4526 | strcpy(super_block->label, label); | 4512 | strcpy(super_block->label, label); |
4527 | spin_unlock(&root->fs_info->super_lock); | 4513 | spin_unlock(&root->fs_info->super_lock); |
4528 | ret = btrfs_end_transaction(trans, root); | 4514 | ret = btrfs_commit_transaction(trans, root); |
4529 | 4515 | ||
4530 | out_unlock: | 4516 | out_unlock: |
4531 | mnt_drop_write_file(file); | 4517 | mnt_drop_write_file(file); |
@@ -4668,7 +4654,7 @@ static int btrfs_ioctl_set_features(struct file *file, void __user *arg) | |||
4668 | if (ret) | 4654 | if (ret) |
4669 | return ret; | 4655 | return ret; |
4670 | 4656 | ||
4671 | trans = btrfs_start_transaction(root, 1); | 4657 | trans = btrfs_start_transaction(root, 0); |
4672 | if (IS_ERR(trans)) | 4658 | if (IS_ERR(trans)) |
4673 | return PTR_ERR(trans); | 4659 | return PTR_ERR(trans); |
4674 | 4660 | ||
@@ -4689,7 +4675,7 @@ static int btrfs_ioctl_set_features(struct file *file, void __user *arg) | |||
4689 | btrfs_set_super_incompat_flags(super_block, newflags); | 4675 | btrfs_set_super_incompat_flags(super_block, newflags); |
4690 | spin_unlock(&root->fs_info->super_lock); | 4676 | spin_unlock(&root->fs_info->super_lock); |
4691 | 4677 | ||
4692 | return btrfs_end_transaction(trans, root); | 4678 | return btrfs_commit_transaction(trans, root); |
4693 | } | 4679 | } |
4694 | 4680 | ||
4695 | long btrfs_ioctl(struct file *file, unsigned int | 4681 | long btrfs_ioctl(struct file *file, unsigned int |
@@ -4757,8 +4743,6 @@ long btrfs_ioctl(struct file *file, unsigned int | |||
4757 | return btrfs_ioctl_logical_to_ino(root, argp); | 4743 | return btrfs_ioctl_logical_to_ino(root, argp); |
4758 | case BTRFS_IOC_SPACE_INFO: | 4744 | case BTRFS_IOC_SPACE_INFO: |
4759 | return btrfs_ioctl_space_info(root, argp); | 4745 | return btrfs_ioctl_space_info(root, argp); |
4760 | case BTRFS_IOC_GLOBAL_RSV: | ||
4761 | return btrfs_ioctl_global_rsv(root, argp); | ||
4762 | case BTRFS_IOC_SYNC: { | 4746 | case BTRFS_IOC_SYNC: { |
4763 | int ret; | 4747 | int ret; |
4764 | 4748 | ||
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index 730dce395858..9dde9717c1b9 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c | |||
@@ -24,12 +24,12 @@ | |||
24 | #include <linux/xattr.h> | 24 | #include <linux/xattr.h> |
25 | #include <linux/posix_acl_xattr.h> | 25 | #include <linux/posix_acl_xattr.h> |
26 | #include <linux/radix-tree.h> | 26 | #include <linux/radix-tree.h> |
27 | #include <linux/crc32c.h> | ||
28 | #include <linux/vmalloc.h> | 27 | #include <linux/vmalloc.h> |
29 | #include <linux/string.h> | 28 | #include <linux/string.h> |
30 | 29 | ||
31 | #include "send.h" | 30 | #include "send.h" |
32 | #include "backref.h" | 31 | #include "backref.h" |
32 | #include "hash.h" | ||
33 | #include "locking.h" | 33 | #include "locking.h" |
34 | #include "disk-io.h" | 34 | #include "disk-io.h" |
35 | #include "btrfs_inode.h" | 35 | #include "btrfs_inode.h" |
@@ -620,7 +620,7 @@ static int send_cmd(struct send_ctx *sctx) | |||
620 | hdr->len = cpu_to_le32(sctx->send_size - sizeof(*hdr)); | 620 | hdr->len = cpu_to_le32(sctx->send_size - sizeof(*hdr)); |
621 | hdr->crc = 0; | 621 | hdr->crc = 0; |
622 | 622 | ||
623 | crc = crc32c(0, (unsigned char *)sctx->send_buf, sctx->send_size); | 623 | crc = btrfs_crc32c(0, (unsigned char *)sctx->send_buf, sctx->send_size); |
624 | hdr->crc = cpu_to_le32(crc); | 624 | hdr->crc = cpu_to_le32(crc); |
625 | 625 | ||
626 | ret = write_buf(sctx->send_filp, sctx->send_buf, sctx->send_size, | 626 | ret = write_buf(sctx->send_filp, sctx->send_buf, sctx->send_size, |
@@ -1332,6 +1332,16 @@ verbose_printk(KERN_DEBUG "btrfs: find_extent_clone: data_offset=%llu, " | |||
1332 | } | 1332 | } |
1333 | 1333 | ||
1334 | if (cur_clone_root) { | 1334 | if (cur_clone_root) { |
1335 | if (compressed != BTRFS_COMPRESS_NONE) { | ||
1336 | /* | ||
1337 | * Offsets given by iterate_extent_inodes() are relative | ||
1338 | * to the start of the extent, we need to add logical | ||
1339 | * offset from the file extent item. | ||
1340 | * (See why at backref.c:check_extent_in_eb()) | ||
1341 | */ | ||
1342 | cur_clone_root->offset += btrfs_file_extent_offset(eb, | ||
1343 | fi); | ||
1344 | } | ||
1335 | *found = cur_clone_root; | 1345 | *found = cur_clone_root; |
1336 | ret = 0; | 1346 | ret = 0; |
1337 | } else { | 1347 | } else { |
@@ -2774,8 +2784,6 @@ static int add_waiting_dir_move(struct send_ctx *sctx, u64 ino) | |||
2774 | return 0; | 2784 | return 0; |
2775 | } | 2785 | } |
2776 | 2786 | ||
2777 | #ifdef CONFIG_BTRFS_ASSERT | ||
2778 | |||
2779 | static int del_waiting_dir_move(struct send_ctx *sctx, u64 ino) | 2787 | static int del_waiting_dir_move(struct send_ctx *sctx, u64 ino) |
2780 | { | 2788 | { |
2781 | struct rb_node *n = sctx->waiting_dir_moves.rb_node; | 2789 | struct rb_node *n = sctx->waiting_dir_moves.rb_node; |
@@ -2796,8 +2804,6 @@ static int del_waiting_dir_move(struct send_ctx *sctx, u64 ino) | |||
2796 | return -ENOENT; | 2804 | return -ENOENT; |
2797 | } | 2805 | } |
2798 | 2806 | ||
2799 | #endif | ||
2800 | |||
2801 | static int add_pending_dir_move(struct send_ctx *sctx, u64 parent_ino) | 2807 | static int add_pending_dir_move(struct send_ctx *sctx, u64 parent_ino) |
2802 | { | 2808 | { |
2803 | struct rb_node **p = &sctx->pending_dir_moves.rb_node; | 2809 | struct rb_node **p = &sctx->pending_dir_moves.rb_node; |
@@ -2902,7 +2908,9 @@ static int apply_dir_move(struct send_ctx *sctx, struct pending_dir_move *pm) | |||
2902 | } | 2908 | } |
2903 | 2909 | ||
2904 | sctx->send_progress = sctx->cur_ino + 1; | 2910 | sctx->send_progress = sctx->cur_ino + 1; |
2905 | ASSERT(del_waiting_dir_move(sctx, pm->ino) == 0); | 2911 | ret = del_waiting_dir_move(sctx, pm->ino); |
2912 | ASSERT(ret == 0); | ||
2913 | |||
2906 | ret = get_cur_path(sctx, pm->ino, pm->gen, to_path); | 2914 | ret = get_cur_path(sctx, pm->ino, pm->gen, to_path); |
2907 | if (ret < 0) | 2915 | if (ret < 0) |
2908 | goto out; | 2916 | goto out; |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index c02f63356895..d04db817be5c 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -566,7 +566,7 @@ int btrfs_parse_options(struct btrfs_root *root, char *options) | |||
566 | kfree(num); | 566 | kfree(num); |
567 | 567 | ||
568 | if (info->max_inline) { | 568 | if (info->max_inline) { |
569 | info->max_inline = max_t(u64, | 569 | info->max_inline = min_t(u64, |
570 | info->max_inline, | 570 | info->max_inline, |
571 | root->sectorsize); | 571 | root->sectorsize); |
572 | } | 572 | } |
@@ -855,6 +855,7 @@ static struct dentry *get_default_root(struct super_block *sb, | |||
855 | struct btrfs_path *path; | 855 | struct btrfs_path *path; |
856 | struct btrfs_key location; | 856 | struct btrfs_key location; |
857 | struct inode *inode; | 857 | struct inode *inode; |
858 | struct dentry *dentry; | ||
858 | u64 dir_id; | 859 | u64 dir_id; |
859 | int new = 0; | 860 | int new = 0; |
860 | 861 | ||
@@ -925,7 +926,13 @@ setup_root: | |||
925 | return dget(sb->s_root); | 926 | return dget(sb->s_root); |
926 | } | 927 | } |
927 | 928 | ||
928 | return d_obtain_alias(inode); | 929 | dentry = d_obtain_alias(inode); |
930 | if (!IS_ERR(dentry)) { | ||
931 | spin_lock(&dentry->d_lock); | ||
932 | dentry->d_flags &= ~DCACHE_DISCONNECTED; | ||
933 | spin_unlock(&dentry->d_lock); | ||
934 | } | ||
935 | return dentry; | ||
929 | } | 936 | } |
930 | 937 | ||
931 | static int btrfs_fill_super(struct super_block *sb, | 938 | static int btrfs_fill_super(struct super_block *sb, |
@@ -1996,7 +2003,7 @@ static void __exit exit_btrfs_fs(void) | |||
1996 | btrfs_hash_exit(); | 2003 | btrfs_hash_exit(); |
1997 | } | 2004 | } |
1998 | 2005 | ||
1999 | module_init(init_btrfs_fs) | 2006 | late_initcall(init_btrfs_fs); |
2000 | module_exit(exit_btrfs_fs) | 2007 | module_exit(exit_btrfs_fs) |
2001 | 2008 | ||
2002 | MODULE_LICENSE("GPL"); | 2009 | MODULE_LICENSE("GPL"); |
diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c index 782374d8fd19..865f4cf9a769 100644 --- a/fs/btrfs/sysfs.c +++ b/fs/btrfs/sysfs.c | |||
@@ -578,8 +578,14 @@ static int add_device_membership(struct btrfs_fs_info *fs_info) | |||
578 | return -ENOMEM; | 578 | return -ENOMEM; |
579 | 579 | ||
580 | list_for_each_entry(dev, &fs_devices->devices, dev_list) { | 580 | list_for_each_entry(dev, &fs_devices->devices, dev_list) { |
581 | struct hd_struct *disk = dev->bdev->bd_part; | 581 | struct hd_struct *disk; |
582 | struct kobject *disk_kobj = &part_to_dev(disk)->kobj; | 582 | struct kobject *disk_kobj; |
583 | |||
584 | if (!dev->bdev) | ||
585 | continue; | ||
586 | |||
587 | disk = dev->bdev->bd_part; | ||
588 | disk_kobj = &part_to_dev(disk)->kobj; | ||
583 | 589 | ||
584 | error = sysfs_create_link(fs_info->device_dir_kobj, | 590 | error = sysfs_create_link(fs_info->device_dir_kobj, |
585 | disk_kobj, disk_kobj->name); | 591 | disk_kobj, disk_kobj->name); |
diff --git a/fs/buffer.c b/fs/buffer.c index 651dba10b9c2..27265a8b43c1 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
@@ -654,14 +654,16 @@ EXPORT_SYMBOL(mark_buffer_dirty_inode); | |||
654 | static void __set_page_dirty(struct page *page, | 654 | static void __set_page_dirty(struct page *page, |
655 | struct address_space *mapping, int warn) | 655 | struct address_space *mapping, int warn) |
656 | { | 656 | { |
657 | spin_lock_irq(&mapping->tree_lock); | 657 | unsigned long flags; |
658 | |||
659 | spin_lock_irqsave(&mapping->tree_lock, flags); | ||
658 | if (page->mapping) { /* Race with truncate? */ | 660 | if (page->mapping) { /* Race with truncate? */ |
659 | WARN_ON_ONCE(warn && !PageUptodate(page)); | 661 | WARN_ON_ONCE(warn && !PageUptodate(page)); |
660 | account_page_dirtied(page, mapping); | 662 | account_page_dirtied(page, mapping); |
661 | radix_tree_tag_set(&mapping->page_tree, | 663 | radix_tree_tag_set(&mapping->page_tree, |
662 | page_index(page), PAGECACHE_TAG_DIRTY); | 664 | page_index(page), PAGECACHE_TAG_DIRTY); |
663 | } | 665 | } |
664 | spin_unlock_irq(&mapping->tree_lock); | 666 | spin_unlock_irqrestore(&mapping->tree_lock, flags); |
665 | __mark_inode_dirty(mapping->host, I_DIRTY_PAGES); | 667 | __mark_inode_dirty(mapping->host, I_DIRTY_PAGES); |
666 | } | 668 | } |
667 | 669 | ||
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index 8f9b4f710d4a..c819b0bd491a 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c | |||
@@ -1043,15 +1043,30 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode, | |||
1043 | __u32 secdesclen = 0; | 1043 | __u32 secdesclen = 0; |
1044 | struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */ | 1044 | struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */ |
1045 | struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */ | 1045 | struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */ |
1046 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | ||
1047 | struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); | ||
1048 | struct cifs_tcon *tcon; | ||
1049 | |||
1050 | if (IS_ERR(tlink)) | ||
1051 | return PTR_ERR(tlink); | ||
1052 | tcon = tlink_tcon(tlink); | ||
1046 | 1053 | ||
1047 | cifs_dbg(NOISY, "set ACL from mode for %s\n", path); | 1054 | cifs_dbg(NOISY, "set ACL from mode for %s\n", path); |
1048 | 1055 | ||
1049 | /* Get the security descriptor */ | 1056 | /* Get the security descriptor */ |
1050 | pntsd = get_cifs_acl(CIFS_SB(inode->i_sb), inode, path, &secdesclen); | 1057 | |
1058 | if (tcon->ses->server->ops->get_acl == NULL) { | ||
1059 | cifs_put_tlink(tlink); | ||
1060 | return -EOPNOTSUPP; | ||
1061 | } | ||
1062 | |||
1063 | pntsd = tcon->ses->server->ops->get_acl(cifs_sb, inode, path, | ||
1064 | &secdesclen); | ||
1051 | if (IS_ERR(pntsd)) { | 1065 | if (IS_ERR(pntsd)) { |
1052 | rc = PTR_ERR(pntsd); | 1066 | rc = PTR_ERR(pntsd); |
1053 | cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc); | 1067 | cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc); |
1054 | goto out; | 1068 | cifs_put_tlink(tlink); |
1069 | return rc; | ||
1055 | } | 1070 | } |
1056 | 1071 | ||
1057 | /* | 1072 | /* |
@@ -1064,6 +1079,7 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode, | |||
1064 | pnntsd = kmalloc(secdesclen, GFP_KERNEL); | 1079 | pnntsd = kmalloc(secdesclen, GFP_KERNEL); |
1065 | if (!pnntsd) { | 1080 | if (!pnntsd) { |
1066 | kfree(pntsd); | 1081 | kfree(pntsd); |
1082 | cifs_put_tlink(tlink); | ||
1067 | return -ENOMEM; | 1083 | return -ENOMEM; |
1068 | } | 1084 | } |
1069 | 1085 | ||
@@ -1072,14 +1088,18 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode, | |||
1072 | 1088 | ||
1073 | cifs_dbg(NOISY, "build_sec_desc rc: %d\n", rc); | 1089 | cifs_dbg(NOISY, "build_sec_desc rc: %d\n", rc); |
1074 | 1090 | ||
1091 | if (tcon->ses->server->ops->set_acl == NULL) | ||
1092 | rc = -EOPNOTSUPP; | ||
1093 | |||
1075 | if (!rc) { | 1094 | if (!rc) { |
1076 | /* Set the security descriptor */ | 1095 | /* Set the security descriptor */ |
1077 | rc = set_cifs_acl(pnntsd, secdesclen, inode, path, aclflag); | 1096 | rc = tcon->ses->server->ops->set_acl(pnntsd, secdesclen, inode, |
1097 | path, aclflag); | ||
1078 | cifs_dbg(NOISY, "set_cifs_acl rc: %d\n", rc); | 1098 | cifs_dbg(NOISY, "set_cifs_acl rc: %d\n", rc); |
1079 | } | 1099 | } |
1100 | cifs_put_tlink(tlink); | ||
1080 | 1101 | ||
1081 | kfree(pnntsd); | 1102 | kfree(pnntsd); |
1082 | kfree(pntsd); | 1103 | kfree(pntsd); |
1083 | out: | ||
1084 | return rc; | 1104 | return rc; |
1085 | } | 1105 | } |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index a245d1809ed8..86dc28c7aa5c 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -323,7 +323,8 @@ struct smb_version_operations { | |||
323 | /* async read from the server */ | 323 | /* async read from the server */ |
324 | int (*async_readv)(struct cifs_readdata *); | 324 | int (*async_readv)(struct cifs_readdata *); |
325 | /* async write to the server */ | 325 | /* async write to the server */ |
326 | int (*async_writev)(struct cifs_writedata *); | 326 | int (*async_writev)(struct cifs_writedata *, |
327 | void (*release)(struct kref *)); | ||
327 | /* sync read from the server */ | 328 | /* sync read from the server */ |
328 | int (*sync_read)(const unsigned int, struct cifsFileInfo *, | 329 | int (*sync_read)(const unsigned int, struct cifsFileInfo *, |
329 | struct cifs_io_parms *, unsigned int *, char **, | 330 | struct cifs_io_parms *, unsigned int *, char **, |
@@ -395,6 +396,10 @@ struct smb_version_operations { | |||
395 | int (*set_EA)(const unsigned int, struct cifs_tcon *, const char *, | 396 | int (*set_EA)(const unsigned int, struct cifs_tcon *, const char *, |
396 | const char *, const void *, const __u16, | 397 | const char *, const void *, const __u16, |
397 | const struct nls_table *, int); | 398 | const struct nls_table *, int); |
399 | struct cifs_ntsd * (*get_acl)(struct cifs_sb_info *, struct inode *, | ||
400 | const char *, u32 *); | ||
401 | int (*set_acl)(struct cifs_ntsd *, __u32, struct inode *, const char *, | ||
402 | int); | ||
398 | }; | 403 | }; |
399 | 404 | ||
400 | struct smb_version_values { | 405 | struct smb_version_values { |
@@ -1064,7 +1069,7 @@ struct cifs_writedata { | |||
1064 | unsigned int pagesz; | 1069 | unsigned int pagesz; |
1065 | unsigned int tailsz; | 1070 | unsigned int tailsz; |
1066 | unsigned int nr_pages; | 1071 | unsigned int nr_pages; |
1067 | struct page *pages[1]; | 1072 | struct page *pages[]; |
1068 | }; | 1073 | }; |
1069 | 1074 | ||
1070 | /* | 1075 | /* |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 79e6e9a93a8c..d00e09dfc452 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -488,7 +488,8 @@ void cifs_readdata_release(struct kref *refcount); | |||
488 | int cifs_async_readv(struct cifs_readdata *rdata); | 488 | int cifs_async_readv(struct cifs_readdata *rdata); |
489 | int cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid); | 489 | int cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid); |
490 | 490 | ||
491 | int cifs_async_writev(struct cifs_writedata *wdata); | 491 | int cifs_async_writev(struct cifs_writedata *wdata, |
492 | void (*release)(struct kref *kref)); | ||
492 | void cifs_writev_complete(struct work_struct *work); | 493 | void cifs_writev_complete(struct work_struct *work); |
493 | struct cifs_writedata *cifs_writedata_alloc(unsigned int nr_pages, | 494 | struct cifs_writedata *cifs_writedata_alloc(unsigned int nr_pages, |
494 | work_func_t complete); | 495 | work_func_t complete); |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 4d881c35eeca..f3264bd7a83d 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -1910,7 +1910,7 @@ cifs_writev_requeue(struct cifs_writedata *wdata) | |||
1910 | 1910 | ||
1911 | do { | 1911 | do { |
1912 | server = tlink_tcon(wdata->cfile->tlink)->ses->server; | 1912 | server = tlink_tcon(wdata->cfile->tlink)->ses->server; |
1913 | rc = server->ops->async_writev(wdata); | 1913 | rc = server->ops->async_writev(wdata, cifs_writedata_release); |
1914 | } while (rc == -EAGAIN); | 1914 | } while (rc == -EAGAIN); |
1915 | 1915 | ||
1916 | for (i = 0; i < wdata->nr_pages; i++) { | 1916 | for (i = 0; i < wdata->nr_pages; i++) { |
@@ -1962,15 +1962,9 @@ cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete) | |||
1962 | { | 1962 | { |
1963 | struct cifs_writedata *wdata; | 1963 | struct cifs_writedata *wdata; |
1964 | 1964 | ||
1965 | /* this would overflow */ | ||
1966 | if (nr_pages == 0) { | ||
1967 | cifs_dbg(VFS, "%s: called with nr_pages == 0!\n", __func__); | ||
1968 | return NULL; | ||
1969 | } | ||
1970 | |||
1971 | /* writedata + number of page pointers */ | 1965 | /* writedata + number of page pointers */ |
1972 | wdata = kzalloc(sizeof(*wdata) + | 1966 | wdata = kzalloc(sizeof(*wdata) + |
1973 | sizeof(struct page *) * (nr_pages - 1), GFP_NOFS); | 1967 | sizeof(struct page *) * nr_pages, GFP_NOFS); |
1974 | if (wdata != NULL) { | 1968 | if (wdata != NULL) { |
1975 | kref_init(&wdata->refcount); | 1969 | kref_init(&wdata->refcount); |
1976 | INIT_LIST_HEAD(&wdata->list); | 1970 | INIT_LIST_HEAD(&wdata->list); |
@@ -2031,7 +2025,8 @@ cifs_writev_callback(struct mid_q_entry *mid) | |||
2031 | 2025 | ||
2032 | /* cifs_async_writev - send an async write, and set up mid to handle result */ | 2026 | /* cifs_async_writev - send an async write, and set up mid to handle result */ |
2033 | int | 2027 | int |
2034 | cifs_async_writev(struct cifs_writedata *wdata) | 2028 | cifs_async_writev(struct cifs_writedata *wdata, |
2029 | void (*release)(struct kref *kref)) | ||
2035 | { | 2030 | { |
2036 | int rc = -EACCES; | 2031 | int rc = -EACCES; |
2037 | WRITE_REQ *smb = NULL; | 2032 | WRITE_REQ *smb = NULL; |
@@ -2105,7 +2100,7 @@ cifs_async_writev(struct cifs_writedata *wdata) | |||
2105 | if (rc == 0) | 2100 | if (rc == 0) |
2106 | cifs_stats_inc(&tcon->stats.cifs_stats.num_writes); | 2101 | cifs_stats_inc(&tcon->stats.cifs_stats.num_writes); |
2107 | else | 2102 | else |
2108 | kref_put(&wdata->refcount, cifs_writedata_release); | 2103 | kref_put(&wdata->refcount, release); |
2109 | 2104 | ||
2110 | async_writev_out: | 2105 | async_writev_out: |
2111 | cifs_small_buf_release(smb); | 2106 | cifs_small_buf_release(smb); |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 853d6d1cc822..755584684f6c 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -2043,7 +2043,8 @@ retry: | |||
2043 | } | 2043 | } |
2044 | wdata->pid = wdata->cfile->pid; | 2044 | wdata->pid = wdata->cfile->pid; |
2045 | server = tlink_tcon(wdata->cfile->tlink)->ses->server; | 2045 | server = tlink_tcon(wdata->cfile->tlink)->ses->server; |
2046 | rc = server->ops->async_writev(wdata); | 2046 | rc = server->ops->async_writev(wdata, |
2047 | cifs_writedata_release); | ||
2047 | } while (wbc->sync_mode == WB_SYNC_ALL && rc == -EAGAIN); | 2048 | } while (wbc->sync_mode == WB_SYNC_ALL && rc == -EAGAIN); |
2048 | 2049 | ||
2049 | for (i = 0; i < nr_pages; ++i) | 2050 | for (i = 0; i < nr_pages; ++i) |
@@ -2331,9 +2332,20 @@ size_t get_numpages(const size_t wsize, const size_t len, size_t *cur_len) | |||
2331 | } | 2332 | } |
2332 | 2333 | ||
2333 | static void | 2334 | static void |
2334 | cifs_uncached_writev_complete(struct work_struct *work) | 2335 | cifs_uncached_writedata_release(struct kref *refcount) |
2335 | { | 2336 | { |
2336 | int i; | 2337 | int i; |
2338 | struct cifs_writedata *wdata = container_of(refcount, | ||
2339 | struct cifs_writedata, refcount); | ||
2340 | |||
2341 | for (i = 0; i < wdata->nr_pages; i++) | ||
2342 | put_page(wdata->pages[i]); | ||
2343 | cifs_writedata_release(refcount); | ||
2344 | } | ||
2345 | |||
2346 | static void | ||
2347 | cifs_uncached_writev_complete(struct work_struct *work) | ||
2348 | { | ||
2337 | struct cifs_writedata *wdata = container_of(work, | 2349 | struct cifs_writedata *wdata = container_of(work, |
2338 | struct cifs_writedata, work); | 2350 | struct cifs_writedata, work); |
2339 | struct inode *inode = wdata->cfile->dentry->d_inode; | 2351 | struct inode *inode = wdata->cfile->dentry->d_inode; |
@@ -2347,12 +2359,7 @@ cifs_uncached_writev_complete(struct work_struct *work) | |||
2347 | 2359 | ||
2348 | complete(&wdata->done); | 2360 | complete(&wdata->done); |
2349 | 2361 | ||
2350 | if (wdata->result != -EAGAIN) { | 2362 | kref_put(&wdata->refcount, cifs_uncached_writedata_release); |
2351 | for (i = 0; i < wdata->nr_pages; i++) | ||
2352 | put_page(wdata->pages[i]); | ||
2353 | } | ||
2354 | |||
2355 | kref_put(&wdata->refcount, cifs_writedata_release); | ||
2356 | } | 2363 | } |
2357 | 2364 | ||
2358 | /* attempt to send write to server, retry on any -EAGAIN errors */ | 2365 | /* attempt to send write to server, retry on any -EAGAIN errors */ |
@@ -2370,7 +2377,8 @@ cifs_uncached_retry_writev(struct cifs_writedata *wdata) | |||
2370 | if (rc != 0) | 2377 | if (rc != 0) |
2371 | continue; | 2378 | continue; |
2372 | } | 2379 | } |
2373 | rc = server->ops->async_writev(wdata); | 2380 | rc = server->ops->async_writev(wdata, |
2381 | cifs_uncached_writedata_release); | ||
2374 | } while (rc == -EAGAIN); | 2382 | } while (rc == -EAGAIN); |
2375 | 2383 | ||
2376 | return rc; | 2384 | return rc; |
@@ -2454,7 +2462,8 @@ cifs_iovec_write(struct file *file, const struct iovec *iov, | |||
2454 | wdata->tailsz = cur_len - ((nr_pages - 1) * PAGE_SIZE); | 2462 | wdata->tailsz = cur_len - ((nr_pages - 1) * PAGE_SIZE); |
2455 | rc = cifs_uncached_retry_writev(wdata); | 2463 | rc = cifs_uncached_retry_writev(wdata); |
2456 | if (rc) { | 2464 | if (rc) { |
2457 | kref_put(&wdata->refcount, cifs_writedata_release); | 2465 | kref_put(&wdata->refcount, |
2466 | cifs_uncached_writedata_release); | ||
2458 | break; | 2467 | break; |
2459 | } | 2468 | } |
2460 | 2469 | ||
@@ -2496,7 +2505,7 @@ restart_loop: | |||
2496 | } | 2505 | } |
2497 | } | 2506 | } |
2498 | list_del_init(&wdata->list); | 2507 | list_del_init(&wdata->list); |
2499 | kref_put(&wdata->refcount, cifs_writedata_release); | 2508 | kref_put(&wdata->refcount, cifs_uncached_writedata_release); |
2500 | } | 2509 | } |
2501 | 2510 | ||
2502 | if (total_written > 0) | 2511 | if (total_written > 0) |
@@ -2559,8 +2568,8 @@ cifs_writev(struct kiocb *iocb, const struct iovec *iov, | |||
2559 | if (rc > 0) { | 2568 | if (rc > 0) { |
2560 | ssize_t err; | 2569 | ssize_t err; |
2561 | 2570 | ||
2562 | err = generic_write_sync(file, pos, rc); | 2571 | err = generic_write_sync(file, iocb->ki_pos - rc, rc); |
2563 | if (err < 0 && rc > 0) | 2572 | if (err < 0) |
2564 | rc = err; | 2573 | rc = err; |
2565 | } | 2574 | } |
2566 | 2575 | ||
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 9cb9679d7357..be58b8fcdb3c 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -527,10 +527,15 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path, | |||
527 | return PTR_ERR(tlink); | 527 | return PTR_ERR(tlink); |
528 | tcon = tlink_tcon(tlink); | 528 | tcon = tlink_tcon(tlink); |
529 | 529 | ||
530 | rc = CIFSSMBQAllEAs(xid, tcon, path, "SETFILEBITS", | 530 | if (tcon->ses->server->ops->query_all_EAs == NULL) { |
531 | ea_value, 4 /* size of buf */, cifs_sb->local_nls, | 531 | cifs_put_tlink(tlink); |
532 | cifs_sb->mnt_cifs_flags & | 532 | return -EOPNOTSUPP; |
533 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 533 | } |
534 | |||
535 | rc = tcon->ses->server->ops->query_all_EAs(xid, tcon, path, | ||
536 | "SETFILEBITS", ea_value, 4 /* size of buf */, | ||
537 | cifs_sb->local_nls, | ||
538 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
534 | cifs_put_tlink(tlink); | 539 | cifs_put_tlink(tlink); |
535 | if (rc < 0) | 540 | if (rc < 0) |
536 | return (int)rc; | 541 | return (int)rc; |
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c index 9ac5bfc9cc56..bfd66d84831e 100644 --- a/fs/cifs/smb1ops.c +++ b/fs/cifs/smb1ops.c | |||
@@ -1067,6 +1067,14 @@ struct smb_version_operations smb1_operations = { | |||
1067 | .query_mf_symlink = cifs_query_mf_symlink, | 1067 | .query_mf_symlink = cifs_query_mf_symlink, |
1068 | .create_mf_symlink = cifs_create_mf_symlink, | 1068 | .create_mf_symlink = cifs_create_mf_symlink, |
1069 | .is_read_op = cifs_is_read_op, | 1069 | .is_read_op = cifs_is_read_op, |
1070 | #ifdef CONFIG_CIFS_XATTR | ||
1071 | .query_all_EAs = CIFSSMBQAllEAs, | ||
1072 | .set_EA = CIFSSMBSetEA, | ||
1073 | #endif /* CIFS_XATTR */ | ||
1074 | #ifdef CONFIG_CIFS_ACL | ||
1075 | .get_acl = get_cifs_acl, | ||
1076 | .set_acl = set_cifs_acl, | ||
1077 | #endif /* CIFS_ACL */ | ||
1070 | }; | 1078 | }; |
1071 | 1079 | ||
1072 | struct smb_version_values smb1_values = { | 1080 | struct smb_version_values smb1_values = { |
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 2013234b73ad..a3f7a9c3cc69 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c | |||
@@ -1890,7 +1890,8 @@ smb2_writev_callback(struct mid_q_entry *mid) | |||
1890 | 1890 | ||
1891 | /* smb2_async_writev - send an async write, and set up mid to handle result */ | 1891 | /* smb2_async_writev - send an async write, and set up mid to handle result */ |
1892 | int | 1892 | int |
1893 | smb2_async_writev(struct cifs_writedata *wdata) | 1893 | smb2_async_writev(struct cifs_writedata *wdata, |
1894 | void (*release)(struct kref *kref)) | ||
1894 | { | 1895 | { |
1895 | int rc = -EACCES; | 1896 | int rc = -EACCES; |
1896 | struct smb2_write_req *req = NULL; | 1897 | struct smb2_write_req *req = NULL; |
@@ -1938,7 +1939,7 @@ smb2_async_writev(struct cifs_writedata *wdata) | |||
1938 | smb2_writev_callback, wdata, 0); | 1939 | smb2_writev_callback, wdata, 0); |
1939 | 1940 | ||
1940 | if (rc) { | 1941 | if (rc) { |
1941 | kref_put(&wdata->refcount, cifs_writedata_release); | 1942 | kref_put(&wdata->refcount, release); |
1942 | cifs_stats_fail_inc(tcon, SMB2_WRITE_HE); | 1943 | cifs_stats_fail_inc(tcon, SMB2_WRITE_HE); |
1943 | } | 1944 | } |
1944 | 1945 | ||
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h index 93adc64666f3..0ce48db20a65 100644 --- a/fs/cifs/smb2proto.h +++ b/fs/cifs/smb2proto.h | |||
@@ -123,7 +123,8 @@ extern int SMB2_get_srv_num(const unsigned int xid, struct cifs_tcon *tcon, | |||
123 | extern int smb2_async_readv(struct cifs_readdata *rdata); | 123 | extern int smb2_async_readv(struct cifs_readdata *rdata); |
124 | extern int SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms, | 124 | extern int SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms, |
125 | unsigned int *nbytes, char **buf, int *buf_type); | 125 | unsigned int *nbytes, char **buf, int *buf_type); |
126 | extern int smb2_async_writev(struct cifs_writedata *wdata); | 126 | extern int smb2_async_writev(struct cifs_writedata *wdata, |
127 | void (*release)(struct kref *kref)); | ||
127 | extern int SMB2_write(const unsigned int xid, struct cifs_io_parms *io_parms, | 128 | extern int SMB2_write(const unsigned int xid, struct cifs_io_parms *io_parms, |
128 | unsigned int *nbytes, struct kvec *iov, int n_vec); | 129 | unsigned int *nbytes, struct kvec *iov, int n_vec); |
129 | extern int SMB2_echo(struct TCP_Server_Info *server); | 130 | extern int SMB2_echo(struct TCP_Server_Info *server); |
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index 95c43bb20335..5ac836a86b18 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c | |||
@@ -176,8 +176,12 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, | |||
176 | rc = -ENOMEM; | 176 | rc = -ENOMEM; |
177 | } else { | 177 | } else { |
178 | memcpy(pacl, ea_value, value_size); | 178 | memcpy(pacl, ea_value, value_size); |
179 | rc = set_cifs_acl(pacl, value_size, | 179 | if (pTcon->ses->server->ops->set_acl) |
180 | direntry->d_inode, full_path, CIFS_ACL_DACL); | 180 | rc = pTcon->ses->server->ops->set_acl(pacl, |
181 | value_size, direntry->d_inode, | ||
182 | full_path, CIFS_ACL_DACL); | ||
183 | else | ||
184 | rc = -EOPNOTSUPP; | ||
181 | if (rc == 0) /* force revalidate of the inode */ | 185 | if (rc == 0) /* force revalidate of the inode */ |
182 | CIFS_I(direntry->d_inode)->time = 0; | 186 | CIFS_I(direntry->d_inode)->time = 0; |
183 | kfree(pacl); | 187 | kfree(pacl); |
@@ -323,8 +327,11 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, | |||
323 | u32 acllen; | 327 | u32 acllen; |
324 | struct cifs_ntsd *pacl; | 328 | struct cifs_ntsd *pacl; |
325 | 329 | ||
326 | pacl = get_cifs_acl(cifs_sb, direntry->d_inode, | 330 | if (pTcon->ses->server->ops->get_acl == NULL) |
327 | full_path, &acllen); | 331 | goto get_ea_exit; /* rc already EOPNOTSUPP */ |
332 | |||
333 | pacl = pTcon->ses->server->ops->get_acl(cifs_sb, | ||
334 | direntry->d_inode, full_path, &acllen); | ||
328 | if (IS_ERR(pacl)) { | 335 | if (IS_ERR(pacl)) { |
329 | rc = PTR_ERR(pacl); | 336 | rc = PTR_ERR(pacl); |
330 | cifs_dbg(VFS, "%s: error %zd getting sec desc\n", | 337 | cifs_dbg(VFS, "%s: error %zd getting sec desc\n", |
@@ -748,11 +748,10 @@ EXPORT_SYMBOL(setup_arg_pages); | |||
748 | 748 | ||
749 | #endif /* CONFIG_MMU */ | 749 | #endif /* CONFIG_MMU */ |
750 | 750 | ||
751 | struct file *open_exec(const char *name) | 751 | static struct file *do_open_exec(struct filename *name) |
752 | { | 752 | { |
753 | struct file *file; | 753 | struct file *file; |
754 | int err; | 754 | int err; |
755 | struct filename tmp = { .name = name }; | ||
756 | static const struct open_flags open_exec_flags = { | 755 | static const struct open_flags open_exec_flags = { |
757 | .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC, | 756 | .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC, |
758 | .acc_mode = MAY_EXEC | MAY_OPEN, | 757 | .acc_mode = MAY_EXEC | MAY_OPEN, |
@@ -760,7 +759,7 @@ struct file *open_exec(const char *name) | |||
760 | .lookup_flags = LOOKUP_FOLLOW, | 759 | .lookup_flags = LOOKUP_FOLLOW, |
761 | }; | 760 | }; |
762 | 761 | ||
763 | file = do_filp_open(AT_FDCWD, &tmp, &open_exec_flags); | 762 | file = do_filp_open(AT_FDCWD, name, &open_exec_flags); |
764 | if (IS_ERR(file)) | 763 | if (IS_ERR(file)) |
765 | goto out; | 764 | goto out; |
766 | 765 | ||
@@ -784,6 +783,12 @@ exit: | |||
784 | fput(file); | 783 | fput(file); |
785 | return ERR_PTR(err); | 784 | return ERR_PTR(err); |
786 | } | 785 | } |
786 | |||
787 | struct file *open_exec(const char *name) | ||
788 | { | ||
789 | struct filename tmp = { .name = name }; | ||
790 | return do_open_exec(&tmp); | ||
791 | } | ||
787 | EXPORT_SYMBOL(open_exec); | 792 | EXPORT_SYMBOL(open_exec); |
788 | 793 | ||
789 | int kernel_read(struct file *file, loff_t offset, | 794 | int kernel_read(struct file *file, loff_t offset, |
@@ -1162,7 +1167,7 @@ int prepare_bprm_creds(struct linux_binprm *bprm) | |||
1162 | return -ENOMEM; | 1167 | return -ENOMEM; |
1163 | } | 1168 | } |
1164 | 1169 | ||
1165 | void free_bprm(struct linux_binprm *bprm) | 1170 | static void free_bprm(struct linux_binprm *bprm) |
1166 | { | 1171 | { |
1167 | free_arg_pages(bprm); | 1172 | free_arg_pages(bprm); |
1168 | if (bprm->cred) { | 1173 | if (bprm->cred) { |
@@ -1432,7 +1437,7 @@ static int exec_binprm(struct linux_binprm *bprm) | |||
1432 | /* | 1437 | /* |
1433 | * sys_execve() executes a new program. | 1438 | * sys_execve() executes a new program. |
1434 | */ | 1439 | */ |
1435 | static int do_execve_common(const char *filename, | 1440 | static int do_execve_common(struct filename *filename, |
1436 | struct user_arg_ptr argv, | 1441 | struct user_arg_ptr argv, |
1437 | struct user_arg_ptr envp) | 1442 | struct user_arg_ptr envp) |
1438 | { | 1443 | { |
@@ -1441,6 +1446,9 @@ static int do_execve_common(const char *filename, | |||
1441 | struct files_struct *displaced; | 1446 | struct files_struct *displaced; |
1442 | int retval; | 1447 | int retval; |
1443 | 1448 | ||
1449 | if (IS_ERR(filename)) | ||
1450 | return PTR_ERR(filename); | ||
1451 | |||
1444 | /* | 1452 | /* |
1445 | * We move the actual failure in case of RLIMIT_NPROC excess from | 1453 | * We move the actual failure in case of RLIMIT_NPROC excess from |
1446 | * set*uid() to execve() because too many poorly written programs | 1454 | * set*uid() to execve() because too many poorly written programs |
@@ -1473,7 +1481,7 @@ static int do_execve_common(const char *filename, | |||
1473 | check_unsafe_exec(bprm); | 1481 | check_unsafe_exec(bprm); |
1474 | current->in_execve = 1; | 1482 | current->in_execve = 1; |
1475 | 1483 | ||
1476 | file = open_exec(filename); | 1484 | file = do_open_exec(filename); |
1477 | retval = PTR_ERR(file); | 1485 | retval = PTR_ERR(file); |
1478 | if (IS_ERR(file)) | 1486 | if (IS_ERR(file)) |
1479 | goto out_unmark; | 1487 | goto out_unmark; |
@@ -1481,8 +1489,7 @@ static int do_execve_common(const char *filename, | |||
1481 | sched_exec(); | 1489 | sched_exec(); |
1482 | 1490 | ||
1483 | bprm->file = file; | 1491 | bprm->file = file; |
1484 | bprm->filename = filename; | 1492 | bprm->filename = bprm->interp = filename->name; |
1485 | bprm->interp = filename; | ||
1486 | 1493 | ||
1487 | retval = bprm_mm_init(bprm); | 1494 | retval = bprm_mm_init(bprm); |
1488 | if (retval) | 1495 | if (retval) |
@@ -1523,6 +1530,7 @@ static int do_execve_common(const char *filename, | |||
1523 | acct_update_integrals(current); | 1530 | acct_update_integrals(current); |
1524 | task_numa_free(current); | 1531 | task_numa_free(current); |
1525 | free_bprm(bprm); | 1532 | free_bprm(bprm); |
1533 | putname(filename); | ||
1526 | if (displaced) | 1534 | if (displaced) |
1527 | put_files_struct(displaced); | 1535 | put_files_struct(displaced); |
1528 | return retval; | 1536 | return retval; |
@@ -1544,10 +1552,11 @@ out_files: | |||
1544 | if (displaced) | 1552 | if (displaced) |
1545 | reset_files_struct(displaced); | 1553 | reset_files_struct(displaced); |
1546 | out_ret: | 1554 | out_ret: |
1555 | putname(filename); | ||
1547 | return retval; | 1556 | return retval; |
1548 | } | 1557 | } |
1549 | 1558 | ||
1550 | int do_execve(const char *filename, | 1559 | int do_execve(struct filename *filename, |
1551 | const char __user *const __user *__argv, | 1560 | const char __user *const __user *__argv, |
1552 | const char __user *const __user *__envp) | 1561 | const char __user *const __user *__envp) |
1553 | { | 1562 | { |
@@ -1557,7 +1566,7 @@ int do_execve(const char *filename, | |||
1557 | } | 1566 | } |
1558 | 1567 | ||
1559 | #ifdef CONFIG_COMPAT | 1568 | #ifdef CONFIG_COMPAT |
1560 | static int compat_do_execve(const char *filename, | 1569 | static int compat_do_execve(struct filename *filename, |
1561 | const compat_uptr_t __user *__argv, | 1570 | const compat_uptr_t __user *__argv, |
1562 | const compat_uptr_t __user *__envp) | 1571 | const compat_uptr_t __user *__envp) |
1563 | { | 1572 | { |
@@ -1607,25 +1616,13 @@ SYSCALL_DEFINE3(execve, | |||
1607 | const char __user *const __user *, argv, | 1616 | const char __user *const __user *, argv, |
1608 | const char __user *const __user *, envp) | 1617 | const char __user *const __user *, envp) |
1609 | { | 1618 | { |
1610 | struct filename *path = getname(filename); | 1619 | return do_execve(getname(filename), argv, envp); |
1611 | int error = PTR_ERR(path); | ||
1612 | if (!IS_ERR(path)) { | ||
1613 | error = do_execve(path->name, argv, envp); | ||
1614 | putname(path); | ||
1615 | } | ||
1616 | return error; | ||
1617 | } | 1620 | } |
1618 | #ifdef CONFIG_COMPAT | 1621 | #ifdef CONFIG_COMPAT |
1619 | asmlinkage long compat_sys_execve(const char __user * filename, | 1622 | asmlinkage long compat_sys_execve(const char __user * filename, |
1620 | const compat_uptr_t __user * argv, | 1623 | const compat_uptr_t __user * argv, |
1621 | const compat_uptr_t __user * envp) | 1624 | const compat_uptr_t __user * envp) |
1622 | { | 1625 | { |
1623 | struct filename *path = getname(filename); | 1626 | return compat_do_execve(getname(filename), argv, envp); |
1624 | int error = PTR_ERR(path); | ||
1625 | if (!IS_ERR(path)) { | ||
1626 | error = compat_do_execve(path->name, argv, envp); | ||
1627 | putname(path); | ||
1628 | } | ||
1629 | return error; | ||
1630 | } | 1627 | } |
1631 | #endif | 1628 | #endif |
diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 43e64f6022eb..1a5073959f32 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c | |||
@@ -152,7 +152,7 @@ ext4_file_dio_write(struct kiocb *iocb, const struct iovec *iov, | |||
152 | if (ret > 0) { | 152 | if (ret > 0) { |
153 | ssize_t err; | 153 | ssize_t err; |
154 | 154 | ||
155 | err = generic_write_sync(file, pos, ret); | 155 | err = generic_write_sync(file, iocb->ki_pos - ret, ret); |
156 | if (err < 0 && ret > 0) | 156 | if (err < 0 && ret > 0) |
157 | ret = err; | 157 | ret = err; |
158 | } | 158 | } |
@@ -34,7 +34,7 @@ static void *alloc_fdmem(size_t size) | |||
34 | * vmalloc() if the allocation size will be considered "large" by the VM. | 34 | * vmalloc() if the allocation size will be considered "large" by the VM. |
35 | */ | 35 | */ |
36 | if (size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) { | 36 | if (size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) { |
37 | void *data = kmalloc(size, GFP_KERNEL|__GFP_NOWARN); | 37 | void *data = kmalloc(size, GFP_KERNEL|__GFP_NOWARN|__GFP_NORETRY); |
38 | if (data != NULL) | 38 | if (data != NULL) |
39 | return data; | 39 | return data; |
40 | } | 40 | } |
diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c index 3bd5ee45f7b3..46325d5c34fc 100644 --- a/fs/jfs/xattr.c +++ b/fs/jfs/xattr.c | |||
@@ -854,9 +854,6 @@ int jfs_setxattr(struct dentry *dentry, const char *name, const void *value, | |||
854 | int rc; | 854 | int rc; |
855 | tid_t tid; | 855 | tid_t tid; |
856 | 856 | ||
857 | if ((rc = can_set_xattr(inode, name, value, value_len))) | ||
858 | return rc; | ||
859 | |||
860 | /* | 857 | /* |
861 | * If this is a request for a synthetic attribute in the system.* | 858 | * If this is a request for a synthetic attribute in the system.* |
862 | * namespace use the generic infrastructure to resolve a handler | 859 | * namespace use the generic infrastructure to resolve a handler |
@@ -865,6 +862,9 @@ int jfs_setxattr(struct dentry *dentry, const char *name, const void *value, | |||
865 | if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) | 862 | if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) |
866 | return generic_setxattr(dentry, name, value, value_len, flags); | 863 | return generic_setxattr(dentry, name, value, value_len, flags); |
867 | 864 | ||
865 | if ((rc = can_set_xattr(inode, name, value, value_len))) | ||
866 | return rc; | ||
867 | |||
868 | if (value == NULL) { /* empty EA, do not remove */ | 868 | if (value == NULL) { /* empty EA, do not remove */ |
869 | value = ""; | 869 | value = ""; |
870 | value_len = 0; | 870 | value_len = 0; |
@@ -1034,9 +1034,6 @@ int jfs_removexattr(struct dentry *dentry, const char *name) | |||
1034 | int rc; | 1034 | int rc; |
1035 | tid_t tid; | 1035 | tid_t tid; |
1036 | 1036 | ||
1037 | if ((rc = can_set_xattr(inode, name, NULL, 0))) | ||
1038 | return rc; | ||
1039 | |||
1040 | /* | 1037 | /* |
1041 | * If this is a request for a synthetic attribute in the system.* | 1038 | * If this is a request for a synthetic attribute in the system.* |
1042 | * namespace use the generic infrastructure to resolve a handler | 1039 | * namespace use the generic infrastructure to resolve a handler |
@@ -1045,6 +1042,9 @@ int jfs_removexattr(struct dentry *dentry, const char *name) | |||
1045 | if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) | 1042 | if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) |
1046 | return generic_removexattr(dentry, name); | 1043 | return generic_removexattr(dentry, name); |
1047 | 1044 | ||
1045 | if ((rc = can_set_xattr(inode, name, NULL, 0))) | ||
1046 | return rc; | ||
1047 | |||
1048 | tid = txBegin(inode->i_sb, 0); | 1048 | tid = txBegin(inode->i_sb, 0); |
1049 | mutex_lock(&ji->commit_mutex); | 1049 | mutex_lock(&ji->commit_mutex); |
1050 | rc = __jfs_setxattr(tid, dentry->d_inode, name, NULL, 0, XATTR_REPLACE); | 1050 | rc = __jfs_setxattr(tid, dentry->d_inode, name, NULL, 0, XATTR_REPLACE); |
@@ -1061,7 +1061,7 @@ int jfs_removexattr(struct dentry *dentry, const char *name) | |||
1061 | * attributes are handled directly. | 1061 | * attributes are handled directly. |
1062 | */ | 1062 | */ |
1063 | const struct xattr_handler *jfs_xattr_handlers[] = { | 1063 | const struct xattr_handler *jfs_xattr_handlers[] = { |
1064 | #ifdef JFS_POSIX_ACL | 1064 | #ifdef CONFIG_JFS_POSIX_ACL |
1065 | &posix_acl_access_xattr_handler, | 1065 | &posix_acl_access_xattr_handler, |
1066 | &posix_acl_default_xattr_handler, | 1066 | &posix_acl_default_xattr_handler, |
1067 | #endif | 1067 | #endif |
diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c index 5104cf5d25c5..bd6e18be6e1a 100644 --- a/fs/kernfs/dir.c +++ b/fs/kernfs/dir.c | |||
@@ -187,19 +187,23 @@ static void kernfs_deactivate(struct kernfs_node *kn) | |||
187 | 187 | ||
188 | kn->u.completion = (void *)&wait; | 188 | kn->u.completion = (void *)&wait; |
189 | 189 | ||
190 | rwsem_acquire(&kn->dep_map, 0, 0, _RET_IP_); | 190 | if (kn->flags & KERNFS_LOCKDEP) |
191 | rwsem_acquire(&kn->dep_map, 0, 0, _RET_IP_); | ||
191 | /* atomic_add_return() is a mb(), put_active() will always see | 192 | /* atomic_add_return() is a mb(), put_active() will always see |
192 | * the updated kn->u.completion. | 193 | * the updated kn->u.completion. |
193 | */ | 194 | */ |
194 | v = atomic_add_return(KN_DEACTIVATED_BIAS, &kn->active); | 195 | v = atomic_add_return(KN_DEACTIVATED_BIAS, &kn->active); |
195 | 196 | ||
196 | if (v != KN_DEACTIVATED_BIAS) { | 197 | if (v != KN_DEACTIVATED_BIAS) { |
197 | lock_contended(&kn->dep_map, _RET_IP_); | 198 | if (kn->flags & KERNFS_LOCKDEP) |
199 | lock_contended(&kn->dep_map, _RET_IP_); | ||
198 | wait_for_completion(&wait); | 200 | wait_for_completion(&wait); |
199 | } | 201 | } |
200 | 202 | ||
201 | lock_acquired(&kn->dep_map, _RET_IP_); | 203 | if (kn->flags & KERNFS_LOCKDEP) { |
202 | rwsem_release(&kn->dep_map, 1, _RET_IP_); | 204 | lock_acquired(&kn->dep_map, _RET_IP_); |
205 | rwsem_release(&kn->dep_map, 1, _RET_IP_); | ||
206 | } | ||
203 | } | 207 | } |
204 | 208 | ||
205 | /** | 209 | /** |
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index e066a3902973..ab798a88ec1d 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c | |||
@@ -779,6 +779,7 @@ nlmsvc_grant_blocked(struct nlm_block *block) | |||
779 | struct nlm_file *file = block->b_file; | 779 | struct nlm_file *file = block->b_file; |
780 | struct nlm_lock *lock = &block->b_call->a_args.lock; | 780 | struct nlm_lock *lock = &block->b_call->a_args.lock; |
781 | int error; | 781 | int error; |
782 | loff_t fl_start, fl_end; | ||
782 | 783 | ||
783 | dprintk("lockd: grant blocked lock %p\n", block); | 784 | dprintk("lockd: grant blocked lock %p\n", block); |
784 | 785 | ||
@@ -796,9 +797,16 @@ nlmsvc_grant_blocked(struct nlm_block *block) | |||
796 | } | 797 | } |
797 | 798 | ||
798 | /* Try the lock operation again */ | 799 | /* Try the lock operation again */ |
800 | /* vfs_lock_file() can mangle fl_start and fl_end, but we need | ||
801 | * them unchanged for the GRANT_MSG | ||
802 | */ | ||
799 | lock->fl.fl_flags |= FL_SLEEP; | 803 | lock->fl.fl_flags |= FL_SLEEP; |
804 | fl_start = lock->fl.fl_start; | ||
805 | fl_end = lock->fl.fl_end; | ||
800 | error = vfs_lock_file(file->f_file, F_SETLK, &lock->fl, NULL); | 806 | error = vfs_lock_file(file->f_file, F_SETLK, &lock->fl, NULL); |
801 | lock->fl.fl_flags &= ~FL_SLEEP; | 807 | lock->fl.fl_flags &= ~FL_SLEEP; |
808 | lock->fl.fl_start = fl_start; | ||
809 | lock->fl.fl_end = fl_end; | ||
802 | 810 | ||
803 | switch (error) { | 811 | switch (error) { |
804 | case 0: | 812 | case 0: |
diff --git a/fs/namei.c b/fs/namei.c index d580df2e6804..385f7817bfcc 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -196,6 +196,7 @@ recopy: | |||
196 | goto error; | 196 | goto error; |
197 | 197 | ||
198 | result->uptr = filename; | 198 | result->uptr = filename; |
199 | result->aname = NULL; | ||
199 | audit_getname(result); | 200 | audit_getname(result); |
200 | return result; | 201 | return result; |
201 | 202 | ||
@@ -210,6 +211,35 @@ getname(const char __user * filename) | |||
210 | return getname_flags(filename, 0, NULL); | 211 | return getname_flags(filename, 0, NULL); |
211 | } | 212 | } |
212 | 213 | ||
214 | /* | ||
215 | * The "getname_kernel()" interface doesn't do pathnames longer | ||
216 | * than EMBEDDED_NAME_MAX. Deal with it - you're a kernel user. | ||
217 | */ | ||
218 | struct filename * | ||
219 | getname_kernel(const char * filename) | ||
220 | { | ||
221 | struct filename *result; | ||
222 | char *kname; | ||
223 | int len; | ||
224 | |||
225 | len = strlen(filename); | ||
226 | if (len >= EMBEDDED_NAME_MAX) | ||
227 | return ERR_PTR(-ENAMETOOLONG); | ||
228 | |||
229 | result = __getname(); | ||
230 | if (unlikely(!result)) | ||
231 | return ERR_PTR(-ENOMEM); | ||
232 | |||
233 | kname = (char *)result + sizeof(*result); | ||
234 | result->name = kname; | ||
235 | result->uptr = NULL; | ||
236 | result->aname = NULL; | ||
237 | result->separate = false; | ||
238 | |||
239 | strlcpy(kname, filename, EMBEDDED_NAME_MAX); | ||
240 | return result; | ||
241 | } | ||
242 | |||
213 | #ifdef CONFIG_AUDITSYSCALL | 243 | #ifdef CONFIG_AUDITSYSCALL |
214 | void putname(struct filename *name) | 244 | void putname(struct filename *name) |
215 | { | 245 | { |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index be38b573495a..4a48fe4b84b6 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -1846,6 +1846,11 @@ int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) | |||
1846 | GFP_KERNEL)) { | 1846 | GFP_KERNEL)) { |
1847 | SetPageUptodate(page); | 1847 | SetPageUptodate(page); |
1848 | unlock_page(page); | 1848 | unlock_page(page); |
1849 | /* | ||
1850 | * add_to_page_cache_lru() grabs an extra page refcount. | ||
1851 | * Drop it here to avoid leaking this page later. | ||
1852 | */ | ||
1853 | page_cache_release(page); | ||
1849 | } else | 1854 | } else |
1850 | __free_page(page); | 1855 | __free_page(page); |
1851 | 1856 | ||
diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c index 9a5ca03fa539..871d6eda8dba 100644 --- a/fs/nfs/nfs3acl.c +++ b/fs/nfs/nfs3acl.c | |||
@@ -80,7 +80,7 @@ struct posix_acl *nfs3_get_acl(struct inode *inode, int type) | |||
80 | } | 80 | } |
81 | 81 | ||
82 | if (res.acl_access != NULL) { | 82 | if (res.acl_access != NULL) { |
83 | if (posix_acl_equiv_mode(res.acl_access, NULL) || | 83 | if ((posix_acl_equiv_mode(res.acl_access, NULL) == 0) || |
84 | res.acl_access->a_count == 0) { | 84 | res.acl_access->a_count == 0) { |
85 | posix_acl_release(res.acl_access); | 85 | posix_acl_release(res.acl_access); |
86 | res.acl_access = NULL; | 86 | res.acl_access = NULL; |
@@ -113,7 +113,7 @@ getout: | |||
113 | return ERR_PTR(status); | 113 | return ERR_PTR(status); |
114 | } | 114 | } |
115 | 115 | ||
116 | int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl, | 116 | static int __nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl, |
117 | struct posix_acl *dfacl) | 117 | struct posix_acl *dfacl) |
118 | { | 118 | { |
119 | struct nfs_server *server = NFS_SERVER(inode); | 119 | struct nfs_server *server = NFS_SERVER(inode); |
@@ -198,6 +198,15 @@ out: | |||
198 | return status; | 198 | return status; |
199 | } | 199 | } |
200 | 200 | ||
201 | int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl, | ||
202 | struct posix_acl *dfacl) | ||
203 | { | ||
204 | int ret; | ||
205 | ret = __nfs3_proc_setacls(inode, acl, dfacl); | ||
206 | return (ret == -EOPNOTSUPP) ? 0 : ret; | ||
207 | |||
208 | } | ||
209 | |||
201 | int nfs3_set_acl(struct inode *inode, struct posix_acl *acl, int type) | 210 | int nfs3_set_acl(struct inode *inode, struct posix_acl *acl, int type) |
202 | { | 211 | { |
203 | struct posix_acl *alloc = NULL, *dfacl = NULL; | 212 | struct posix_acl *alloc = NULL, *dfacl = NULL; |
@@ -225,7 +234,7 @@ int nfs3_set_acl(struct inode *inode, struct posix_acl *acl, int type) | |||
225 | if (IS_ERR(alloc)) | 234 | if (IS_ERR(alloc)) |
226 | goto fail; | 235 | goto fail; |
227 | } | 236 | } |
228 | status = nfs3_proc_setacls(inode, acl, dfacl); | 237 | status = __nfs3_proc_setacls(inode, acl, dfacl); |
229 | posix_acl_release(alloc); | 238 | posix_acl_release(alloc); |
230 | return status; | 239 | return status; |
231 | 240 | ||
@@ -233,25 +242,6 @@ fail: | |||
233 | return PTR_ERR(alloc); | 242 | return PTR_ERR(alloc); |
234 | } | 243 | } |
235 | 244 | ||
236 | int nfs3_proc_set_default_acl(struct inode *dir, struct inode *inode, | ||
237 | umode_t mode) | ||
238 | { | ||
239 | struct posix_acl *default_acl, *acl; | ||
240 | int error; | ||
241 | |||
242 | error = posix_acl_create(dir, &mode, &default_acl, &acl); | ||
243 | if (error) | ||
244 | return (error == -EOPNOTSUPP) ? 0 : error; | ||
245 | |||
246 | error = nfs3_proc_setacls(inode, acl, default_acl); | ||
247 | |||
248 | if (acl) | ||
249 | posix_acl_release(acl); | ||
250 | if (default_acl) | ||
251 | posix_acl_release(default_acl); | ||
252 | return error; | ||
253 | } | ||
254 | |||
255 | const struct xattr_handler *nfs3_xattr_handlers[] = { | 245 | const struct xattr_handler *nfs3_xattr_handlers[] = { |
256 | &posix_acl_access_xattr_handler, | 246 | &posix_acl_access_xattr_handler, |
257 | &posix_acl_default_xattr_handler, | 247 | &posix_acl_default_xattr_handler, |
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index dbb3e1f30c68..860ad26a5590 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c | |||
@@ -170,7 +170,7 @@ void nfs41_shutdown_client(struct nfs_client *clp) | |||
170 | void nfs40_shutdown_client(struct nfs_client *clp) | 170 | void nfs40_shutdown_client(struct nfs_client *clp) |
171 | { | 171 | { |
172 | if (clp->cl_slot_tbl) { | 172 | if (clp->cl_slot_tbl) { |
173 | nfs4_release_slot_table(clp->cl_slot_tbl); | 173 | nfs4_shutdown_slot_table(clp->cl_slot_tbl); |
174 | kfree(clp->cl_slot_tbl); | 174 | kfree(clp->cl_slot_tbl); |
175 | } | 175 | } |
176 | } | 176 | } |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 42da6af77587..2da6a698b8f7 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -1620,15 +1620,15 @@ static void nfs4_open_confirm_prepare(struct rpc_task *task, void *calldata) | |||
1620 | { | 1620 | { |
1621 | struct nfs4_opendata *data = calldata; | 1621 | struct nfs4_opendata *data = calldata; |
1622 | 1622 | ||
1623 | nfs40_setup_sequence(data->o_arg.server, &data->o_arg.seq_args, | 1623 | nfs40_setup_sequence(data->o_arg.server, &data->c_arg.seq_args, |
1624 | &data->o_res.seq_res, task); | 1624 | &data->c_res.seq_res, task); |
1625 | } | 1625 | } |
1626 | 1626 | ||
1627 | static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata) | 1627 | static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata) |
1628 | { | 1628 | { |
1629 | struct nfs4_opendata *data = calldata; | 1629 | struct nfs4_opendata *data = calldata; |
1630 | 1630 | ||
1631 | nfs40_sequence_done(task, &data->o_res.seq_res); | 1631 | nfs40_sequence_done(task, &data->c_res.seq_res); |
1632 | 1632 | ||
1633 | data->rpc_status = task->tk_status; | 1633 | data->rpc_status = task->tk_status; |
1634 | if (data->rpc_status == 0) { | 1634 | if (data->rpc_status == 0) { |
@@ -1686,7 +1686,7 @@ static int _nfs4_proc_open_confirm(struct nfs4_opendata *data) | |||
1686 | }; | 1686 | }; |
1687 | int status; | 1687 | int status; |
1688 | 1688 | ||
1689 | nfs4_init_sequence(&data->o_arg.seq_args, &data->o_res.seq_res, 1); | 1689 | nfs4_init_sequence(&data->c_arg.seq_args, &data->c_res.seq_res, 1); |
1690 | kref_get(&data->kref); | 1690 | kref_get(&data->kref); |
1691 | data->rpc_done = 0; | 1691 | data->rpc_done = 0; |
1692 | data->rpc_status = 0; | 1692 | data->rpc_status = 0; |
diff --git a/fs/nfs/nfs4session.c b/fs/nfs/nfs4session.c index cf883c7ae053..e799dc3c3b1d 100644 --- a/fs/nfs/nfs4session.c +++ b/fs/nfs/nfs4session.c | |||
@@ -231,14 +231,23 @@ out: | |||
231 | return ret; | 231 | return ret; |
232 | } | 232 | } |
233 | 233 | ||
234 | /* | ||
235 | * nfs4_release_slot_table - release all slot table entries | ||
236 | */ | ||
237 | static void nfs4_release_slot_table(struct nfs4_slot_table *tbl) | ||
238 | { | ||
239 | nfs4_shrink_slot_table(tbl, 0); | ||
240 | } | ||
241 | |||
234 | /** | 242 | /** |
235 | * nfs4_release_slot_table - release resources attached to a slot table | 243 | * nfs4_shutdown_slot_table - release resources attached to a slot table |
236 | * @tbl: slot table to shut down | 244 | * @tbl: slot table to shut down |
237 | * | 245 | * |
238 | */ | 246 | */ |
239 | void nfs4_release_slot_table(struct nfs4_slot_table *tbl) | 247 | void nfs4_shutdown_slot_table(struct nfs4_slot_table *tbl) |
240 | { | 248 | { |
241 | nfs4_shrink_slot_table(tbl, 0); | 249 | nfs4_release_slot_table(tbl); |
250 | rpc_destroy_wait_queue(&tbl->slot_tbl_waitq); | ||
242 | } | 251 | } |
243 | 252 | ||
244 | /** | 253 | /** |
@@ -422,7 +431,7 @@ void nfs41_update_target_slotid(struct nfs4_slot_table *tbl, | |||
422 | spin_unlock(&tbl->slot_tbl_lock); | 431 | spin_unlock(&tbl->slot_tbl_lock); |
423 | } | 432 | } |
424 | 433 | ||
425 | static void nfs4_destroy_session_slot_tables(struct nfs4_session *session) | 434 | static void nfs4_release_session_slot_tables(struct nfs4_session *session) |
426 | { | 435 | { |
427 | nfs4_release_slot_table(&session->fc_slot_table); | 436 | nfs4_release_slot_table(&session->fc_slot_table); |
428 | nfs4_release_slot_table(&session->bc_slot_table); | 437 | nfs4_release_slot_table(&session->bc_slot_table); |
@@ -450,7 +459,7 @@ int nfs4_setup_session_slot_tables(struct nfs4_session *ses) | |||
450 | if (status && tbl->slots == NULL) | 459 | if (status && tbl->slots == NULL) |
451 | /* Fore and back channel share a connection so get | 460 | /* Fore and back channel share a connection so get |
452 | * both slot tables or neither */ | 461 | * both slot tables or neither */ |
453 | nfs4_destroy_session_slot_tables(ses); | 462 | nfs4_release_session_slot_tables(ses); |
454 | return status; | 463 | return status; |
455 | } | 464 | } |
456 | 465 | ||
@@ -470,6 +479,12 @@ struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp) | |||
470 | return session; | 479 | return session; |
471 | } | 480 | } |
472 | 481 | ||
482 | static void nfs4_destroy_session_slot_tables(struct nfs4_session *session) | ||
483 | { | ||
484 | nfs4_shutdown_slot_table(&session->fc_slot_table); | ||
485 | nfs4_shutdown_slot_table(&session->bc_slot_table); | ||
486 | } | ||
487 | |||
473 | void nfs4_destroy_session(struct nfs4_session *session) | 488 | void nfs4_destroy_session(struct nfs4_session *session) |
474 | { | 489 | { |
475 | struct rpc_xprt *xprt; | 490 | struct rpc_xprt *xprt; |
diff --git a/fs/nfs/nfs4session.h b/fs/nfs/nfs4session.h index 232306100651..b34ada9bc6a2 100644 --- a/fs/nfs/nfs4session.h +++ b/fs/nfs/nfs4session.h | |||
@@ -74,7 +74,7 @@ enum nfs4_session_state { | |||
74 | 74 | ||
75 | extern int nfs4_setup_slot_table(struct nfs4_slot_table *tbl, | 75 | extern int nfs4_setup_slot_table(struct nfs4_slot_table *tbl, |
76 | unsigned int max_reqs, const char *queue); | 76 | unsigned int max_reqs, const char *queue); |
77 | extern void nfs4_release_slot_table(struct nfs4_slot_table *tbl); | 77 | extern void nfs4_shutdown_slot_table(struct nfs4_slot_table *tbl); |
78 | extern struct nfs4_slot *nfs4_alloc_slot(struct nfs4_slot_table *tbl); | 78 | extern struct nfs4_slot *nfs4_alloc_slot(struct nfs4_slot_table *tbl); |
79 | extern void nfs4_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot); | 79 | extern void nfs4_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot); |
80 | extern void nfs4_slot_tbl_drain_complete(struct nfs4_slot_table *tbl); | 80 | extern void nfs4_slot_tbl_drain_complete(struct nfs4_slot_table *tbl); |
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c index d3a587144222..d190e33d0ec2 100644 --- a/fs/nfsd/nfs4acl.c +++ b/fs/nfsd/nfs4acl.c | |||
@@ -151,17 +151,15 @@ nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, | |||
151 | pacl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL); | 151 | pacl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL); |
152 | if (IS_ERR(pacl)) | 152 | if (IS_ERR(pacl)) |
153 | return PTR_ERR(pacl); | 153 | return PTR_ERR(pacl); |
154 | /* allocate for worst case: one (deny, allow) pair each: */ | ||
155 | size += 2 * pacl->a_count; | ||
156 | } | 154 | } |
155 | /* allocate for worst case: one (deny, allow) pair each: */ | ||
156 | size += 2 * pacl->a_count; | ||
157 | 157 | ||
158 | if (S_ISDIR(inode->i_mode)) { | 158 | if (S_ISDIR(inode->i_mode)) { |
159 | flags = NFS4_ACL_DIR; | 159 | flags = NFS4_ACL_DIR; |
160 | dpacl = get_acl(inode, ACL_TYPE_DEFAULT); | 160 | dpacl = get_acl(inode, ACL_TYPE_DEFAULT); |
161 | if (dpacl) | 161 | if (dpacl) |
162 | size += 2 * dpacl->a_count; | 162 | size += 2 * dpacl->a_count; |
163 | } else { | ||
164 | dpacl = NULL; | ||
165 | } | 163 | } |
166 | 164 | ||
167 | *acl = nfs4_acl_new(size); | 165 | *acl = nfs4_acl_new(size); |
@@ -170,8 +168,7 @@ nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, | |||
170 | goto out; | 168 | goto out; |
171 | } | 169 | } |
172 | 170 | ||
173 | if (pacl) | 171 | _posix_to_nfsv4_one(pacl, *acl, flags & ~NFS4_ACL_TYPE_DEFAULT); |
174 | _posix_to_nfsv4_one(pacl, *acl, flags & ~NFS4_ACL_TYPE_DEFAULT); | ||
175 | 172 | ||
176 | if (dpacl) | 173 | if (dpacl) |
177 | _posix_to_nfsv4_one(dpacl, *acl, flags | NFS4_ACL_TYPE_DEFAULT); | 174 | _posix_to_nfsv4_one(dpacl, *acl, flags | NFS4_ACL_TYPE_DEFAULT); |
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c index ea4ba9daeb47..db9bd8a31725 100644 --- a/fs/ntfs/file.c +++ b/fs/ntfs/file.c | |||
@@ -2134,7 +2134,7 @@ static ssize_t ntfs_file_aio_write(struct kiocb *iocb, const struct iovec *iov, | |||
2134 | ret = ntfs_file_aio_write_nolock(iocb, iov, nr_segs, &iocb->ki_pos); | 2134 | ret = ntfs_file_aio_write_nolock(iocb, iov, nr_segs, &iocb->ki_pos); |
2135 | mutex_unlock(&inode->i_mutex); | 2135 | mutex_unlock(&inode->i_mutex); |
2136 | if (ret > 0) { | 2136 | if (ret > 0) { |
2137 | int err = generic_write_sync(file, pos, ret); | 2137 | int err = generic_write_sync(file, iocb->ki_pos - ret, ret); |
2138 | if (err < 0) | 2138 | if (err < 0) |
2139 | ret = err; | 2139 | ret = err; |
2140 | } | 2140 | } |
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index 8750ae1b8636..e2edff38be52 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c | |||
@@ -4742,6 +4742,7 @@ int ocfs2_add_clusters_in_btree(handle_t *handle, | |||
4742 | enum ocfs2_alloc_restarted *reason_ret) | 4742 | enum ocfs2_alloc_restarted *reason_ret) |
4743 | { | 4743 | { |
4744 | int status = 0, err = 0; | 4744 | int status = 0, err = 0; |
4745 | int need_free = 0; | ||
4745 | int free_extents; | 4746 | int free_extents; |
4746 | enum ocfs2_alloc_restarted reason = RESTART_NONE; | 4747 | enum ocfs2_alloc_restarted reason = RESTART_NONE; |
4747 | u32 bit_off, num_bits; | 4748 | u32 bit_off, num_bits; |
@@ -4796,7 +4797,8 @@ int ocfs2_add_clusters_in_btree(handle_t *handle, | |||
4796 | OCFS2_JOURNAL_ACCESS_WRITE); | 4797 | OCFS2_JOURNAL_ACCESS_WRITE); |
4797 | if (status < 0) { | 4798 | if (status < 0) { |
4798 | mlog_errno(status); | 4799 | mlog_errno(status); |
4799 | goto leave; | 4800 | need_free = 1; |
4801 | goto bail; | ||
4800 | } | 4802 | } |
4801 | 4803 | ||
4802 | block = ocfs2_clusters_to_blocks(osb->sb, bit_off); | 4804 | block = ocfs2_clusters_to_blocks(osb->sb, bit_off); |
@@ -4807,7 +4809,8 @@ int ocfs2_add_clusters_in_btree(handle_t *handle, | |||
4807 | num_bits, flags, meta_ac); | 4809 | num_bits, flags, meta_ac); |
4808 | if (status < 0) { | 4810 | if (status < 0) { |
4809 | mlog_errno(status); | 4811 | mlog_errno(status); |
4810 | goto leave; | 4812 | need_free = 1; |
4813 | goto bail; | ||
4811 | } | 4814 | } |
4812 | 4815 | ||
4813 | ocfs2_journal_dirty(handle, et->et_root_bh); | 4816 | ocfs2_journal_dirty(handle, et->et_root_bh); |
@@ -4821,6 +4824,19 @@ int ocfs2_add_clusters_in_btree(handle_t *handle, | |||
4821 | reason = RESTART_TRANS; | 4824 | reason = RESTART_TRANS; |
4822 | } | 4825 | } |
4823 | 4826 | ||
4827 | bail: | ||
4828 | if (need_free) { | ||
4829 | if (data_ac->ac_which == OCFS2_AC_USE_LOCAL) | ||
4830 | ocfs2_free_local_alloc_bits(osb, handle, data_ac, | ||
4831 | bit_off, num_bits); | ||
4832 | else | ||
4833 | ocfs2_free_clusters(handle, | ||
4834 | data_ac->ac_inode, | ||
4835 | data_ac->ac_bh, | ||
4836 | ocfs2_clusters_to_blocks(osb->sb, bit_off), | ||
4837 | num_bits); | ||
4838 | } | ||
4839 | |||
4824 | leave: | 4840 | leave: |
4825 | if (reason_ret) | 4841 | if (reason_ret) |
4826 | *reason_ret = reason; | 4842 | *reason_ret = reason; |
@@ -6805,6 +6821,8 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode, | |||
6805 | struct buffer_head *di_bh) | 6821 | struct buffer_head *di_bh) |
6806 | { | 6822 | { |
6807 | int ret, i, has_data, num_pages = 0; | 6823 | int ret, i, has_data, num_pages = 0; |
6824 | int need_free = 0; | ||
6825 | u32 bit_off, num; | ||
6808 | handle_t *handle; | 6826 | handle_t *handle; |
6809 | u64 uninitialized_var(block); | 6827 | u64 uninitialized_var(block); |
6810 | struct ocfs2_inode_info *oi = OCFS2_I(inode); | 6828 | struct ocfs2_inode_info *oi = OCFS2_I(inode); |
@@ -6850,7 +6868,6 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode, | |||
6850 | } | 6868 | } |
6851 | 6869 | ||
6852 | if (has_data) { | 6870 | if (has_data) { |
6853 | u32 bit_off, num; | ||
6854 | unsigned int page_end; | 6871 | unsigned int page_end; |
6855 | u64 phys; | 6872 | u64 phys; |
6856 | 6873 | ||
@@ -6886,6 +6903,7 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode, | |||
6886 | ret = ocfs2_grab_eof_pages(inode, 0, end, pages, &num_pages); | 6903 | ret = ocfs2_grab_eof_pages(inode, 0, end, pages, &num_pages); |
6887 | if (ret) { | 6904 | if (ret) { |
6888 | mlog_errno(ret); | 6905 | mlog_errno(ret); |
6906 | need_free = 1; | ||
6889 | goto out_commit; | 6907 | goto out_commit; |
6890 | } | 6908 | } |
6891 | 6909 | ||
@@ -6896,6 +6914,7 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode, | |||
6896 | ret = ocfs2_read_inline_data(inode, pages[0], di_bh); | 6914 | ret = ocfs2_read_inline_data(inode, pages[0], di_bh); |
6897 | if (ret) { | 6915 | if (ret) { |
6898 | mlog_errno(ret); | 6916 | mlog_errno(ret); |
6917 | need_free = 1; | ||
6899 | goto out_commit; | 6918 | goto out_commit; |
6900 | } | 6919 | } |
6901 | 6920 | ||
@@ -6927,6 +6946,7 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode, | |||
6927 | ret = ocfs2_insert_extent(handle, &et, 0, block, 1, 0, NULL); | 6946 | ret = ocfs2_insert_extent(handle, &et, 0, block, 1, 0, NULL); |
6928 | if (ret) { | 6947 | if (ret) { |
6929 | mlog_errno(ret); | 6948 | mlog_errno(ret); |
6949 | need_free = 1; | ||
6930 | goto out_commit; | 6950 | goto out_commit; |
6931 | } | 6951 | } |
6932 | 6952 | ||
@@ -6938,6 +6958,18 @@ out_commit: | |||
6938 | dquot_free_space_nodirty(inode, | 6958 | dquot_free_space_nodirty(inode, |
6939 | ocfs2_clusters_to_bytes(osb->sb, 1)); | 6959 | ocfs2_clusters_to_bytes(osb->sb, 1)); |
6940 | 6960 | ||
6961 | if (need_free) { | ||
6962 | if (data_ac->ac_which == OCFS2_AC_USE_LOCAL) | ||
6963 | ocfs2_free_local_alloc_bits(osb, handle, data_ac, | ||
6964 | bit_off, num); | ||
6965 | else | ||
6966 | ocfs2_free_clusters(handle, | ||
6967 | data_ac->ac_inode, | ||
6968 | data_ac->ac_bh, | ||
6969 | ocfs2_clusters_to_blocks(osb->sb, bit_off), | ||
6970 | num); | ||
6971 | } | ||
6972 | |||
6941 | ocfs2_commit_trans(osb, handle); | 6973 | ocfs2_commit_trans(osb, handle); |
6942 | 6974 | ||
6943 | out_unlock: | 6975 | out_unlock: |
@@ -7126,7 +7158,7 @@ int ocfs2_truncate_inline(struct inode *inode, struct buffer_head *di_bh, | |||
7126 | if (end > i_size_read(inode)) | 7158 | if (end > i_size_read(inode)) |
7127 | end = i_size_read(inode); | 7159 | end = i_size_read(inode); |
7128 | 7160 | ||
7129 | BUG_ON(start >= end); | 7161 | BUG_ON(start > end); |
7130 | 7162 | ||
7131 | if (!(OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) || | 7163 | if (!(OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) || |
7132 | !(le16_to_cpu(di->i_dyn_features) & OCFS2_INLINE_DATA_FL) || | 7164 | !(le16_to_cpu(di->i_dyn_features) & OCFS2_INLINE_DATA_FL) || |
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index d77d71ead8d1..8450262bcf2a 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
@@ -185,6 +185,9 @@ static int ocfs2_sync_file(struct file *file, loff_t start, loff_t end, | |||
185 | file->f_path.dentry->d_name.name, | 185 | file->f_path.dentry->d_name.name, |
186 | (unsigned long long)datasync); | 186 | (unsigned long long)datasync); |
187 | 187 | ||
188 | if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb)) | ||
189 | return -EROFS; | ||
190 | |||
188 | err = filemap_write_and_wait_range(inode->i_mapping, start, end); | 191 | err = filemap_write_and_wait_range(inode->i_mapping, start, end); |
189 | if (err) | 192 | if (err) |
190 | return err; | 193 | return err; |
@@ -474,11 +477,6 @@ static int ocfs2_truncate_file(struct inode *inode, | |||
474 | goto bail; | 477 | goto bail; |
475 | } | 478 | } |
476 | 479 | ||
477 | /* lets handle the simple truncate cases before doing any more | ||
478 | * cluster locking. */ | ||
479 | if (new_i_size == le64_to_cpu(fe->i_size)) | ||
480 | goto bail; | ||
481 | |||
482 | down_write(&OCFS2_I(inode)->ip_alloc_sem); | 480 | down_write(&OCFS2_I(inode)->ip_alloc_sem); |
483 | 481 | ||
484 | ocfs2_resv_discard(&osb->osb_la_resmap, | 482 | ocfs2_resv_discard(&osb->osb_la_resmap, |
@@ -718,7 +716,8 @@ leave: | |||
718 | * While a write will already be ordering the data, a truncate will not. | 716 | * While a write will already be ordering the data, a truncate will not. |
719 | * Thus, we need to explicitly order the zeroed pages. | 717 | * Thus, we need to explicitly order the zeroed pages. |
720 | */ | 718 | */ |
721 | static handle_t *ocfs2_zero_start_ordered_transaction(struct inode *inode) | 719 | static handle_t *ocfs2_zero_start_ordered_transaction(struct inode *inode, |
720 | struct buffer_head *di_bh) | ||
722 | { | 721 | { |
723 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 722 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
724 | handle_t *handle = NULL; | 723 | handle_t *handle = NULL; |
@@ -735,7 +734,14 @@ static handle_t *ocfs2_zero_start_ordered_transaction(struct inode *inode) | |||
735 | } | 734 | } |
736 | 735 | ||
737 | ret = ocfs2_jbd2_file_inode(handle, inode); | 736 | ret = ocfs2_jbd2_file_inode(handle, inode); |
738 | if (ret < 0) | 737 | if (ret < 0) { |
738 | mlog_errno(ret); | ||
739 | goto out; | ||
740 | } | ||
741 | |||
742 | ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), di_bh, | ||
743 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
744 | if (ret) | ||
739 | mlog_errno(ret); | 745 | mlog_errno(ret); |
740 | 746 | ||
741 | out: | 747 | out: |
@@ -751,7 +757,7 @@ out: | |||
751 | * to be too fragile to do exactly what we need without us having to | 757 | * to be too fragile to do exactly what we need without us having to |
752 | * worry about recursive locking in ->write_begin() and ->write_end(). */ | 758 | * worry about recursive locking in ->write_begin() and ->write_end(). */ |
753 | static int ocfs2_write_zero_page(struct inode *inode, u64 abs_from, | 759 | static int ocfs2_write_zero_page(struct inode *inode, u64 abs_from, |
754 | u64 abs_to) | 760 | u64 abs_to, struct buffer_head *di_bh) |
755 | { | 761 | { |
756 | struct address_space *mapping = inode->i_mapping; | 762 | struct address_space *mapping = inode->i_mapping; |
757 | struct page *page; | 763 | struct page *page; |
@@ -759,6 +765,7 @@ static int ocfs2_write_zero_page(struct inode *inode, u64 abs_from, | |||
759 | handle_t *handle = NULL; | 765 | handle_t *handle = NULL; |
760 | int ret = 0; | 766 | int ret = 0; |
761 | unsigned zero_from, zero_to, block_start, block_end; | 767 | unsigned zero_from, zero_to, block_start, block_end; |
768 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; | ||
762 | 769 | ||
763 | BUG_ON(abs_from >= abs_to); | 770 | BUG_ON(abs_from >= abs_to); |
764 | BUG_ON(abs_to > (((u64)index + 1) << PAGE_CACHE_SHIFT)); | 771 | BUG_ON(abs_to > (((u64)index + 1) << PAGE_CACHE_SHIFT)); |
@@ -801,7 +808,8 @@ static int ocfs2_write_zero_page(struct inode *inode, u64 abs_from, | |||
801 | } | 808 | } |
802 | 809 | ||
803 | if (!handle) { | 810 | if (!handle) { |
804 | handle = ocfs2_zero_start_ordered_transaction(inode); | 811 | handle = ocfs2_zero_start_ordered_transaction(inode, |
812 | di_bh); | ||
805 | if (IS_ERR(handle)) { | 813 | if (IS_ERR(handle)) { |
806 | ret = PTR_ERR(handle); | 814 | ret = PTR_ERR(handle); |
807 | handle = NULL; | 815 | handle = NULL; |
@@ -818,8 +826,22 @@ static int ocfs2_write_zero_page(struct inode *inode, u64 abs_from, | |||
818 | ret = 0; | 826 | ret = 0; |
819 | } | 827 | } |
820 | 828 | ||
821 | if (handle) | 829 | if (handle) { |
830 | /* | ||
831 | * fs-writeback will release the dirty pages without page lock | ||
832 | * whose offset are over inode size, the release happens at | ||
833 | * block_write_full_page_endio(). | ||
834 | */ | ||
835 | i_size_write(inode, abs_to); | ||
836 | inode->i_blocks = ocfs2_inode_sector_count(inode); | ||
837 | di->i_size = cpu_to_le64((u64)i_size_read(inode)); | ||
838 | inode->i_mtime = inode->i_ctime = CURRENT_TIME; | ||
839 | di->i_mtime = di->i_ctime = cpu_to_le64(inode->i_mtime.tv_sec); | ||
840 | di->i_ctime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec); | ||
841 | di->i_mtime_nsec = di->i_ctime_nsec; | ||
842 | ocfs2_journal_dirty(handle, di_bh); | ||
822 | ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle); | 843 | ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle); |
844 | } | ||
823 | 845 | ||
824 | out_unlock: | 846 | out_unlock: |
825 | unlock_page(page); | 847 | unlock_page(page); |
@@ -915,7 +937,7 @@ out: | |||
915 | * has made sure that the entire range needs zeroing. | 937 | * has made sure that the entire range needs zeroing. |
916 | */ | 938 | */ |
917 | static int ocfs2_zero_extend_range(struct inode *inode, u64 range_start, | 939 | static int ocfs2_zero_extend_range(struct inode *inode, u64 range_start, |
918 | u64 range_end) | 940 | u64 range_end, struct buffer_head *di_bh) |
919 | { | 941 | { |
920 | int rc = 0; | 942 | int rc = 0; |
921 | u64 next_pos; | 943 | u64 next_pos; |
@@ -931,7 +953,7 @@ static int ocfs2_zero_extend_range(struct inode *inode, u64 range_start, | |||
931 | next_pos = (zero_pos & PAGE_CACHE_MASK) + PAGE_CACHE_SIZE; | 953 | next_pos = (zero_pos & PAGE_CACHE_MASK) + PAGE_CACHE_SIZE; |
932 | if (next_pos > range_end) | 954 | if (next_pos > range_end) |
933 | next_pos = range_end; | 955 | next_pos = range_end; |
934 | rc = ocfs2_write_zero_page(inode, zero_pos, next_pos); | 956 | rc = ocfs2_write_zero_page(inode, zero_pos, next_pos, di_bh); |
935 | if (rc < 0) { | 957 | if (rc < 0) { |
936 | mlog_errno(rc); | 958 | mlog_errno(rc); |
937 | break; | 959 | break; |
@@ -977,7 +999,7 @@ int ocfs2_zero_extend(struct inode *inode, struct buffer_head *di_bh, | |||
977 | range_end = zero_to_size; | 999 | range_end = zero_to_size; |
978 | 1000 | ||
979 | ret = ocfs2_zero_extend_range(inode, range_start, | 1001 | ret = ocfs2_zero_extend_range(inode, range_start, |
980 | range_end); | 1002 | range_end, di_bh); |
981 | if (ret) { | 1003 | if (ret) { |
982 | mlog_errno(ret); | 1004 | mlog_errno(ret); |
983 | break; | 1005 | break; |
@@ -1145,14 +1167,14 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) | |||
1145 | goto bail_unlock_rw; | 1167 | goto bail_unlock_rw; |
1146 | } | 1168 | } |
1147 | 1169 | ||
1148 | if (size_change && attr->ia_size != i_size_read(inode)) { | 1170 | if (size_change) { |
1149 | status = inode_newsize_ok(inode, attr->ia_size); | 1171 | status = inode_newsize_ok(inode, attr->ia_size); |
1150 | if (status) | 1172 | if (status) |
1151 | goto bail_unlock; | 1173 | goto bail_unlock; |
1152 | 1174 | ||
1153 | inode_dio_wait(inode); | 1175 | inode_dio_wait(inode); |
1154 | 1176 | ||
1155 | if (i_size_read(inode) > attr->ia_size) { | 1177 | if (i_size_read(inode) >= attr->ia_size) { |
1156 | if (ocfs2_should_order_data(inode)) { | 1178 | if (ocfs2_should_order_data(inode)) { |
1157 | status = ocfs2_begin_ordered_truncate(inode, | 1179 | status = ocfs2_begin_ordered_truncate(inode, |
1158 | attr->ia_size); | 1180 | attr->ia_size); |
diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c index cd5496b7a0a3..044013455621 100644 --- a/fs/ocfs2/localalloc.c +++ b/fs/ocfs2/localalloc.c | |||
@@ -781,6 +781,48 @@ bail: | |||
781 | return status; | 781 | return status; |
782 | } | 782 | } |
783 | 783 | ||
784 | int ocfs2_free_local_alloc_bits(struct ocfs2_super *osb, | ||
785 | handle_t *handle, | ||
786 | struct ocfs2_alloc_context *ac, | ||
787 | u32 bit_off, | ||
788 | u32 num_bits) | ||
789 | { | ||
790 | int status, start; | ||
791 | u32 clear_bits; | ||
792 | struct inode *local_alloc_inode; | ||
793 | void *bitmap; | ||
794 | struct ocfs2_dinode *alloc; | ||
795 | struct ocfs2_local_alloc *la; | ||
796 | |||
797 | BUG_ON(ac->ac_which != OCFS2_AC_USE_LOCAL); | ||
798 | |||
799 | local_alloc_inode = ac->ac_inode; | ||
800 | alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data; | ||
801 | la = OCFS2_LOCAL_ALLOC(alloc); | ||
802 | |||
803 | bitmap = la->la_bitmap; | ||
804 | start = bit_off - le32_to_cpu(la->la_bm_off); | ||
805 | clear_bits = num_bits; | ||
806 | |||
807 | status = ocfs2_journal_access_di(handle, | ||
808 | INODE_CACHE(local_alloc_inode), | ||
809 | osb->local_alloc_bh, | ||
810 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
811 | if (status < 0) { | ||
812 | mlog_errno(status); | ||
813 | goto bail; | ||
814 | } | ||
815 | |||
816 | while (clear_bits--) | ||
817 | ocfs2_clear_bit(start++, bitmap); | ||
818 | |||
819 | le32_add_cpu(&alloc->id1.bitmap1.i_used, -num_bits); | ||
820 | ocfs2_journal_dirty(handle, osb->local_alloc_bh); | ||
821 | |||
822 | bail: | ||
823 | return status; | ||
824 | } | ||
825 | |||
784 | static u32 ocfs2_local_alloc_count_bits(struct ocfs2_dinode *alloc) | 826 | static u32 ocfs2_local_alloc_count_bits(struct ocfs2_dinode *alloc) |
785 | { | 827 | { |
786 | u32 count; | 828 | u32 count; |
diff --git a/fs/ocfs2/localalloc.h b/fs/ocfs2/localalloc.h index 1be9b5864460..44a7d1fb2dec 100644 --- a/fs/ocfs2/localalloc.h +++ b/fs/ocfs2/localalloc.h | |||
@@ -55,6 +55,12 @@ int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb, | |||
55 | u32 *bit_off, | 55 | u32 *bit_off, |
56 | u32 *num_bits); | 56 | u32 *num_bits); |
57 | 57 | ||
58 | int ocfs2_free_local_alloc_bits(struct ocfs2_super *osb, | ||
59 | handle_t *handle, | ||
60 | struct ocfs2_alloc_context *ac, | ||
61 | u32 bit_off, | ||
62 | u32 num_bits); | ||
63 | |||
58 | void ocfs2_local_alloc_seen_free_bits(struct ocfs2_super *osb, | 64 | void ocfs2_local_alloc_seen_free_bits(struct ocfs2_super *osb, |
59 | unsigned int num_clusters); | 65 | unsigned int num_clusters); |
60 | void ocfs2_la_enable_worker(struct work_struct *work); | 66 | void ocfs2_la_enable_worker(struct work_struct *work); |
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index f4d609be9400..3683643f3f0e 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c | |||
@@ -664,6 +664,7 @@ static int ocfs2_link(struct dentry *old_dentry, | |||
664 | struct ocfs2_super *osb = OCFS2_SB(dir->i_sb); | 664 | struct ocfs2_super *osb = OCFS2_SB(dir->i_sb); |
665 | struct ocfs2_dir_lookup_result lookup = { NULL, }; | 665 | struct ocfs2_dir_lookup_result lookup = { NULL, }; |
666 | sigset_t oldset; | 666 | sigset_t oldset; |
667 | u64 old_de_ino; | ||
667 | 668 | ||
668 | trace_ocfs2_link((unsigned long long)OCFS2_I(inode)->ip_blkno, | 669 | trace_ocfs2_link((unsigned long long)OCFS2_I(inode)->ip_blkno, |
669 | old_dentry->d_name.len, old_dentry->d_name.name, | 670 | old_dentry->d_name.len, old_dentry->d_name.name, |
@@ -686,6 +687,22 @@ static int ocfs2_link(struct dentry *old_dentry, | |||
686 | goto out; | 687 | goto out; |
687 | } | 688 | } |
688 | 689 | ||
690 | err = ocfs2_lookup_ino_from_name(dir, old_dentry->d_name.name, | ||
691 | old_dentry->d_name.len, &old_de_ino); | ||
692 | if (err) { | ||
693 | err = -ENOENT; | ||
694 | goto out; | ||
695 | } | ||
696 | |||
697 | /* | ||
698 | * Check whether another node removed the source inode while we | ||
699 | * were in the vfs. | ||
700 | */ | ||
701 | if (old_de_ino != OCFS2_I(inode)->ip_blkno) { | ||
702 | err = -ENOENT; | ||
703 | goto out; | ||
704 | } | ||
705 | |||
689 | err = ocfs2_check_dir_for_entry(dir, dentry->d_name.name, | 706 | err = ocfs2_check_dir_for_entry(dir, dentry->d_name.name, |
690 | dentry->d_name.len); | 707 | dentry->d_name.len); |
691 | if (err) | 708 | if (err) |
diff --git a/fs/posix_acl.c b/fs/posix_acl.c index 38bae5a0ea25..11c54fd51e16 100644 --- a/fs/posix_acl.c +++ b/fs/posix_acl.c | |||
@@ -521,8 +521,11 @@ posix_acl_chmod(struct inode *inode, umode_t mode) | |||
521 | return -EOPNOTSUPP; | 521 | return -EOPNOTSUPP; |
522 | 522 | ||
523 | acl = get_acl(inode, ACL_TYPE_ACCESS); | 523 | acl = get_acl(inode, ACL_TYPE_ACCESS); |
524 | if (IS_ERR_OR_NULL(acl)) | 524 | if (IS_ERR_OR_NULL(acl)) { |
525 | if (acl == ERR_PTR(-EOPNOTSUPP)) | ||
526 | return 0; | ||
525 | return PTR_ERR(acl); | 527 | return PTR_ERR(acl); |
528 | } | ||
526 | 529 | ||
527 | ret = __posix_acl_chmod(&acl, GFP_KERNEL, mode); | 530 | ret = __posix_acl_chmod(&acl, GFP_KERNEL, mode); |
528 | if (ret) | 531 | if (ret) |
@@ -544,14 +547,15 @@ posix_acl_create(struct inode *dir, umode_t *mode, | |||
544 | goto no_acl; | 547 | goto no_acl; |
545 | 548 | ||
546 | p = get_acl(dir, ACL_TYPE_DEFAULT); | 549 | p = get_acl(dir, ACL_TYPE_DEFAULT); |
547 | if (IS_ERR(p)) | 550 | if (IS_ERR(p)) { |
551 | if (p == ERR_PTR(-EOPNOTSUPP)) | ||
552 | goto apply_umask; | ||
548 | return PTR_ERR(p); | 553 | return PTR_ERR(p); |
549 | |||
550 | if (!p) { | ||
551 | *mode &= ~current_umask(); | ||
552 | goto no_acl; | ||
553 | } | 554 | } |
554 | 555 | ||
556 | if (!p) | ||
557 | goto apply_umask; | ||
558 | |||
555 | *acl = posix_acl_clone(p, GFP_NOFS); | 559 | *acl = posix_acl_clone(p, GFP_NOFS); |
556 | if (!*acl) | 560 | if (!*acl) |
557 | return -ENOMEM; | 561 | return -ENOMEM; |
@@ -575,6 +579,8 @@ posix_acl_create(struct inode *dir, umode_t *mode, | |||
575 | } | 579 | } |
576 | return 0; | 580 | return 0; |
577 | 581 | ||
582 | apply_umask: | ||
583 | *mode &= ~current_umask(); | ||
578 | no_acl: | 584 | no_acl: |
579 | *default_acl = NULL; | 585 | *default_acl = NULL; |
580 | *acl = NULL; | 586 | *acl = NULL; |
diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c index 2ca7ba047f04..88d4585b30f1 100644 --- a/fs/proc/vmcore.c +++ b/fs/proc/vmcore.c | |||
@@ -468,17 +468,24 @@ static int __init update_note_header_size_elf64(const Elf64_Ehdr *ehdr_ptr) | |||
468 | return rc; | 468 | return rc; |
469 | } | 469 | } |
470 | nhdr_ptr = notes_section; | 470 | nhdr_ptr = notes_section; |
471 | while (real_sz < max_sz) { | 471 | while (nhdr_ptr->n_namesz != 0) { |
472 | if (nhdr_ptr->n_namesz == 0) | ||
473 | break; | ||
474 | sz = sizeof(Elf64_Nhdr) + | 472 | sz = sizeof(Elf64_Nhdr) + |
475 | ((nhdr_ptr->n_namesz + 3) & ~3) + | 473 | ((nhdr_ptr->n_namesz + 3) & ~3) + |
476 | ((nhdr_ptr->n_descsz + 3) & ~3); | 474 | ((nhdr_ptr->n_descsz + 3) & ~3); |
475 | if ((real_sz + sz) > max_sz) { | ||
476 | pr_warn("Warning: Exceeded p_memsz, dropping PT_NOTE entry n_namesz=0x%x, n_descsz=0x%x\n", | ||
477 | nhdr_ptr->n_namesz, nhdr_ptr->n_descsz); | ||
478 | break; | ||
479 | } | ||
477 | real_sz += sz; | 480 | real_sz += sz; |
478 | nhdr_ptr = (Elf64_Nhdr*)((char*)nhdr_ptr + sz); | 481 | nhdr_ptr = (Elf64_Nhdr*)((char*)nhdr_ptr + sz); |
479 | } | 482 | } |
480 | kfree(notes_section); | 483 | kfree(notes_section); |
481 | phdr_ptr->p_memsz = real_sz; | 484 | phdr_ptr->p_memsz = real_sz; |
485 | if (real_sz == 0) { | ||
486 | pr_warn("Warning: Zero PT_NOTE entries found\n"); | ||
487 | return -EINVAL; | ||
488 | } | ||
482 | } | 489 | } |
483 | 490 | ||
484 | return 0; | 491 | return 0; |
@@ -648,17 +655,24 @@ static int __init update_note_header_size_elf32(const Elf32_Ehdr *ehdr_ptr) | |||
648 | return rc; | 655 | return rc; |
649 | } | 656 | } |
650 | nhdr_ptr = notes_section; | 657 | nhdr_ptr = notes_section; |
651 | while (real_sz < max_sz) { | 658 | while (nhdr_ptr->n_namesz != 0) { |
652 | if (nhdr_ptr->n_namesz == 0) | ||
653 | break; | ||
654 | sz = sizeof(Elf32_Nhdr) + | 659 | sz = sizeof(Elf32_Nhdr) + |
655 | ((nhdr_ptr->n_namesz + 3) & ~3) + | 660 | ((nhdr_ptr->n_namesz + 3) & ~3) + |
656 | ((nhdr_ptr->n_descsz + 3) & ~3); | 661 | ((nhdr_ptr->n_descsz + 3) & ~3); |
662 | if ((real_sz + sz) > max_sz) { | ||
663 | pr_warn("Warning: Exceeded p_memsz, dropping PT_NOTE entry n_namesz=0x%x, n_descsz=0x%x\n", | ||
664 | nhdr_ptr->n_namesz, nhdr_ptr->n_descsz); | ||
665 | break; | ||
666 | } | ||
657 | real_sz += sz; | 667 | real_sz += sz; |
658 | nhdr_ptr = (Elf32_Nhdr*)((char*)nhdr_ptr + sz); | 668 | nhdr_ptr = (Elf32_Nhdr*)((char*)nhdr_ptr + sz); |
659 | } | 669 | } |
660 | kfree(notes_section); | 670 | kfree(notes_section); |
661 | phdr_ptr->p_memsz = real_sz; | 671 | phdr_ptr->p_memsz = real_sz; |
672 | if (real_sz == 0) { | ||
673 | pr_warn("Warning: Zero PT_NOTE entries found\n"); | ||
674 | return -EINVAL; | ||
675 | } | ||
662 | } | 676 | } |
663 | 677 | ||
664 | return 0; | 678 | return 0; |
@@ -222,23 +222,6 @@ SYSCALL_DEFINE1(fdatasync, unsigned int, fd) | |||
222 | return do_fsync(fd, 1); | 222 | return do_fsync(fd, 1); |
223 | } | 223 | } |
224 | 224 | ||
225 | /** | ||
226 | * generic_write_sync - perform syncing after a write if file / inode is sync | ||
227 | * @file: file to which the write happened | ||
228 | * @pos: offset where the write started | ||
229 | * @count: length of the write | ||
230 | * | ||
231 | * This is just a simple wrapper about our general syncing function. | ||
232 | */ | ||
233 | int generic_write_sync(struct file *file, loff_t pos, loff_t count) | ||
234 | { | ||
235 | if (!(file->f_flags & O_DSYNC) && !IS_SYNC(file->f_mapping->host)) | ||
236 | return 0; | ||
237 | return vfs_fsync_range(file, pos, pos + count - 1, | ||
238 | (file->f_flags & __O_SYNC) ? 0 : 1); | ||
239 | } | ||
240 | EXPORT_SYMBOL(generic_write_sync); | ||
241 | |||
242 | /* | 225 | /* |
243 | * sys_sync_file_range() permits finely controlled syncing over a segment of | 226 | * sys_sync_file_range() permits finely controlled syncing over a segment of |
244 | * a file in the range offset .. (offset+nbytes-1) inclusive. If nbytes is | 227 | * a file in the range offset .. (offset+nbytes-1) inclusive. If nbytes is |
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 2e7989e3a2d6..64b48eade91d 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c | |||
@@ -799,7 +799,7 @@ xfs_file_aio_write( | |||
799 | XFS_STATS_ADD(xs_write_bytes, ret); | 799 | XFS_STATS_ADD(xs_write_bytes, ret); |
800 | 800 | ||
801 | /* Handle various SYNC-type writes */ | 801 | /* Handle various SYNC-type writes */ |
802 | err = generic_write_sync(file, pos, ret); | 802 | err = generic_write_sync(file, iocb->ki_pos - ret, ret); |
803 | if (err < 0) | 803 | if (err < 0) |
804 | ret = err; | 804 | ret = err; |
805 | } | 805 | } |