diff options
Diffstat (limited to 'fs')
45 files changed, 429 insertions, 192 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..5215f04260b2 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) |
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..184e9cb39647 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 | ||
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index b0134892dc70..383ab455bfa7 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
| @@ -4525,7 +4525,7 @@ static int btrfs_ioctl_set_fslabel(struct file *file, void __user *arg) | |||
| 4525 | spin_lock(&root->fs_info->super_lock); | 4525 | spin_lock(&root->fs_info->super_lock); |
| 4526 | strcpy(super_block->label, label); | 4526 | strcpy(super_block->label, label); |
| 4527 | spin_unlock(&root->fs_info->super_lock); | 4527 | spin_unlock(&root->fs_info->super_lock); |
| 4528 | ret = btrfs_end_transaction(trans, root); | 4528 | ret = btrfs_commit_transaction(trans, root); |
| 4529 | 4529 | ||
| 4530 | out_unlock: | 4530 | out_unlock: |
| 4531 | mnt_drop_write_file(file); | 4531 | mnt_drop_write_file(file); |
| @@ -4668,7 +4668,7 @@ static int btrfs_ioctl_set_features(struct file *file, void __user *arg) | |||
| 4668 | if (ret) | 4668 | if (ret) |
| 4669 | return ret; | 4669 | return ret; |
| 4670 | 4670 | ||
| 4671 | trans = btrfs_start_transaction(root, 1); | 4671 | trans = btrfs_start_transaction(root, 0); |
| 4672 | if (IS_ERR(trans)) | 4672 | if (IS_ERR(trans)) |
| 4673 | return PTR_ERR(trans); | 4673 | return PTR_ERR(trans); |
| 4674 | 4674 | ||
| @@ -4689,7 +4689,7 @@ static int btrfs_ioctl_set_features(struct file *file, void __user *arg) | |||
| 4689 | btrfs_set_super_incompat_flags(super_block, newflags); | 4689 | btrfs_set_super_incompat_flags(super_block, newflags); |
| 4690 | spin_unlock(&root->fs_info->super_lock); | 4690 | spin_unlock(&root->fs_info->super_lock); |
| 4691 | 4691 | ||
| 4692 | return btrfs_end_transaction(trans, root); | 4692 | return btrfs_commit_transaction(trans, root); |
| 4693 | } | 4693 | } |
| 4694 | 4694 | ||
| 4695 | long btrfs_ioctl(struct file *file, unsigned int | 4695 | long btrfs_ioctl(struct file *file, unsigned int |
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index 730dce395858..9c8d1a3fdc3a 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, |
| @@ -2774,8 +2774,6 @@ static int add_waiting_dir_move(struct send_ctx *sctx, u64 ino) | |||
| 2774 | return 0; | 2774 | return 0; |
| 2775 | } | 2775 | } |
| 2776 | 2776 | ||
| 2777 | #ifdef CONFIG_BTRFS_ASSERT | ||
| 2778 | |||
| 2779 | static int del_waiting_dir_move(struct send_ctx *sctx, u64 ino) | 2777 | static int del_waiting_dir_move(struct send_ctx *sctx, u64 ino) |
| 2780 | { | 2778 | { |
| 2781 | struct rb_node *n = sctx->waiting_dir_moves.rb_node; | 2779 | struct rb_node *n = sctx->waiting_dir_moves.rb_node; |
| @@ -2796,8 +2794,6 @@ static int del_waiting_dir_move(struct send_ctx *sctx, u64 ino) | |||
| 2796 | return -ENOENT; | 2794 | return -ENOENT; |
| 2797 | } | 2795 | } |
| 2798 | 2796 | ||
| 2799 | #endif | ||
| 2800 | |||
| 2801 | static int add_pending_dir_move(struct send_ctx *sctx, u64 parent_ino) | 2797 | static int add_pending_dir_move(struct send_ctx *sctx, u64 parent_ino) |
| 2802 | { | 2798 | { |
| 2803 | struct rb_node **p = &sctx->pending_dir_moves.rb_node; | 2799 | struct rb_node **p = &sctx->pending_dir_moves.rb_node; |
| @@ -2902,7 +2898,9 @@ static int apply_dir_move(struct send_ctx *sctx, struct pending_dir_move *pm) | |||
| 2902 | } | 2898 | } |
| 2903 | 2899 | ||
| 2904 | sctx->send_progress = sctx->cur_ino + 1; | 2900 | sctx->send_progress = sctx->cur_ino + 1; |
| 2905 | ASSERT(del_waiting_dir_move(sctx, pm->ino) == 0); | 2901 | ret = del_waiting_dir_move(sctx, pm->ino); |
| 2902 | ASSERT(ret == 0); | ||
| 2903 | |||
| 2906 | ret = get_cur_path(sctx, pm->ino, pm->gen, to_path); | 2904 | ret = get_cur_path(sctx, pm->ino, pm->gen, to_path); |
| 2907 | if (ret < 0) | 2905 | if (ret < 0) |
| 2908 | goto out; | 2906 | goto out; |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index c02f63356895..97cc24198554 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
| @@ -1996,7 +1996,7 @@ static void __exit exit_btrfs_fs(void) | |||
| 1996 | btrfs_hash_exit(); | 1996 | btrfs_hash_exit(); |
| 1997 | } | 1997 | } |
| 1998 | 1998 | ||
| 1999 | module_init(init_btrfs_fs) | 1999 | late_initcall(init_btrfs_fs); |
| 2000 | module_exit(exit_btrfs_fs) | 2000 | module_exit(exit_btrfs_fs) |
| 2001 | 2001 | ||
| 2002 | MODULE_LICENSE("GPL"); | 2002 | MODULE_LICENSE("GPL"); |
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 | } |
