diff options
Diffstat (limited to 'fs')
69 files changed, 911 insertions, 1015 deletions
diff --git a/fs/bio-integrity.c b/fs/bio-integrity.c index 0bad24ddc2e7..0129b78a6908 100644 --- a/fs/bio-integrity.c +++ b/fs/bio-integrity.c | |||
| @@ -114,6 +114,14 @@ void bio_integrity_free(struct bio *bio) | |||
| 114 | } | 114 | } |
| 115 | EXPORT_SYMBOL(bio_integrity_free); | 115 | EXPORT_SYMBOL(bio_integrity_free); |
| 116 | 116 | ||
| 117 | static inline unsigned int bip_integrity_vecs(struct bio_integrity_payload *bip) | ||
| 118 | { | ||
| 119 | if (bip->bip_slab == BIO_POOL_NONE) | ||
| 120 | return BIP_INLINE_VECS; | ||
| 121 | |||
| 122 | return bvec_nr_vecs(bip->bip_slab); | ||
| 123 | } | ||
| 124 | |||
| 117 | /** | 125 | /** |
| 118 | * bio_integrity_add_page - Attach integrity metadata | 126 | * bio_integrity_add_page - Attach integrity metadata |
| 119 | * @bio: bio to update | 127 | * @bio: bio to update |
| @@ -129,7 +137,7 @@ int bio_integrity_add_page(struct bio *bio, struct page *page, | |||
| 129 | struct bio_integrity_payload *bip = bio->bi_integrity; | 137 | struct bio_integrity_payload *bip = bio->bi_integrity; |
| 130 | struct bio_vec *iv; | 138 | struct bio_vec *iv; |
| 131 | 139 | ||
| 132 | if (bip->bip_vcnt >= bvec_nr_vecs(bip->bip_slab)) { | 140 | if (bip->bip_vcnt >= bip_integrity_vecs(bip)) { |
| 133 | printk(KERN_ERR "%s: bip_vec full\n", __func__); | 141 | printk(KERN_ERR "%s: bip_vec full\n", __func__); |
| 134 | return 0; | 142 | return 0; |
| 135 | } | 143 | } |
| @@ -226,7 +234,8 @@ unsigned int bio_integrity_tag_size(struct bio *bio) | |||
| 226 | } | 234 | } |
| 227 | EXPORT_SYMBOL(bio_integrity_tag_size); | 235 | EXPORT_SYMBOL(bio_integrity_tag_size); |
| 228 | 236 | ||
| 229 | int bio_integrity_tag(struct bio *bio, void *tag_buf, unsigned int len, int set) | 237 | static int bio_integrity_tag(struct bio *bio, void *tag_buf, unsigned int len, |
| 238 | int set) | ||
| 230 | { | 239 | { |
| 231 | struct bio_integrity_payload *bip = bio->bi_integrity; | 240 | struct bio_integrity_payload *bip = bio->bi_integrity; |
| 232 | struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev); | 241 | struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev); |
| @@ -611,7 +611,6 @@ EXPORT_SYMBOL(bio_clone_fast); | |||
| 611 | struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask, | 611 | struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask, |
| 612 | struct bio_set *bs) | 612 | struct bio_set *bs) |
| 613 | { | 613 | { |
| 614 | unsigned nr_iovecs = 0; | ||
| 615 | struct bvec_iter iter; | 614 | struct bvec_iter iter; |
| 616 | struct bio_vec bv; | 615 | struct bio_vec bv; |
| 617 | struct bio *bio; | 616 | struct bio *bio; |
| @@ -638,10 +637,7 @@ struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask, | |||
| 638 | * __bio_clone_fast() anyways. | 637 | * __bio_clone_fast() anyways. |
| 639 | */ | 638 | */ |
| 640 | 639 | ||
| 641 | bio_for_each_segment(bv, bio_src, iter) | 640 | bio = bio_alloc_bioset(gfp_mask, bio_segments(bio_src), bs); |
| 642 | nr_iovecs++; | ||
| 643 | |||
| 644 | bio = bio_alloc_bioset(gfp_mask, nr_iovecs, bs); | ||
| 645 | if (!bio) | 641 | if (!bio) |
| 646 | return NULL; | 642 | return NULL; |
| 647 | 643 | ||
| @@ -650,9 +646,18 @@ struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask, | |||
| 650 | bio->bi_iter.bi_sector = bio_src->bi_iter.bi_sector; | 646 | bio->bi_iter.bi_sector = bio_src->bi_iter.bi_sector; |
| 651 | bio->bi_iter.bi_size = bio_src->bi_iter.bi_size; | 647 | bio->bi_iter.bi_size = bio_src->bi_iter.bi_size; |
| 652 | 648 | ||
| 649 | if (bio->bi_rw & REQ_DISCARD) | ||
| 650 | goto integrity_clone; | ||
| 651 | |||
| 652 | if (bio->bi_rw & REQ_WRITE_SAME) { | ||
| 653 | bio->bi_io_vec[bio->bi_vcnt++] = bio_src->bi_io_vec[0]; | ||
| 654 | goto integrity_clone; | ||
| 655 | } | ||
| 656 | |||
| 653 | bio_for_each_segment(bv, bio_src, iter) | 657 | bio_for_each_segment(bv, bio_src, iter) |
| 654 | bio->bi_io_vec[bio->bi_vcnt++] = bv; | 658 | bio->bi_io_vec[bio->bi_vcnt++] = bv; |
| 655 | 659 | ||
| 660 | integrity_clone: | ||
| 656 | if (bio_integrity(bio_src)) { | 661 | if (bio_integrity(bio_src)) { |
| 657 | int ret; | 662 | int ret; |
| 658 | 663 | ||
diff --git a/fs/btrfs/check-integrity.c b/fs/btrfs/check-integrity.c index 49a62b4dda3b..0e8388e72d8d 100644 --- a/fs/btrfs/check-integrity.c +++ b/fs/btrfs/check-integrity.c | |||
| @@ -92,11 +92,11 @@ | |||
| 92 | #include <linux/slab.h> | 92 | #include <linux/slab.h> |
| 93 | #include <linux/buffer_head.h> | 93 | #include <linux/buffer_head.h> |
| 94 | #include <linux/mutex.h> | 94 | #include <linux/mutex.h> |
| 95 | #include <linux/crc32c.h> | ||
| 96 | #include <linux/genhd.h> | 95 | #include <linux/genhd.h> |
| 97 | #include <linux/blkdev.h> | 96 | #include <linux/blkdev.h> |
| 98 | #include "ctree.h" | 97 | #include "ctree.h" |
| 99 | #include "disk-io.h" | 98 | #include "disk-io.h" |
| 99 | #include "hash.h" | ||
| 100 | #include "transaction.h" | 100 | #include "transaction.h" |
| 101 | #include "extent_io.h" | 101 | #include "extent_io.h" |
| 102 | #include "volumes.h" | 102 | #include "volumes.h" |
| @@ -1823,7 +1823,7 @@ static int btrfsic_test_for_metadata(struct btrfsic_state *state, | |||
| 1823 | size_t sublen = i ? PAGE_CACHE_SIZE : | 1823 | size_t sublen = i ? PAGE_CACHE_SIZE : |
| 1824 | (PAGE_CACHE_SIZE - BTRFS_CSUM_SIZE); | 1824 | (PAGE_CACHE_SIZE - BTRFS_CSUM_SIZE); |
| 1825 | 1825 | ||
| 1826 | crc = crc32c(crc, data, sublen); | 1826 | crc = btrfs_crc32c(crc, data, sublen); |
| 1827 | } | 1827 | } |
| 1828 | btrfs_csum_final(crc, csum); | 1828 | btrfs_csum_final(crc, csum); |
| 1829 | if (memcmp(csum, h->csum, state->csum_size)) | 1829 | if (memcmp(csum, h->csum, state->csum_size)) |
diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c index e2600cdb6c25..b01fb6c527e3 100644 --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c | |||
| @@ -1010,6 +1010,8 @@ int btrfs_decompress_buf2page(char *buf, unsigned long buf_start, | |||
| 1010 | bytes = min(bytes, working_bytes); | 1010 | bytes = min(bytes, working_bytes); |
| 1011 | kaddr = kmap_atomic(page_out); | 1011 | kaddr = kmap_atomic(page_out); |
| 1012 | memcpy(kaddr + *pg_offset, buf + buf_offset, bytes); | 1012 | memcpy(kaddr + *pg_offset, buf + buf_offset, bytes); |
| 1013 | if (*pg_index == (vcnt - 1) && *pg_offset == 0) | ||
| 1014 | memset(kaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); | ||
| 1013 | kunmap_atomic(kaddr); | 1015 | kunmap_atomic(kaddr); |
| 1014 | flush_dcache_page(page_out); | 1016 | flush_dcache_page(page_out); |
| 1015 | 1017 | ||
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 0e69295d0031..81ea55314b1f 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
| @@ -26,7 +26,6 @@ | |||
| 26 | #include <linux/workqueue.h> | 26 | #include <linux/workqueue.h> |
| 27 | #include <linux/kthread.h> | 27 | #include <linux/kthread.h> |
| 28 | #include <linux/freezer.h> | 28 | #include <linux/freezer.h> |
| 29 | #include <linux/crc32c.h> | ||
| 30 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
| 31 | #include <linux/migrate.h> | 30 | #include <linux/migrate.h> |
| 32 | #include <linux/ratelimit.h> | 31 | #include <linux/ratelimit.h> |
| @@ -35,6 +34,7 @@ | |||
| 35 | #include <asm/unaligned.h> | 34 | #include <asm/unaligned.h> |
| 36 | #include "ctree.h" | 35 | #include "ctree.h" |
| 37 | #include "disk-io.h" | 36 | #include "disk-io.h" |
| 37 | #include "hash.h" | ||
| 38 | #include "transaction.h" | 38 | #include "transaction.h" |
| 39 | #include "btrfs_inode.h" | 39 | #include "btrfs_inode.h" |
| 40 | #include "volumes.h" | 40 | #include "volumes.h" |
| @@ -244,7 +244,7 @@ out: | |||
| 244 | 244 | ||
| 245 | u32 btrfs_csum_data(char *data, u32 seed, size_t len) | 245 | u32 btrfs_csum_data(char *data, u32 seed, size_t len) |
| 246 | { | 246 | { |
| 247 | return crc32c(seed, data, len); | 247 | return btrfs_crc32c(seed, data, len); |
| 248 | } | 248 | } |
| 249 | 249 | ||
| 250 | void btrfs_csum_final(u32 crc, char *result) | 250 | void btrfs_csum_final(u32 crc, char *result) |
| @@ -3839,7 +3839,6 @@ static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans, | |||
| 3839 | rb_erase(&ref->rb_node, &head->ref_root); | 3839 | rb_erase(&ref->rb_node, &head->ref_root); |
| 3840 | atomic_dec(&delayed_refs->num_entries); | 3840 | atomic_dec(&delayed_refs->num_entries); |
| 3841 | btrfs_put_delayed_ref(ref); | 3841 | btrfs_put_delayed_ref(ref); |
| 3842 | cond_resched_lock(&head->lock); | ||
| 3843 | } | 3842 | } |
| 3844 | if (head->must_insert_reserved) | 3843 | if (head->must_insert_reserved) |
| 3845 | pin_bytes = true; | 3844 | pin_bytes = true; |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 9c9ecc93ae2c..32312e09f0f5 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
| @@ -2385,6 +2385,7 @@ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, | |||
| 2385 | spin_unlock(&delayed_refs->lock); | 2385 | spin_unlock(&delayed_refs->lock); |
| 2386 | locked_ref = NULL; | 2386 | locked_ref = NULL; |
| 2387 | cond_resched(); | 2387 | cond_resched(); |
| 2388 | count++; | ||
| 2388 | continue; | 2389 | continue; |
| 2389 | } | 2390 | } |
| 2390 | 2391 | ||
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 5c4ab9c18940..d3d44486290b 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
| @@ -2629,7 +2629,7 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent) | |||
| 2629 | EXTENT_DEFRAG, 1, cached_state); | 2629 | EXTENT_DEFRAG, 1, cached_state); |
| 2630 | if (ret) { | 2630 | if (ret) { |
| 2631 | u64 last_snapshot = btrfs_root_last_snapshot(&root->root_item); | 2631 | u64 last_snapshot = btrfs_root_last_snapshot(&root->root_item); |
| 2632 | if (last_snapshot >= BTRFS_I(inode)->generation) | 2632 | if (0 && last_snapshot >= BTRFS_I(inode)->generation) |
| 2633 | /* the inode is shared */ | 2633 | /* the inode is shared */ |
| 2634 | new = record_old_file_extents(inode, ordered_extent); | 2634 | new = record_old_file_extents(inode, ordered_extent); |
| 2635 | 2635 | ||
| @@ -5154,7 +5154,7 @@ static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry, | |||
| 5154 | return ERR_CAST(inode); | 5154 | return ERR_CAST(inode); |
| 5155 | } | 5155 | } |
| 5156 | 5156 | ||
| 5157 | return d_splice_alias(inode, dentry); | 5157 | return d_materialise_unique(dentry, inode); |
| 5158 | } | 5158 | } |
| 5159 | 5159 | ||
| 5160 | unsigned char btrfs_filetype_table[] = { | 5160 | unsigned char btrfs_filetype_table[] = { |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index b0134892dc70..a6d8efa46bfe 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
| @@ -3537,20 +3537,6 @@ out: | |||
| 3537 | return ret; | 3537 | return ret; |
| 3538 | } | 3538 | } |
| 3539 | 3539 | ||
| 3540 | static long btrfs_ioctl_global_rsv(struct btrfs_root *root, void __user *arg) | ||
| 3541 | { | ||
| 3542 | struct btrfs_block_rsv *block_rsv = &root->fs_info->global_block_rsv; | ||
| 3543 | u64 reserved; | ||
| 3544 | |||
| 3545 | spin_lock(&block_rsv->lock); | ||
| 3546 | reserved = block_rsv->reserved; | ||
| 3547 | spin_unlock(&block_rsv->lock); | ||
| 3548 | |||
| 3549 | if (arg && copy_to_user(arg, &reserved, sizeof(reserved))) | ||
| 3550 | return -EFAULT; | ||
| 3551 | return 0; | ||
| 3552 | } | ||
| 3553 | |||
| 3554 | /* | 3540 | /* |
| 3555 | * there are many ways the trans_start and trans_end ioctls can lead | 3541 | * there are many ways the trans_start and trans_end ioctls can lead |
| 3556 | * to deadlocks. They should only be used by applications that | 3542 | * to deadlocks. They should only be used by applications that |
| @@ -4525,7 +4511,7 @@ static int btrfs_ioctl_set_fslabel(struct file *file, void __user *arg) | |||
| 4525 | spin_lock(&root->fs_info->super_lock); | 4511 | spin_lock(&root->fs_info->super_lock); |
| 4526 | strcpy(super_block->label, label); | 4512 | strcpy(super_block->label, label); |
| 4527 | spin_unlock(&root->fs_info->super_lock); | 4513 | spin_unlock(&root->fs_info->super_lock); |
| 4528 | ret = btrfs_end_transaction(trans, root); | 4514 | ret = btrfs_commit_transaction(trans, root); |
| 4529 | 4515 | ||
| 4530 | out_unlock: | 4516 | out_unlock: |
| 4531 | mnt_drop_write_file(file); | 4517 | mnt_drop_write_file(file); |
| @@ -4668,7 +4654,7 @@ static int btrfs_ioctl_set_features(struct file *file, void __user *arg) | |||
| 4668 | if (ret) | 4654 | if (ret) |
| 4669 | return ret; | 4655 | return ret; |
| 4670 | 4656 | ||
| 4671 | trans = btrfs_start_transaction(root, 1); | 4657 | trans = btrfs_start_transaction(root, 0); |
| 4672 | if (IS_ERR(trans)) | 4658 | if (IS_ERR(trans)) |
| 4673 | return PTR_ERR(trans); | 4659 | return PTR_ERR(trans); |
| 4674 | 4660 | ||
| @@ -4689,7 +4675,7 @@ static int btrfs_ioctl_set_features(struct file *file, void __user *arg) | |||
| 4689 | btrfs_set_super_incompat_flags(super_block, newflags); | 4675 | btrfs_set_super_incompat_flags(super_block, newflags); |
| 4690 | spin_unlock(&root->fs_info->super_lock); | 4676 | spin_unlock(&root->fs_info->super_lock); |
| 4691 | 4677 | ||
| 4692 | return btrfs_end_transaction(trans, root); | 4678 | return btrfs_commit_transaction(trans, root); |
| 4693 | } | 4679 | } |
| 4694 | 4680 | ||
| 4695 | long btrfs_ioctl(struct file *file, unsigned int | 4681 | long btrfs_ioctl(struct file *file, unsigned int |
| @@ -4757,8 +4743,6 @@ long btrfs_ioctl(struct file *file, unsigned int | |||
| 4757 | return btrfs_ioctl_logical_to_ino(root, argp); | 4743 | return btrfs_ioctl_logical_to_ino(root, argp); |
| 4758 | case BTRFS_IOC_SPACE_INFO: | 4744 | case BTRFS_IOC_SPACE_INFO: |
| 4759 | return btrfs_ioctl_space_info(root, argp); | 4745 | return btrfs_ioctl_space_info(root, argp); |
| 4760 | case BTRFS_IOC_GLOBAL_RSV: | ||
| 4761 | return btrfs_ioctl_global_rsv(root, argp); | ||
| 4762 | case BTRFS_IOC_SYNC: { | 4746 | case BTRFS_IOC_SYNC: { |
| 4763 | int ret; | 4747 | int ret; |
| 4764 | 4748 | ||
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index 730dce395858..9dde9717c1b9 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c | |||
| @@ -24,12 +24,12 @@ | |||
| 24 | #include <linux/xattr.h> | 24 | #include <linux/xattr.h> |
| 25 | #include <linux/posix_acl_xattr.h> | 25 | #include <linux/posix_acl_xattr.h> |
| 26 | #include <linux/radix-tree.h> | 26 | #include <linux/radix-tree.h> |
| 27 | #include <linux/crc32c.h> | ||
| 28 | #include <linux/vmalloc.h> | 27 | #include <linux/vmalloc.h> |
| 29 | #include <linux/string.h> | 28 | #include <linux/string.h> |
| 30 | 29 | ||
| 31 | #include "send.h" | 30 | #include "send.h" |
| 32 | #include "backref.h" | 31 | #include "backref.h" |
| 32 | #include "hash.h" | ||
| 33 | #include "locking.h" | 33 | #include "locking.h" |
| 34 | #include "disk-io.h" | 34 | #include "disk-io.h" |
| 35 | #include "btrfs_inode.h" | 35 | #include "btrfs_inode.h" |
| @@ -620,7 +620,7 @@ static int send_cmd(struct send_ctx *sctx) | |||
| 620 | hdr->len = cpu_to_le32(sctx->send_size - sizeof(*hdr)); | 620 | hdr->len = cpu_to_le32(sctx->send_size - sizeof(*hdr)); |
| 621 | hdr->crc = 0; | 621 | hdr->crc = 0; |
| 622 | 622 | ||
| 623 | crc = crc32c(0, (unsigned char *)sctx->send_buf, sctx->send_size); | 623 | crc = btrfs_crc32c(0, (unsigned char *)sctx->send_buf, sctx->send_size); |
| 624 | hdr->crc = cpu_to_le32(crc); | 624 | hdr->crc = cpu_to_le32(crc); |
| 625 | 625 | ||
| 626 | ret = write_buf(sctx->send_filp, sctx->send_buf, sctx->send_size, | 626 | ret = write_buf(sctx->send_filp, sctx->send_buf, sctx->send_size, |
| @@ -1332,6 +1332,16 @@ verbose_printk(KERN_DEBUG "btrfs: find_extent_clone: data_offset=%llu, " | |||
| 1332 | } | 1332 | } |
| 1333 | 1333 | ||
| 1334 | if (cur_clone_root) { | 1334 | if (cur_clone_root) { |
| 1335 | if (compressed != BTRFS_COMPRESS_NONE) { | ||
| 1336 | /* | ||
| 1337 | * Offsets given by iterate_extent_inodes() are relative | ||
| 1338 | * to the start of the extent, we need to add logical | ||
| 1339 | * offset from the file extent item. | ||
| 1340 | * (See why at backref.c:check_extent_in_eb()) | ||
| 1341 | */ | ||
| 1342 | cur_clone_root->offset += btrfs_file_extent_offset(eb, | ||
| 1343 | fi); | ||
| 1344 | } | ||
| 1335 | *found = cur_clone_root; | 1345 | *found = cur_clone_root; |
| 1336 | ret = 0; | 1346 | ret = 0; |
| 1337 | } else { | 1347 | } else { |
| @@ -2774,8 +2784,6 @@ static int add_waiting_dir_move(struct send_ctx *sctx, u64 ino) | |||
| 2774 | return 0; | 2784 | return 0; |
| 2775 | } | 2785 | } |
| 2776 | 2786 | ||
| 2777 | #ifdef CONFIG_BTRFS_ASSERT | ||
| 2778 | |||
| 2779 | static int del_waiting_dir_move(struct send_ctx *sctx, u64 ino) | 2787 | static int del_waiting_dir_move(struct send_ctx *sctx, u64 ino) |
| 2780 | { | 2788 | { |
| 2781 | struct rb_node *n = sctx->waiting_dir_moves.rb_node; | 2789 | struct rb_node *n = sctx->waiting_dir_moves.rb_node; |
| @@ -2796,8 +2804,6 @@ static int del_waiting_dir_move(struct send_ctx *sctx, u64 ino) | |||
| 2796 | return -ENOENT; | 2804 | return -ENOENT; |
| 2797 | } | 2805 | } |
| 2798 | 2806 | ||
| 2799 | #endif | ||
| 2800 | |||
| 2801 | static int add_pending_dir_move(struct send_ctx *sctx, u64 parent_ino) | 2807 | static int add_pending_dir_move(struct send_ctx *sctx, u64 parent_ino) |
| 2802 | { | 2808 | { |
| 2803 | struct rb_node **p = &sctx->pending_dir_moves.rb_node; | 2809 | struct rb_node **p = &sctx->pending_dir_moves.rb_node; |
| @@ -2902,7 +2908,9 @@ static int apply_dir_move(struct send_ctx *sctx, struct pending_dir_move *pm) | |||
| 2902 | } | 2908 | } |
| 2903 | 2909 | ||
| 2904 | sctx->send_progress = sctx->cur_ino + 1; | 2910 | sctx->send_progress = sctx->cur_ino + 1; |
| 2905 | ASSERT(del_waiting_dir_move(sctx, pm->ino) == 0); | 2911 | ret = del_waiting_dir_move(sctx, pm->ino); |
| 2912 | ASSERT(ret == 0); | ||
| 2913 | |||
| 2906 | ret = get_cur_path(sctx, pm->ino, pm->gen, to_path); | 2914 | ret = get_cur_path(sctx, pm->ino, pm->gen, to_path); |
| 2907 | if (ret < 0) | 2915 | if (ret < 0) |
| 2908 | goto out; | 2916 | goto out; |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index c02f63356895..d04db817be5c 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
| @@ -566,7 +566,7 @@ int btrfs_parse_options(struct btrfs_root *root, char *options) | |||
| 566 | kfree(num); | 566 | kfree(num); |
| 567 | 567 | ||
| 568 | if (info->max_inline) { | 568 | if (info->max_inline) { |
| 569 | info->max_inline = max_t(u64, | 569 | info->max_inline = min_t(u64, |
| 570 | info->max_inline, | 570 | info->max_inline, |
| 571 | root->sectorsize); | 571 | root->sectorsize); |
| 572 | } | 572 | } |
| @@ -855,6 +855,7 @@ static struct dentry *get_default_root(struct super_block *sb, | |||
| 855 | struct btrfs_path *path; | 855 | struct btrfs_path *path; |
| 856 | struct btrfs_key location; | 856 | struct btrfs_key location; |
| 857 | struct inode *inode; | 857 | struct inode *inode; |
| 858 | struct dentry *dentry; | ||
| 858 | u64 dir_id; | 859 | u64 dir_id; |
| 859 | int new = 0; | 860 | int new = 0; |
| 860 | 861 | ||
| @@ -925,7 +926,13 @@ setup_root: | |||
| 925 | return dget(sb->s_root); | 926 | return dget(sb->s_root); |
| 926 | } | 927 | } |
| 927 | 928 | ||
| 928 | return d_obtain_alias(inode); | 929 | dentry = d_obtain_alias(inode); |
| 930 | if (!IS_ERR(dentry)) { | ||
| 931 | spin_lock(&dentry->d_lock); | ||
| 932 | dentry->d_flags &= ~DCACHE_DISCONNECTED; | ||
| 933 | spin_unlock(&dentry->d_lock); | ||
| 934 | } | ||
| 935 | return dentry; | ||
| 929 | } | 936 | } |
| 930 | 937 | ||
| 931 | static int btrfs_fill_super(struct super_block *sb, | 938 | static int btrfs_fill_super(struct super_block *sb, |
| @@ -1996,7 +2003,7 @@ static void __exit exit_btrfs_fs(void) | |||
| 1996 | btrfs_hash_exit(); | 2003 | btrfs_hash_exit(); |
| 1997 | } | 2004 | } |
| 1998 | 2005 | ||
| 1999 | module_init(init_btrfs_fs) | 2006 | late_initcall(init_btrfs_fs); |
| 2000 | module_exit(exit_btrfs_fs) | 2007 | module_exit(exit_btrfs_fs) |
| 2001 | 2008 | ||
| 2002 | MODULE_LICENSE("GPL"); | 2009 | MODULE_LICENSE("GPL"); |
diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c index 782374d8fd19..865f4cf9a769 100644 --- a/fs/btrfs/sysfs.c +++ b/fs/btrfs/sysfs.c | |||
| @@ -578,8 +578,14 @@ static int add_device_membership(struct btrfs_fs_info *fs_info) | |||
| 578 | return -ENOMEM; | 578 | return -ENOMEM; |
| 579 | 579 | ||
| 580 | list_for_each_entry(dev, &fs_devices->devices, dev_list) { | 580 | list_for_each_entry(dev, &fs_devices->devices, dev_list) { |
| 581 | struct hd_struct *disk = dev->bdev->bd_part; | 581 | struct hd_struct *disk; |
| 582 | struct kobject *disk_kobj = &part_to_dev(disk)->kobj; | 582 | struct kobject *disk_kobj; |
| 583 | |||
| 584 | if (!dev->bdev) | ||
| 585 | continue; | ||
| 586 | |||
| 587 | disk = dev->bdev->bd_part; | ||
| 588 | disk_kobj = &part_to_dev(disk)->kobj; | ||
| 583 | 589 | ||
| 584 | error = sysfs_create_link(fs_info->device_dir_kobj, | 590 | error = sysfs_create_link(fs_info->device_dir_kobj, |
| 585 | disk_kobj, disk_kobj->name); | 591 | disk_kobj, disk_kobj->name); |
diff --git a/fs/buffer.c b/fs/buffer.c index 651dba10b9c2..27265a8b43c1 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
| @@ -654,14 +654,16 @@ EXPORT_SYMBOL(mark_buffer_dirty_inode); | |||
| 654 | static void __set_page_dirty(struct page *page, | 654 | static void __set_page_dirty(struct page *page, |
| 655 | struct address_space *mapping, int warn) | 655 | struct address_space *mapping, int warn) |
| 656 | { | 656 | { |
| 657 | spin_lock_irq(&mapping->tree_lock); | 657 | unsigned long flags; |
| 658 | |||
| 659 | spin_lock_irqsave(&mapping->tree_lock, flags); | ||
| 658 | if (page->mapping) { /* Race with truncate? */ | 660 | if (page->mapping) { /* Race with truncate? */ |
| 659 | WARN_ON_ONCE(warn && !PageUptodate(page)); | 661 | WARN_ON_ONCE(warn && !PageUptodate(page)); |
| 660 | account_page_dirtied(page, mapping); | 662 | account_page_dirtied(page, mapping); |
| 661 | radix_tree_tag_set(&mapping->page_tree, | 663 | radix_tree_tag_set(&mapping->page_tree, |
| 662 | page_index(page), PAGECACHE_TAG_DIRTY); | 664 | page_index(page), PAGECACHE_TAG_DIRTY); |
| 663 | } | 665 | } |
| 664 | spin_unlock_irq(&mapping->tree_lock); | 666 | spin_unlock_irqrestore(&mapping->tree_lock, flags); |
| 665 | __mark_inode_dirty(mapping->host, I_DIRTY_PAGES); | 667 | __mark_inode_dirty(mapping->host, I_DIRTY_PAGES); |
| 666 | } | 668 | } |
| 667 | 669 | ||
diff --git a/fs/ceph/acl.c b/fs/ceph/acl.c index 4c2d452c4bfc..21887d63dad5 100644 --- a/fs/ceph/acl.c +++ b/fs/ceph/acl.c | |||
| @@ -54,11 +54,6 @@ static inline struct posix_acl *ceph_get_cached_acl(struct inode *inode, | |||
| 54 | return acl; | 54 | return acl; |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | void ceph_forget_all_cached_acls(struct inode *inode) | ||
| 58 | { | ||
| 59 | forget_all_cached_acls(inode); | ||
| 60 | } | ||
| 61 | |||
| 62 | struct posix_acl *ceph_get_acl(struct inode *inode, int type) | 57 | struct posix_acl *ceph_get_acl(struct inode *inode, int type) |
| 63 | { | 58 | { |
| 64 | int size; | 59 | int size; |
| @@ -160,11 +155,7 @@ int ceph_set_acl(struct inode *inode, struct posix_acl *acl, int type) | |||
| 160 | goto out_dput; | 155 | goto out_dput; |
| 161 | } | 156 | } |
| 162 | 157 | ||
| 163 | if (value) | 158 | ret = __ceph_setxattr(dentry, name, value, size, 0); |
| 164 | ret = __ceph_setxattr(dentry, name, value, size, 0); | ||
| 165 | else | ||
| 166 | ret = __ceph_removexattr(dentry, name); | ||
| 167 | |||
| 168 | if (ret) { | 159 | if (ret) { |
| 169 | if (new_mode != old_mode) { | 160 | if (new_mode != old_mode) { |
| 170 | newattrs.ia_mode = old_mode; | 161 | newattrs.ia_mode = old_mode; |
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 6da4df84ba30..45eda6d7a40c 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c | |||
| @@ -100,6 +100,14 @@ static unsigned fpos_off(loff_t p) | |||
| 100 | return p & 0xffffffff; | 100 | return p & 0xffffffff; |
| 101 | } | 101 | } |
| 102 | 102 | ||
| 103 | static int fpos_cmp(loff_t l, loff_t r) | ||
| 104 | { | ||
| 105 | int v = ceph_frag_compare(fpos_frag(l), fpos_frag(r)); | ||
| 106 | if (v) | ||
| 107 | return v; | ||
| 108 | return (int)(fpos_off(l) - fpos_off(r)); | ||
| 109 | } | ||
| 110 | |||
| 103 | /* | 111 | /* |
| 104 | * When possible, we try to satisfy a readdir by peeking at the | 112 | * When possible, we try to satisfy a readdir by peeking at the |
| 105 | * dcache. We make this work by carefully ordering dentries on | 113 | * dcache. We make this work by carefully ordering dentries on |
| @@ -156,7 +164,7 @@ more: | |||
| 156 | if (!d_unhashed(dentry) && dentry->d_inode && | 164 | if (!d_unhashed(dentry) && dentry->d_inode && |
| 157 | ceph_snap(dentry->d_inode) != CEPH_SNAPDIR && | 165 | ceph_snap(dentry->d_inode) != CEPH_SNAPDIR && |
| 158 | ceph_ino(dentry->d_inode) != CEPH_INO_CEPH && | 166 | ceph_ino(dentry->d_inode) != CEPH_INO_CEPH && |
| 159 | ctx->pos <= di->offset) | 167 | fpos_cmp(ctx->pos, di->offset) <= 0) |
| 160 | break; | 168 | break; |
| 161 | dout(" skipping %p %.*s at %llu (%llu)%s%s\n", dentry, | 169 | dout(" skipping %p %.*s at %llu (%llu)%s%s\n", dentry, |
| 162 | dentry->d_name.len, dentry->d_name.name, di->offset, | 170 | dentry->d_name.len, dentry->d_name.name, di->offset, |
| @@ -695,9 +703,8 @@ static int ceph_mknod(struct inode *dir, struct dentry *dentry, | |||
| 695 | ceph_mdsc_put_request(req); | 703 | ceph_mdsc_put_request(req); |
| 696 | 704 | ||
| 697 | if (!err) | 705 | if (!err) |
| 698 | err = ceph_init_acl(dentry, dentry->d_inode, dir); | 706 | ceph_init_acl(dentry, dentry->d_inode, dir); |
| 699 | 707 | else | |
| 700 | if (err) | ||
| 701 | d_drop(dentry); | 708 | d_drop(dentry); |
| 702 | return err; | 709 | return err; |
| 703 | } | 710 | } |
| @@ -735,7 +742,9 @@ static int ceph_symlink(struct inode *dir, struct dentry *dentry, | |||
| 735 | if (!err && !req->r_reply_info.head->is_dentry) | 742 | if (!err && !req->r_reply_info.head->is_dentry) |
| 736 | err = ceph_handle_notrace_create(dir, dentry); | 743 | err = ceph_handle_notrace_create(dir, dentry); |
| 737 | ceph_mdsc_put_request(req); | 744 | ceph_mdsc_put_request(req); |
| 738 | if (err) | 745 | if (!err) |
| 746 | ceph_init_acl(dentry, dentry->d_inode, dir); | ||
| 747 | else | ||
| 739 | d_drop(dentry); | 748 | d_drop(dentry); |
| 740 | return err; | 749 | return err; |
| 741 | } | 750 | } |
| @@ -776,7 +785,9 @@ static int ceph_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) | |||
| 776 | err = ceph_handle_notrace_create(dir, dentry); | 785 | err = ceph_handle_notrace_create(dir, dentry); |
| 777 | ceph_mdsc_put_request(req); | 786 | ceph_mdsc_put_request(req); |
| 778 | out: | 787 | out: |
| 779 | if (err < 0) | 788 | if (!err) |
| 789 | ceph_init_acl(dentry, dentry->d_inode, dir); | ||
| 790 | else | ||
| 780 | d_drop(dentry); | 791 | d_drop(dentry); |
| 781 | return err; | 792 | return err; |
| 782 | } | 793 | } |
diff --git a/fs/ceph/file.c b/fs/ceph/file.c index dfd2ce3419f8..09c7afe32e49 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c | |||
| @@ -286,6 +286,7 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry, | |||
| 286 | } else { | 286 | } else { |
| 287 | dout("atomic_open finish_open on dn %p\n", dn); | 287 | dout("atomic_open finish_open on dn %p\n", dn); |
| 288 | if (req->r_op == CEPH_MDS_OP_CREATE && req->r_reply_info.has_create_ino) { | 288 | if (req->r_op == CEPH_MDS_OP_CREATE && req->r_reply_info.has_create_ino) { |
| 289 | ceph_init_acl(dentry, dentry->d_inode, dir); | ||
| 289 | *opened |= FILE_CREATED; | 290 | *opened |= FILE_CREATED; |
| 290 | } | 291 | } |
| 291 | err = finish_open(file, dentry, ceph_open, opened); | 292 | err = finish_open(file, dentry, ceph_open, opened); |
diff --git a/fs/ceph/super.c b/fs/ceph/super.c index 2df963f1cf5a..10a4ccbf38da 100644 --- a/fs/ceph/super.c +++ b/fs/ceph/super.c | |||
| @@ -144,7 +144,11 @@ enum { | |||
| 144 | Opt_ino32, | 144 | Opt_ino32, |
| 145 | Opt_noino32, | 145 | Opt_noino32, |
| 146 | Opt_fscache, | 146 | Opt_fscache, |
| 147 | Opt_nofscache | 147 | Opt_nofscache, |
| 148 | #ifdef CONFIG_CEPH_FS_POSIX_ACL | ||
| 149 | Opt_acl, | ||
| 150 | #endif | ||
| 151 | Opt_noacl | ||
| 148 | }; | 152 | }; |
| 149 | 153 | ||
| 150 | static match_table_t fsopt_tokens = { | 154 | static match_table_t fsopt_tokens = { |
| @@ -172,6 +176,10 @@ static match_table_t fsopt_tokens = { | |||
| 172 | {Opt_noino32, "noino32"}, | 176 | {Opt_noino32, "noino32"}, |
| 173 | {Opt_fscache, "fsc"}, | 177 | {Opt_fscache, "fsc"}, |
| 174 | {Opt_nofscache, "nofsc"}, | 178 | {Opt_nofscache, "nofsc"}, |
| 179 | #ifdef CONFIG_CEPH_FS_POSIX_ACL | ||
| 180 | {Opt_acl, "acl"}, | ||
| 181 | #endif | ||
| 182 | {Opt_noacl, "noacl"}, | ||
| 175 | {-1, NULL} | 183 | {-1, NULL} |
| 176 | }; | 184 | }; |
| 177 | 185 | ||
| @@ -271,6 +279,14 @@ static int parse_fsopt_token(char *c, void *private) | |||
| 271 | case Opt_nofscache: | 279 | case Opt_nofscache: |
| 272 | fsopt->flags &= ~CEPH_MOUNT_OPT_FSCACHE; | 280 | fsopt->flags &= ~CEPH_MOUNT_OPT_FSCACHE; |
| 273 | break; | 281 | break; |
| 282 | #ifdef CONFIG_CEPH_FS_POSIX_ACL | ||
| 283 | case Opt_acl: | ||
| 284 | fsopt->sb_flags |= MS_POSIXACL; | ||
| 285 | break; | ||
| 286 | #endif | ||
| 287 | case Opt_noacl: | ||
| 288 | fsopt->sb_flags &= ~MS_POSIXACL; | ||
| 289 | break; | ||
| 274 | default: | 290 | default: |
| 275 | BUG_ON(token); | 291 | BUG_ON(token); |
| 276 | } | 292 | } |
| @@ -438,6 +454,13 @@ static int ceph_show_options(struct seq_file *m, struct dentry *root) | |||
| 438 | else | 454 | else |
| 439 | seq_puts(m, ",nofsc"); | 455 | seq_puts(m, ",nofsc"); |
| 440 | 456 | ||
| 457 | #ifdef CONFIG_CEPH_FS_POSIX_ACL | ||
| 458 | if (fsopt->sb_flags & MS_POSIXACL) | ||
| 459 | seq_puts(m, ",acl"); | ||
| 460 | else | ||
| 461 | seq_puts(m, ",noacl"); | ||
| 462 | #endif | ||
| 463 | |||
| 441 | if (fsopt->wsize) | 464 | if (fsopt->wsize) |
| 442 | seq_printf(m, ",wsize=%d", fsopt->wsize); | 465 | seq_printf(m, ",wsize=%d", fsopt->wsize); |
| 443 | if (fsopt->rsize != CEPH_RSIZE_DEFAULT) | 466 | if (fsopt->rsize != CEPH_RSIZE_DEFAULT) |
| @@ -819,9 +842,6 @@ static int ceph_set_super(struct super_block *s, void *data) | |||
| 819 | 842 | ||
| 820 | s->s_flags = fsc->mount_options->sb_flags; | 843 | s->s_flags = fsc->mount_options->sb_flags; |
| 821 | s->s_maxbytes = 1ULL << 40; /* temp value until we get mdsmap */ | 844 | s->s_maxbytes = 1ULL << 40; /* temp value until we get mdsmap */ |
| 822 | #ifdef CONFIG_CEPH_FS_POSIX_ACL | ||
| 823 | s->s_flags |= MS_POSIXACL; | ||
| 824 | #endif | ||
| 825 | 845 | ||
| 826 | s->s_xattr = ceph_xattr_handlers; | 846 | s->s_xattr = ceph_xattr_handlers; |
| 827 | s->s_fs_info = fsc; | 847 | s->s_fs_info = fsc; |
| @@ -911,6 +931,10 @@ static struct dentry *ceph_mount(struct file_system_type *fs_type, | |||
| 911 | struct ceph_options *opt = NULL; | 931 | struct ceph_options *opt = NULL; |
| 912 | 932 | ||
| 913 | dout("ceph_mount\n"); | 933 | dout("ceph_mount\n"); |
| 934 | |||
| 935 | #ifdef CONFIG_CEPH_FS_POSIX_ACL | ||
| 936 | flags |= MS_POSIXACL; | ||
| 937 | #endif | ||
| 914 | err = parse_mount_options(&fsopt, &opt, flags, data, dev_name, &path); | 938 | err = parse_mount_options(&fsopt, &opt, flags, data, dev_name, &path); |
| 915 | if (err < 0) { | 939 | if (err < 0) { |
| 916 | res = ERR_PTR(err); | 940 | res = ERR_PTR(err); |
diff --git a/fs/ceph/super.h b/fs/ceph/super.h index 19793b56d0a7..d8801a95b685 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <linux/wait.h> | 13 | #include <linux/wait.h> |
| 14 | #include <linux/writeback.h> | 14 | #include <linux/writeback.h> |
| 15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
| 16 | #include <linux/posix_acl.h> | ||
| 16 | 17 | ||
| 17 | #include <linux/ceph/libceph.h> | 18 | #include <linux/ceph/libceph.h> |
| 18 | 19 | ||
| @@ -743,7 +744,11 @@ extern const struct xattr_handler *ceph_xattr_handlers[]; | |||
| 743 | struct posix_acl *ceph_get_acl(struct inode *, int); | 744 | struct posix_acl *ceph_get_acl(struct inode *, int); |
| 744 | int ceph_set_acl(struct inode *inode, struct posix_acl *acl, int type); | 745 | int ceph_set_acl(struct inode *inode, struct posix_acl *acl, int type); |
| 745 | int ceph_init_acl(struct dentry *, struct inode *, struct inode *); | 746 | int ceph_init_acl(struct dentry *, struct inode *, struct inode *); |
| 746 | void ceph_forget_all_cached_acls(struct inode *inode); | 747 | |
| 748 | static inline void ceph_forget_all_cached_acls(struct inode *inode) | ||
| 749 | { | ||
| 750 | forget_all_cached_acls(inode); | ||
| 751 | } | ||
| 747 | 752 | ||
| 748 | #else | 753 | #else |
| 749 | 754 | ||
diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c index 898b6565ad3e..a55ec37378c6 100644 --- a/fs/ceph/xattr.c +++ b/fs/ceph/xattr.c | |||
| @@ -12,6 +12,9 @@ | |||
| 12 | #define XATTR_CEPH_PREFIX "ceph." | 12 | #define XATTR_CEPH_PREFIX "ceph." |
| 13 | #define XATTR_CEPH_PREFIX_LEN (sizeof (XATTR_CEPH_PREFIX) - 1) | 13 | #define XATTR_CEPH_PREFIX_LEN (sizeof (XATTR_CEPH_PREFIX) - 1) |
| 14 | 14 | ||
| 15 | static int __remove_xattr(struct ceph_inode_info *ci, | ||
| 16 | struct ceph_inode_xattr *xattr); | ||
| 17 | |||
| 15 | /* | 18 | /* |
| 16 | * List of handlers for synthetic system.* attributes. Other | 19 | * List of handlers for synthetic system.* attributes. Other |
| 17 | * attributes are handled directly. | 20 | * attributes are handled directly. |
| @@ -319,8 +322,7 @@ static struct ceph_vxattr *ceph_match_vxattr(struct inode *inode, | |||
| 319 | static int __set_xattr(struct ceph_inode_info *ci, | 322 | static int __set_xattr(struct ceph_inode_info *ci, |
| 320 | const char *name, int name_len, | 323 | const char *name, int name_len, |
| 321 | const char *val, int val_len, | 324 | const char *val, int val_len, |
| 322 | int dirty, | 325 | int flags, int update_xattr, |
| 323 | int should_free_name, int should_free_val, | ||
| 324 | struct ceph_inode_xattr **newxattr) | 326 | struct ceph_inode_xattr **newxattr) |
| 325 | { | 327 | { |
| 326 | struct rb_node **p; | 328 | struct rb_node **p; |
| @@ -349,12 +351,31 @@ static int __set_xattr(struct ceph_inode_info *ci, | |||
| 349 | xattr = NULL; | 351 | xattr = NULL; |
| 350 | } | 352 | } |
| 351 | 353 | ||
| 354 | if (update_xattr) { | ||
| 355 | int err = 0; | ||
| 356 | if (xattr && (flags & XATTR_CREATE)) | ||
| 357 | err = -EEXIST; | ||
| 358 | else if (!xattr && (flags & XATTR_REPLACE)) | ||
| 359 | err = -ENODATA; | ||
| 360 | if (err) { | ||
| 361 | kfree(name); | ||
| 362 | kfree(val); | ||
| 363 | return err; | ||
| 364 | } | ||
| 365 | if (update_xattr < 0) { | ||
| 366 | if (xattr) | ||
| 367 | __remove_xattr(ci, xattr); | ||
| 368 | kfree(name); | ||
| 369 | return 0; | ||
| 370 | } | ||
| 371 | } | ||
| 372 | |||
| 352 | if (!xattr) { | 373 | if (!xattr) { |
| 353 | new = 1; | 374 | new = 1; |
| 354 | xattr = *newxattr; | 375 | xattr = *newxattr; |
| 355 | xattr->name = name; | 376 | xattr->name = name; |
| 356 | xattr->name_len = name_len; | 377 | xattr->name_len = name_len; |
| 357 | xattr->should_free_name = should_free_name; | 378 | xattr->should_free_name = update_xattr; |
| 358 | 379 | ||
| 359 | ci->i_xattrs.count++; | 380 | ci->i_xattrs.count++; |
| 360 | dout("__set_xattr count=%d\n", ci->i_xattrs.count); | 381 | dout("__set_xattr count=%d\n", ci->i_xattrs.count); |
| @@ -364,7 +385,7 @@ static int __set_xattr(struct ceph_inode_info *ci, | |||
| 364 | if (xattr->should_free_val) | 385 | if (xattr->should_free_val) |
| 365 | kfree((void *)xattr->val); | 386 | kfree((void *)xattr->val); |
| 366 | 387 | ||
| 367 | if (should_free_name) { | 388 | if (update_xattr) { |
| 368 | kfree((void *)name); | 389 | kfree((void *)name); |
| 369 | name = xattr->name; | 390 | name = xattr->name; |
| 370 | } | 391 | } |
| @@ -379,8 +400,8 @@ static int __set_xattr(struct ceph_inode_info *ci, | |||
| 379 | xattr->val = ""; | 400 | xattr->val = ""; |
| 380 | 401 | ||
| 381 | xattr->val_len = val_len; | 402 | xattr->val_len = val_len; |
| 382 | xattr->dirty = dirty; | 403 | xattr->dirty = update_xattr; |
| 383 | xattr->should_free_val = (val && should_free_val); | 404 | xattr->should_free_val = (val && update_xattr); |
| 384 | 405 | ||
| 385 | if (new) { | 406 | if (new) { |
| 386 | rb_link_node(&xattr->node, parent, p); | 407 | rb_link_node(&xattr->node, parent, p); |
| @@ -442,7 +463,7 @@ static int __remove_xattr(struct ceph_inode_info *ci, | |||
| 442 | struct ceph_inode_xattr *xattr) | 463 | struct ceph_inode_xattr *xattr) |
| 443 | { | 464 | { |
| 444 | if (!xattr) | 465 | if (!xattr) |
| 445 | return -EOPNOTSUPP; | 466 | return -ENODATA; |
| 446 | 467 | ||
| 447 | rb_erase(&xattr->node, &ci->i_xattrs.index); | 468 | rb_erase(&xattr->node, &ci->i_xattrs.index); |
| 448 | 469 | ||
| @@ -588,7 +609,7 @@ start: | |||
| 588 | p += len; | 609 | p += len; |
| 589 | 610 | ||
| 590 | err = __set_xattr(ci, name, namelen, val, len, | 611 | err = __set_xattr(ci, name, namelen, val, len, |
| 591 | 0, 0, 0, &xattrs[numattr]); | 612 | 0, 0, &xattrs[numattr]); |
| 592 | 613 | ||
| 593 | if (err < 0) | 614 | if (err < 0) |
| 594 | goto bad; | 615 | goto bad; |
| @@ -850,6 +871,9 @@ static int ceph_sync_setxattr(struct dentry *dentry, const char *name, | |||
| 850 | 871 | ||
| 851 | dout("setxattr value=%.*s\n", (int)size, value); | 872 | dout("setxattr value=%.*s\n", (int)size, value); |
| 852 | 873 | ||
| 874 | if (!value) | ||
| 875 | flags |= CEPH_XATTR_REMOVE; | ||
| 876 | |||
| 853 | /* do request */ | 877 | /* do request */ |
| 854 | req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_SETXATTR, | 878 | req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_SETXATTR, |
| 855 | USE_AUTH_MDS); | 879 | USE_AUTH_MDS); |
| @@ -892,7 +916,7 @@ int __ceph_setxattr(struct dentry *dentry, const char *name, | |||
| 892 | struct ceph_inode_info *ci = ceph_inode(inode); | 916 | struct ceph_inode_info *ci = ceph_inode(inode); |
| 893 | int issued; | 917 | int issued; |
| 894 | int err; | 918 | int err; |
| 895 | int dirty; | 919 | int dirty = 0; |
| 896 | int name_len = strlen(name); | 920 | int name_len = strlen(name); |
| 897 | int val_len = size; | 921 | int val_len = size; |
| 898 | char *newname = NULL; | 922 | char *newname = NULL; |
| @@ -953,12 +977,14 @@ retry: | |||
| 953 | goto retry; | 977 | goto retry; |
| 954 | } | 978 | } |
| 955 | 979 | ||
| 956 | err = __set_xattr(ci, newname, name_len, newval, | 980 | err = __set_xattr(ci, newname, name_len, newval, val_len, |
| 957 | val_len, 1, 1, 1, &xattr); | 981 | flags, value ? 1 : -1, &xattr); |
| 958 | 982 | ||
| 959 | dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL); | 983 | if (!err) { |
| 960 | ci->i_xattrs.dirty = true; | 984 | dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL); |
| 961 | inode->i_ctime = CURRENT_TIME; | 985 | ci->i_xattrs.dirty = true; |
| 986 | inode->i_ctime = CURRENT_TIME; | ||
| 987 | } | ||
| 962 | 988 | ||
| 963 | spin_unlock(&ci->i_ceph_lock); | 989 | spin_unlock(&ci->i_ceph_lock); |
| 964 | if (dirty) | 990 | if (dirty) |
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index 8f9b4f710d4a..7ff866dbb89e 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c | |||
| @@ -865,8 +865,8 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, | |||
| 865 | return rc; | 865 | return rc; |
| 866 | } | 866 | } |
| 867 | 867 | ||
| 868 | static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, | 868 | struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, |
| 869 | __u16 fid, u32 *pacllen) | 869 | const struct cifs_fid *cifsfid, u32 *pacllen) |
| 870 | { | 870 | { |
| 871 | struct cifs_ntsd *pntsd = NULL; | 871 | struct cifs_ntsd *pntsd = NULL; |
| 872 | unsigned int xid; | 872 | unsigned int xid; |
| @@ -877,7 +877,8 @@ static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, | |||
| 877 | return ERR_CAST(tlink); | 877 | return ERR_CAST(tlink); |
| 878 | 878 | ||
| 879 | xid = get_xid(); | 879 | xid = get_xid(); |
| 880 | rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), fid, &pntsd, pacllen); | 880 | rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), cifsfid->netfid, &pntsd, |
| 881 | pacllen); | ||
| 881 | free_xid(xid); | 882 | free_xid(xid); |
| 882 | 883 | ||
| 883 | cifs_put_tlink(tlink); | 884 | cifs_put_tlink(tlink); |
| @@ -946,7 +947,7 @@ struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb, | |||
| 946 | if (!open_file) | 947 | if (!open_file) |
| 947 | return get_cifs_acl_by_path(cifs_sb, path, pacllen); | 948 | return get_cifs_acl_by_path(cifs_sb, path, pacllen); |
| 948 | 949 | ||
| 949 | pntsd = get_cifs_acl_by_fid(cifs_sb, open_file->fid.netfid, pacllen); | 950 | pntsd = get_cifs_acl_by_fid(cifs_sb, &open_file->fid, pacllen); |
| 950 | cifsFileInfo_put(open_file); | 951 | cifsFileInfo_put(open_file); |
| 951 | return pntsd; | 952 | return pntsd; |
| 952 | } | 953 | } |
| @@ -1006,19 +1007,31 @@ out: | |||
| 1006 | /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */ | 1007 | /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */ |
| 1007 | int | 1008 | int |
| 1008 | cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, | 1009 | cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, |
| 1009 | struct inode *inode, const char *path, const __u16 *pfid) | 1010 | struct inode *inode, const char *path, |
| 1011 | const struct cifs_fid *pfid) | ||
| 1010 | { | 1012 | { |
| 1011 | struct cifs_ntsd *pntsd = NULL; | 1013 | struct cifs_ntsd *pntsd = NULL; |
| 1012 | u32 acllen = 0; | 1014 | u32 acllen = 0; |
| 1013 | int rc = 0; | 1015 | int rc = 0; |
| 1016 | struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); | ||
| 1017 | struct cifs_tcon *tcon; | ||
| 1014 | 1018 | ||
| 1015 | cifs_dbg(NOISY, "converting ACL to mode for %s\n", path); | 1019 | cifs_dbg(NOISY, "converting ACL to mode for %s\n", path); |
| 1016 | 1020 | ||
| 1017 | if (pfid) | 1021 | if (IS_ERR(tlink)) |
| 1018 | pntsd = get_cifs_acl_by_fid(cifs_sb, *pfid, &acllen); | 1022 | return PTR_ERR(tlink); |
| 1019 | else | 1023 | tcon = tlink_tcon(tlink); |
| 1020 | pntsd = get_cifs_acl(cifs_sb, inode, path, &acllen); | ||
| 1021 | 1024 | ||
| 1025 | if (pfid && (tcon->ses->server->ops->get_acl_by_fid)) | ||
| 1026 | pntsd = tcon->ses->server->ops->get_acl_by_fid(cifs_sb, pfid, | ||
| 1027 | &acllen); | ||
| 1028 | else if (tcon->ses->server->ops->get_acl) | ||
| 1029 | pntsd = tcon->ses->server->ops->get_acl(cifs_sb, inode, path, | ||
| 1030 | &acllen); | ||
| 1031 | else { | ||
| 1032 | cifs_put_tlink(tlink); | ||
| 1033 | return -EOPNOTSUPP; | ||
| 1034 | } | ||
| 1022 | /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */ | 1035 | /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */ |
| 1023 | if (IS_ERR(pntsd)) { | 1036 | if (IS_ERR(pntsd)) { |
| 1024 | rc = PTR_ERR(pntsd); | 1037 | rc = PTR_ERR(pntsd); |
| @@ -1030,6 +1043,8 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, | |||
| 1030 | cifs_dbg(VFS, "parse sec desc failed rc = %d\n", rc); | 1043 | cifs_dbg(VFS, "parse sec desc failed rc = %d\n", rc); |
| 1031 | } | 1044 | } |
| 1032 | 1045 | ||
| 1046 | cifs_put_tlink(tlink); | ||
| 1047 | |||
| 1033 | return rc; | 1048 | return rc; |
| 1034 | } | 1049 | } |
| 1035 | 1050 | ||
| @@ -1043,15 +1058,30 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode, | |||
| 1043 | __u32 secdesclen = 0; | 1058 | __u32 secdesclen = 0; |
| 1044 | struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */ | 1059 | struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */ |
| 1045 | struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */ | 1060 | struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */ |
| 1061 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | ||
| 1062 | struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); | ||
| 1063 | struct cifs_tcon *tcon; | ||
| 1064 | |||
| 1065 | if (IS_ERR(tlink)) | ||
| 1066 | return PTR_ERR(tlink); | ||
| 1067 | tcon = tlink_tcon(tlink); | ||
| 1046 | 1068 | ||
| 1047 | cifs_dbg(NOISY, "set ACL from mode for %s\n", path); | 1069 | cifs_dbg(NOISY, "set ACL from mode for %s\n", path); |
| 1048 | 1070 | ||
| 1049 | /* Get the security descriptor */ | 1071 | /* Get the security descriptor */ |
| 1050 | pntsd = get_cifs_acl(CIFS_SB(inode->i_sb), inode, path, &secdesclen); | 1072 | |
| 1073 | if (tcon->ses->server->ops->get_acl == NULL) { | ||
| 1074 | cifs_put_tlink(tlink); | ||
| 1075 | return -EOPNOTSUPP; | ||
| 1076 | } | ||
| 1077 | |||
| 1078 | pntsd = tcon->ses->server->ops->get_acl(cifs_sb, inode, path, | ||
| 1079 | &secdesclen); | ||
| 1051 | if (IS_ERR(pntsd)) { | 1080 | if (IS_ERR(pntsd)) { |
| 1052 | rc = PTR_ERR(pntsd); | 1081 | rc = PTR_ERR(pntsd); |
| 1053 | cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc); | 1082 | cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc); |
| 1054 | goto out; | 1083 | cifs_put_tlink(tlink); |
| 1084 | return rc; | ||
| 1055 | } | 1085 | } |
| 1056 | 1086 | ||
| 1057 | /* | 1087 | /* |
| @@ -1064,6 +1094,7 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode, | |||
| 1064 | pnntsd = kmalloc(secdesclen, GFP_KERNEL); | 1094 | pnntsd = kmalloc(secdesclen, GFP_KERNEL); |
| 1065 | if (!pnntsd) { | 1095 | if (!pnntsd) { |
| 1066 | kfree(pntsd); | 1096 | kfree(pntsd); |
| 1097 | cifs_put_tlink(tlink); | ||
| 1067 | return -ENOMEM; | 1098 | return -ENOMEM; |
| 1068 | } | 1099 | } |
| 1069 | 1100 | ||
| @@ -1072,14 +1103,18 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode, | |||
| 1072 | 1103 | ||
| 1073 | cifs_dbg(NOISY, "build_sec_desc rc: %d\n", rc); | 1104 | cifs_dbg(NOISY, "build_sec_desc rc: %d\n", rc); |
| 1074 | 1105 | ||
| 1106 | if (tcon->ses->server->ops->set_acl == NULL) | ||
| 1107 | rc = -EOPNOTSUPP; | ||
| 1108 | |||
| 1075 | if (!rc) { | 1109 | if (!rc) { |
| 1076 | /* Set the security descriptor */ | 1110 | /* Set the security descriptor */ |
| 1077 | rc = set_cifs_acl(pnntsd, secdesclen, inode, path, aclflag); | 1111 | rc = tcon->ses->server->ops->set_acl(pnntsd, secdesclen, inode, |
| 1112 | path, aclflag); | ||
| 1078 | cifs_dbg(NOISY, "set_cifs_acl rc: %d\n", rc); | 1113 | cifs_dbg(NOISY, "set_cifs_acl rc: %d\n", rc); |
| 1079 | } | 1114 | } |
| 1115 | cifs_put_tlink(tlink); | ||
| 1080 | 1116 | ||
| 1081 | kfree(pnntsd); | 1117 | kfree(pnntsd); |
| 1082 | kfree(pntsd); | 1118 | kfree(pntsd); |
| 1083 | out: | ||
| 1084 | return rc; | 1119 | return rc; |
| 1085 | } | 1120 | } |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index a245d1809ed8..cf32f0393369 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,12 @@ 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 | struct cifs_ntsd * (*get_acl_by_fid)(struct cifs_sb_info *, | ||
| 402 | const struct cifs_fid *, u32 *); | ||
| 403 | int (*set_acl)(struct cifs_ntsd *, __u32, struct inode *, const char *, | ||
| 404 | int); | ||
| 398 | }; | 405 | }; |
| 399 | 406 | ||
| 400 | struct smb_version_values { | 407 | struct smb_version_values { |
| @@ -1064,7 +1071,7 @@ struct cifs_writedata { | |||
| 1064 | unsigned int pagesz; | 1071 | unsigned int pagesz; |
| 1065 | unsigned int tailsz; | 1072 | unsigned int tailsz; |
| 1066 | unsigned int nr_pages; | 1073 | unsigned int nr_pages; |
| 1067 | struct page *pages[1]; | 1074 | struct page *pages[]; |
| 1068 | }; | 1075 | }; |
| 1069 | 1076 | ||
| 1070 | /* | 1077 | /* |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 79e6e9a93a8c..acc4ee8ed075 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
| @@ -151,7 +151,7 @@ extern struct inode *cifs_iget(struct super_block *sb, | |||
| 151 | 151 | ||
| 152 | extern int cifs_get_inode_info(struct inode **inode, const char *full_path, | 152 | extern int cifs_get_inode_info(struct inode **inode, const char *full_path, |
| 153 | FILE_ALL_INFO *data, struct super_block *sb, | 153 | FILE_ALL_INFO *data, struct super_block *sb, |
| 154 | int xid, const __u16 *fid); | 154 | int xid, const struct cifs_fid *fid); |
| 155 | extern int cifs_get_inode_info_unix(struct inode **pinode, | 155 | extern int cifs_get_inode_info_unix(struct inode **pinode, |
| 156 | const unsigned char *search_path, | 156 | const unsigned char *search_path, |
| 157 | struct super_block *sb, unsigned int xid); | 157 | struct super_block *sb, unsigned int xid); |
| @@ -162,11 +162,13 @@ extern int cifs_rename_pending_delete(const char *full_path, | |||
| 162 | const unsigned int xid); | 162 | const unsigned int xid); |
| 163 | extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, | 163 | extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, |
| 164 | struct cifs_fattr *fattr, struct inode *inode, | 164 | struct cifs_fattr *fattr, struct inode *inode, |
| 165 | const char *path, const __u16 *pfid); | 165 | const char *path, const struct cifs_fid *pfid); |
| 166 | extern int id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64, | 166 | extern int id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64, |
| 167 | kuid_t, kgid_t); | 167 | kuid_t, kgid_t); |
| 168 | extern struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *, struct inode *, | 168 | extern struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *, struct inode *, |
| 169 | const char *, u32 *); | 169 | const char *, u32 *); |
| 170 | extern struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *, | ||
| 171 | const struct cifs_fid *, u32 *); | ||
| 170 | extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *, | 172 | extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *, |
| 171 | const char *, int); | 173 | const char *, int); |
| 172 | 174 | ||
| @@ -488,7 +490,8 @@ void cifs_readdata_release(struct kref *refcount); | |||
| 488 | int cifs_async_readv(struct cifs_readdata *rdata); | 490 | int cifs_async_readv(struct cifs_readdata *rdata); |
| 489 | int cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid); | 491 | int cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid); |
| 490 | 492 | ||
| 491 | int cifs_async_writev(struct cifs_writedata *wdata); | 493 | int cifs_async_writev(struct cifs_writedata *wdata, |
| 494 | void (*release)(struct kref *kref)); | ||
| 492 | void cifs_writev_complete(struct work_struct *work); | 495 | void cifs_writev_complete(struct work_struct *work); |
| 493 | struct cifs_writedata *cifs_writedata_alloc(unsigned int nr_pages, | 496 | struct cifs_writedata *cifs_writedata_alloc(unsigned int nr_pages, |
| 494 | work_func_t complete); | 497 | 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/dir.c b/fs/cifs/dir.c index d3a6796caa5a..3db0c5fd9a11 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
| @@ -378,7 +378,7 @@ cifs_create_get_file_info: | |||
| 378 | xid); | 378 | xid); |
| 379 | else { | 379 | else { |
| 380 | rc = cifs_get_inode_info(&newinode, full_path, buf, inode->i_sb, | 380 | rc = cifs_get_inode_info(&newinode, full_path, buf, inode->i_sb, |
| 381 | xid, &fid->netfid); | 381 | xid, fid); |
| 382 | if (newinode) { | 382 | if (newinode) { |
| 383 | if (server->ops->set_lease_key) | 383 | if (server->ops->set_lease_key) |
| 384 | server->ops->set_lease_key(newinode, fid); | 384 | server->ops->set_lease_key(newinode, fid); |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 853d6d1cc822..53c15074bb36 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
| @@ -244,7 +244,7 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb, | |||
| 244 | xid); | 244 | xid); |
| 245 | else | 245 | else |
| 246 | rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb, | 246 | rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb, |
| 247 | xid, &fid->netfid); | 247 | xid, fid); |
| 248 | 248 | ||
| 249 | out: | 249 | out: |
| 250 | kfree(buf); | 250 | kfree(buf); |
| @@ -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; |
| @@ -2381,7 +2389,7 @@ cifs_iovec_write(struct file *file, const struct iovec *iov, | |||
| 2381 | unsigned long nr_segs, loff_t *poffset) | 2389 | unsigned long nr_segs, loff_t *poffset) |
| 2382 | { | 2390 | { |
| 2383 | unsigned long nr_pages, i; | 2391 | unsigned long nr_pages, i; |
| 2384 | size_t copied, len, cur_len; | 2392 | size_t bytes, copied, len, cur_len; |
| 2385 | ssize_t total_written = 0; | 2393 | ssize_t total_written = 0; |
| 2386 | loff_t offset; | 2394 | loff_t offset; |
| 2387 | struct iov_iter it; | 2395 | struct iov_iter it; |
| @@ -2436,14 +2444,45 @@ cifs_iovec_write(struct file *file, const struct iovec *iov, | |||
| 2436 | 2444 | ||
| 2437 | save_len = cur_len; | 2445 | save_len = cur_len; |
| 2438 | for (i = 0; i < nr_pages; i++) { | 2446 | for (i = 0; i < nr_pages; i++) { |
| 2439 | copied = min_t(const size_t, cur_len, PAGE_SIZE); | 2447 | bytes = min_t(const size_t, cur_len, PAGE_SIZE); |
| 2440 | copied = iov_iter_copy_from_user(wdata->pages[i], &it, | 2448 | copied = iov_iter_copy_from_user(wdata->pages[i], &it, |
| 2441 | 0, copied); | 2449 | 0, bytes); |
| 2442 | cur_len -= copied; | 2450 | cur_len -= copied; |
| 2443 | iov_iter_advance(&it, copied); | 2451 | iov_iter_advance(&it, copied); |
| 2452 | /* | ||
| 2453 | * If we didn't copy as much as we expected, then that | ||
| 2454 | * may mean we trod into an unmapped area. Stop copying | ||
| 2455 | * at that point. On the next pass through the big | ||
| 2456 | * loop, we'll likely end up getting a zero-length | ||
| 2457 | * write and bailing out of it. | ||
| 2458 | */ | ||
| 2459 | if (copied < bytes) | ||
| 2460 | break; | ||
| 2444 | } | 2461 | } |
| 2445 | cur_len = save_len - cur_len; | 2462 | cur_len = save_len - cur_len; |
| 2446 | 2463 | ||
| 2464 | /* | ||
| 2465 | * If we have no data to send, then that probably means that | ||
| 2466 | * the copy above failed altogether. That's most likely because | ||
| 2467 | * the address in the iovec was bogus. Set the rc to -EFAULT, | ||
| 2468 | * free anything we allocated and bail out. | ||
| 2469 | */ | ||
| 2470 | if (!cur_len) { | ||
| 2471 | for (i = 0; i < nr_pages; i++) | ||
| 2472 | put_page(wdata->pages[i]); | ||
| 2473 | kfree(wdata); | ||
| 2474 | rc = -EFAULT; | ||
| 2475 | break; | ||
| 2476 | } | ||
| 2477 | |||
| 2478 | /* | ||
| 2479 | * i + 1 now represents the number of pages we actually used in | ||
| 2480 | * the copy phase above. Bring nr_pages down to that, and free | ||
| 2481 | * any pages that we didn't use. | ||
| 2482 | */ | ||
| 2483 | for ( ; nr_pages > i + 1; nr_pages--) | ||
| 2484 | put_page(wdata->pages[nr_pages - 1]); | ||
| 2485 | |||
| 2447 | wdata->sync_mode = WB_SYNC_ALL; | 2486 | wdata->sync_mode = WB_SYNC_ALL; |
| 2448 | wdata->nr_pages = nr_pages; | 2487 | wdata->nr_pages = nr_pages; |
| 2449 | wdata->offset = (__u64)offset; | 2488 | wdata->offset = (__u64)offset; |
| @@ -2454,7 +2493,8 @@ cifs_iovec_write(struct file *file, const struct iovec *iov, | |||
| 2454 | wdata->tailsz = cur_len - ((nr_pages - 1) * PAGE_SIZE); | 2493 | wdata->tailsz = cur_len - ((nr_pages - 1) * PAGE_SIZE); |
| 2455 | rc = cifs_uncached_retry_writev(wdata); | 2494 | rc = cifs_uncached_retry_writev(wdata); |
| 2456 | if (rc) { | 2495 | if (rc) { |
| 2457 | kref_put(&wdata->refcount, cifs_writedata_release); | 2496 | kref_put(&wdata->refcount, |
| 2497 | cifs_uncached_writedata_release); | ||
| 2458 | break; | 2498 | break; |
| 2459 | } | 2499 | } |
| 2460 | 2500 | ||
| @@ -2496,7 +2536,7 @@ restart_loop: | |||
| 2496 | } | 2536 | } |
| 2497 | } | 2537 | } |
| 2498 | list_del_init(&wdata->list); | 2538 | list_del_init(&wdata->list); |
| 2499 | kref_put(&wdata->refcount, cifs_writedata_release); | 2539 | kref_put(&wdata->refcount, cifs_uncached_writedata_release); |
| 2500 | } | 2540 | } |
| 2501 | 2541 | ||
| 2502 | if (total_written > 0) | 2542 | if (total_written > 0) |
| @@ -2559,8 +2599,8 @@ cifs_writev(struct kiocb *iocb, const struct iovec *iov, | |||
| 2559 | if (rc > 0) { | 2599 | if (rc > 0) { |
| 2560 | ssize_t err; | 2600 | ssize_t err; |
| 2561 | 2601 | ||
| 2562 | err = generic_write_sync(file, pos, rc); | 2602 | err = generic_write_sync(file, iocb->ki_pos - rc, rc); |
| 2563 | if (err < 0 && rc > 0) | 2603 | if (err < 0) |
| 2564 | rc = err; | 2604 | rc = err; |
| 2565 | } | 2605 | } |
| 2566 | 2606 | ||
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 9cb9679d7357..aadc2b68678b 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; |
| @@ -672,7 +677,7 @@ cgfi_exit: | |||
| 672 | int | 677 | int |
| 673 | cifs_get_inode_info(struct inode **inode, const char *full_path, | 678 | cifs_get_inode_info(struct inode **inode, const char *full_path, |
| 674 | FILE_ALL_INFO *data, struct super_block *sb, int xid, | 679 | FILE_ALL_INFO *data, struct super_block *sb, int xid, |
| 675 | const __u16 *fid) | 680 | const struct cifs_fid *fid) |
| 676 | { | 681 | { |
| 677 | bool validinum = false; | 682 | bool validinum = false; |
| 678 | __u16 srchflgs; | 683 | __u16 srchflgs; |
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c index 9ac5bfc9cc56..526fb89f9230 100644 --- a/fs/cifs/smb1ops.c +++ b/fs/cifs/smb1ops.c | |||
| @@ -1067,6 +1067,15 @@ 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 | .get_acl_by_fid = get_cifs_acl_by_fid, | ||
| 1077 | .set_acl = set_cifs_acl, | ||
| 1078 | #endif /* CIFS_ACL */ | ||
| 1070 | }; | 1079 | }; |
| 1071 | 1080 | ||
| 1072 | struct smb_version_values smb1_values = { | 1081 | struct smb_version_values smb1_values = { |
diff --git a/fs/cifs/smb2glob.h b/fs/cifs/smb2glob.h index c38350851b08..bc0bb9c34f72 100644 --- a/fs/cifs/smb2glob.h +++ b/fs/cifs/smb2glob.h | |||
| @@ -57,4 +57,7 @@ | |||
| 57 | #define SMB2_CMACAES_SIZE (16) | 57 | #define SMB2_CMACAES_SIZE (16) |
| 58 | #define SMB3_SIGNKEY_SIZE (16) | 58 | #define SMB3_SIGNKEY_SIZE (16) |
| 59 | 59 | ||
| 60 | /* Maximum buffer size value we can send with 1 credit */ | ||
| 61 | #define SMB2_MAX_BUFFER_SIZE 65536 | ||
| 62 | |||
| 60 | #endif /* _SMB2_GLOB_H */ | 63 | #endif /* _SMB2_GLOB_H */ |
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 757da3e54d3d..192f51a12cf1 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c | |||
| @@ -182,11 +182,8 @@ smb2_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *volume_info) | |||
| 182 | /* start with specified wsize, or default */ | 182 | /* start with specified wsize, or default */ |
| 183 | wsize = volume_info->wsize ? volume_info->wsize : CIFS_DEFAULT_IOSIZE; | 183 | wsize = volume_info->wsize ? volume_info->wsize : CIFS_DEFAULT_IOSIZE; |
| 184 | wsize = min_t(unsigned int, wsize, server->max_write); | 184 | wsize = min_t(unsigned int, wsize, server->max_write); |
| 185 | /* | 185 | /* set it to the maximum buffer size value we can send with 1 credit */ |
| 186 | * limit write size to 2 ** 16, because we don't support multicredit | 186 | wsize = min_t(unsigned int, wsize, SMB2_MAX_BUFFER_SIZE); |
| 187 | * requests now. | ||
| 188 | */ | ||
| 189 | wsize = min_t(unsigned int, wsize, 2 << 15); | ||
| 190 | 187 | ||
| 191 | return wsize; | 188 | return wsize; |
| 192 | } | 189 | } |
| @@ -200,11 +197,8 @@ smb2_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *volume_info) | |||
| 200 | /* start with specified rsize, or default */ | 197 | /* start with specified rsize, or default */ |
| 201 | rsize = volume_info->rsize ? volume_info->rsize : CIFS_DEFAULT_IOSIZE; | 198 | rsize = volume_info->rsize ? volume_info->rsize : CIFS_DEFAULT_IOSIZE; |
| 202 | rsize = min_t(unsigned int, rsize, server->max_read); | 199 | rsize = min_t(unsigned int, rsize, server->max_read); |
| 203 | /* | 200 | /* set it to the maximum buffer size value we can send with 1 credit */ |
| 204 | * limit write size to 2 ** 16, because we don't support multicredit | 201 | rsize = min_t(unsigned int, rsize, SMB2_MAX_BUFFER_SIZE); |
| 205 | * requests now. | ||
| 206 | */ | ||
| 207 | rsize = min_t(unsigned int, rsize, 2 << 15); | ||
| 208 | 202 | ||
| 209 | return rsize; | 203 | return rsize; |
| 210 | } | 204 | } |
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 2013234b73ad..860344701067 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c | |||
| @@ -413,7 +413,9 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) | |||
| 413 | 413 | ||
| 414 | /* SMB2 only has an extended negflavor */ | 414 | /* SMB2 only has an extended negflavor */ |
| 415 | server->negflavor = CIFS_NEGFLAVOR_EXTENDED; | 415 | server->negflavor = CIFS_NEGFLAVOR_EXTENDED; |
| 416 | server->maxBuf = le32_to_cpu(rsp->MaxTransactSize); | 416 | /* set it to the maximum buffer size value we can send with 1 credit */ |
| 417 | server->maxBuf = min_t(unsigned int, le32_to_cpu(rsp->MaxTransactSize), | ||
| 418 | SMB2_MAX_BUFFER_SIZE); | ||
| 417 | server->max_read = le32_to_cpu(rsp->MaxReadSize); | 419 | server->max_read = le32_to_cpu(rsp->MaxReadSize); |
| 418 | server->max_write = le32_to_cpu(rsp->MaxWriteSize); | 420 | server->max_write = le32_to_cpu(rsp->MaxWriteSize); |
| 419 | /* BB Do we need to validate the SecurityMode? */ | 421 | /* BB Do we need to validate the SecurityMode? */ |
| @@ -1890,7 +1892,8 @@ smb2_writev_callback(struct mid_q_entry *mid) | |||
| 1890 | 1892 | ||
| 1891 | /* smb2_async_writev - send an async write, and set up mid to handle result */ | 1893 | /* smb2_async_writev - send an async write, and set up mid to handle result */ |
| 1892 | int | 1894 | int |
| 1893 | smb2_async_writev(struct cifs_writedata *wdata) | 1895 | smb2_async_writev(struct cifs_writedata *wdata, |
| 1896 | void (*release)(struct kref *kref)) | ||
| 1894 | { | 1897 | { |
| 1895 | int rc = -EACCES; | 1898 | int rc = -EACCES; |
| 1896 | struct smb2_write_req *req = NULL; | 1899 | struct smb2_write_req *req = NULL; |
| @@ -1938,7 +1941,7 @@ smb2_async_writev(struct cifs_writedata *wdata) | |||
| 1938 | smb2_writev_callback, wdata, 0); | 1941 | smb2_writev_callback, wdata, 0); |
| 1939 | 1942 | ||
| 1940 | if (rc) { | 1943 | if (rc) { |
| 1941 | kref_put(&wdata->refcount, cifs_writedata_release); | 1944 | kref_put(&wdata->refcount, release); |
| 1942 | cifs_stats_fail_inc(tcon, SMB2_WRITE_HE); | 1945 | cifs_stats_fail_inc(tcon, SMB2_WRITE_HE); |
| 1943 | } | 1946 | } |
| 1944 | 1947 | ||
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/ext4.h b/fs/ext4/ext4.h index ece55565b9cd..d3a534fdc5ff 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
| @@ -771,6 +771,8 @@ do { \ | |||
| 771 | if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime)) \ | 771 | if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime)) \ |
| 772 | (einode)->xtime.tv_sec = \ | 772 | (einode)->xtime.tv_sec = \ |
| 773 | (signed)le32_to_cpu((raw_inode)->xtime); \ | 773 | (signed)le32_to_cpu((raw_inode)->xtime); \ |
| 774 | else \ | ||
| 775 | (einode)->xtime.tv_sec = 0; \ | ||
| 774 | if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime ## _extra)) \ | 776 | if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime ## _extra)) \ |
| 775 | ext4_decode_extra_time(&(einode)->xtime, \ | 777 | ext4_decode_extra_time(&(einode)->xtime, \ |
| 776 | raw_inode->xtime ## _extra); \ | 778 | raw_inode->xtime ## _extra); \ |
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 10cff4736b11..74bc2d549c58 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
| @@ -3906,6 +3906,7 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode, | |||
| 3906 | } else | 3906 | } else |
| 3907 | err = ret; | 3907 | err = ret; |
| 3908 | map->m_flags |= EXT4_MAP_MAPPED; | 3908 | map->m_flags |= EXT4_MAP_MAPPED; |
| 3909 | map->m_pblk = newblock; | ||
| 3909 | if (allocated > map->m_len) | 3910 | if (allocated > map->m_len) |
| 3910 | allocated = map->m_len; | 3911 | allocated = map->m_len; |
| 3911 | map->m_len = allocated; | 3912 | map->m_len = allocated; |
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 | } |
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index 6bea80614d77..a2a837f00407 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c | |||
| @@ -140,7 +140,7 @@ static long swap_inode_boot_loader(struct super_block *sb, | |||
| 140 | handle = ext4_journal_start(inode_bl, EXT4_HT_MOVE_EXTENTS, 2); | 140 | handle = ext4_journal_start(inode_bl, EXT4_HT_MOVE_EXTENTS, 2); |
| 141 | if (IS_ERR(handle)) { | 141 | if (IS_ERR(handle)) { |
| 142 | err = -EINVAL; | 142 | err = -EINVAL; |
| 143 | goto swap_boot_out; | 143 | goto journal_err_out; |
| 144 | } | 144 | } |
| 145 | 145 | ||
| 146 | /* Protect extent tree against block allocations via delalloc */ | 146 | /* Protect extent tree against block allocations via delalloc */ |
| @@ -198,6 +198,7 @@ static long swap_inode_boot_loader(struct super_block *sb, | |||
| 198 | 198 | ||
| 199 | ext4_double_up_write_data_sem(inode, inode_bl); | 199 | ext4_double_up_write_data_sem(inode, inode_bl); |
| 200 | 200 | ||
| 201 | journal_err_out: | ||
| 201 | ext4_inode_resume_unlocked_dio(inode); | 202 | ext4_inode_resume_unlocked_dio(inode); |
| 202 | ext4_inode_resume_unlocked_dio(inode_bl); | 203 | ext4_inode_resume_unlocked_dio(inode_bl); |
| 203 | 204 | ||
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index c5adbb318a90..f3b84cd9de56 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c | |||
| @@ -243,6 +243,7 @@ static int ext4_alloc_group_tables(struct super_block *sb, | |||
| 243 | ext4_group_t group; | 243 | ext4_group_t group; |
| 244 | ext4_group_t last_group; | 244 | ext4_group_t last_group; |
| 245 | unsigned overhead; | 245 | unsigned overhead; |
| 246 | __u16 uninit_mask = (flexbg_size > 1) ? ~EXT4_BG_BLOCK_UNINIT : ~0; | ||
| 246 | 247 | ||
| 247 | BUG_ON(flex_gd->count == 0 || group_data == NULL); | 248 | BUG_ON(flex_gd->count == 0 || group_data == NULL); |
| 248 | 249 | ||
| @@ -266,7 +267,7 @@ next_group: | |||
| 266 | src_group++; | 267 | src_group++; |
| 267 | for (; src_group <= last_group; src_group++) { | 268 | for (; src_group <= last_group; src_group++) { |
| 268 | overhead = ext4_group_overhead_blocks(sb, src_group); | 269 | overhead = ext4_group_overhead_blocks(sb, src_group); |
| 269 | if (overhead != 0) | 270 | if (overhead == 0) |
| 270 | last_blk += group_data[src_group - group].blocks_count; | 271 | last_blk += group_data[src_group - group].blocks_count; |
| 271 | else | 272 | else |
| 272 | break; | 273 | break; |
| @@ -280,8 +281,7 @@ next_group: | |||
| 280 | group = ext4_get_group_number(sb, start_blk - 1); | 281 | group = ext4_get_group_number(sb, start_blk - 1); |
| 281 | group -= group_data[0].group; | 282 | group -= group_data[0].group; |
| 282 | group_data[group].free_blocks_count--; | 283 | group_data[group].free_blocks_count--; |
| 283 | if (flexbg_size > 1) | 284 | flex_gd->bg_flags[group] &= uninit_mask; |
| 284 | flex_gd->bg_flags[group] &= ~EXT4_BG_BLOCK_UNINIT; | ||
| 285 | } | 285 | } |
| 286 | 286 | ||
| 287 | /* Allocate inode bitmaps */ | 287 | /* Allocate inode bitmaps */ |
| @@ -292,22 +292,30 @@ next_group: | |||
| 292 | group = ext4_get_group_number(sb, start_blk - 1); | 292 | group = ext4_get_group_number(sb, start_blk - 1); |
| 293 | group -= group_data[0].group; | 293 | group -= group_data[0].group; |
| 294 | group_data[group].free_blocks_count--; | 294 | group_data[group].free_blocks_count--; |
| 295 | if (flexbg_size > 1) | 295 | flex_gd->bg_flags[group] &= uninit_mask; |
| 296 | flex_gd->bg_flags[group] &= ~EXT4_BG_BLOCK_UNINIT; | ||
| 297 | } | 296 | } |
| 298 | 297 | ||
| 299 | /* Allocate inode tables */ | 298 | /* Allocate inode tables */ |
| 300 | for (; it_index < flex_gd->count; it_index++) { | 299 | for (; it_index < flex_gd->count; it_index++) { |
| 301 | if (start_blk + EXT4_SB(sb)->s_itb_per_group > last_blk) | 300 | unsigned int itb = EXT4_SB(sb)->s_itb_per_group; |
| 301 | ext4_fsblk_t next_group_start; | ||
| 302 | |||
| 303 | if (start_blk + itb > last_blk) | ||
| 302 | goto next_group; | 304 | goto next_group; |
| 303 | group_data[it_index].inode_table = start_blk; | 305 | group_data[it_index].inode_table = start_blk; |
| 304 | group = ext4_get_group_number(sb, start_blk - 1); | 306 | group = ext4_get_group_number(sb, start_blk); |
| 307 | next_group_start = ext4_group_first_block_no(sb, group + 1); | ||
| 305 | group -= group_data[0].group; | 308 | group -= group_data[0].group; |
| 306 | group_data[group].free_blocks_count -= | ||
| 307 | EXT4_SB(sb)->s_itb_per_group; | ||
| 308 | if (flexbg_size > 1) | ||
| 309 | flex_gd->bg_flags[group] &= ~EXT4_BG_BLOCK_UNINIT; | ||
| 310 | 309 | ||
| 310 | if (start_blk + itb > next_group_start) { | ||
| 311 | flex_gd->bg_flags[group + 1] &= uninit_mask; | ||
| 312 | overhead = start_blk + itb - next_group_start; | ||
| 313 | group_data[group + 1].free_blocks_count -= overhead; | ||
| 314 | itb -= overhead; | ||
| 315 | } | ||
| 316 | |||
| 317 | group_data[group].free_blocks_count -= itb; | ||
| 318 | flex_gd->bg_flags[group] &= uninit_mask; | ||
| 311 | start_blk += EXT4_SB(sb)->s_itb_per_group; | 319 | start_blk += EXT4_SB(sb)->s_itb_per_group; |
| 312 | } | 320 | } |
| 313 | 321 | ||
| @@ -401,7 +409,7 @@ static int set_flexbg_block_bitmap(struct super_block *sb, handle_t *handle, | |||
| 401 | start = ext4_group_first_block_no(sb, group); | 409 | start = ext4_group_first_block_no(sb, group); |
| 402 | group -= flex_gd->groups[0].group; | 410 | group -= flex_gd->groups[0].group; |
| 403 | 411 | ||
| 404 | count2 = sb->s_blocksize * 8 - (block - start); | 412 | count2 = EXT4_BLOCKS_PER_GROUP(sb) - (block - start); |
| 405 | if (count2 > count) | 413 | if (count2 > count) |
| 406 | count2 = count; | 414 | count2 = count; |
| 407 | 415 | ||
| @@ -620,7 +628,7 @@ handle_ib: | |||
| 620 | if (err) | 628 | if (err) |
| 621 | goto out; | 629 | goto out; |
| 622 | count = group_table_count[j]; | 630 | count = group_table_count[j]; |
| 623 | start = group_data[i].block_bitmap; | 631 | start = (&group_data[i].block_bitmap)[j]; |
| 624 | block = start; | 632 | block = start; |
| 625 | } | 633 | } |
| 626 | 634 | ||
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 1f7784de05b6..710fed2377d4 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
| @@ -3695,16 +3695,22 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
| 3695 | for (i = 0; i < 4; i++) | 3695 | for (i = 0; i < 4; i++) |
| 3696 | sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]); | 3696 | sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]); |
| 3697 | sbi->s_def_hash_version = es->s_def_hash_version; | 3697 | sbi->s_def_hash_version = es->s_def_hash_version; |
| 3698 | i = le32_to_cpu(es->s_flags); | 3698 | if (EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_DIR_INDEX)) { |
| 3699 | if (i & EXT2_FLAGS_UNSIGNED_HASH) | 3699 | i = le32_to_cpu(es->s_flags); |
| 3700 | sbi->s_hash_unsigned = 3; | 3700 | if (i & EXT2_FLAGS_UNSIGNED_HASH) |
| 3701 | else if ((i & EXT2_FLAGS_SIGNED_HASH) == 0) { | 3701 | sbi->s_hash_unsigned = 3; |
| 3702 | else if ((i & EXT2_FLAGS_SIGNED_HASH) == 0) { | ||
| 3702 | #ifdef __CHAR_UNSIGNED__ | 3703 | #ifdef __CHAR_UNSIGNED__ |
| 3703 | es->s_flags |= cpu_to_le32(EXT2_FLAGS_UNSIGNED_HASH); | 3704 | if (!(sb->s_flags & MS_RDONLY)) |
| 3704 | sbi->s_hash_unsigned = 3; | 3705 | es->s_flags |= |
| 3706 | cpu_to_le32(EXT2_FLAGS_UNSIGNED_HASH); | ||
| 3707 | sbi->s_hash_unsigned = 3; | ||
| 3705 | #else | 3708 | #else |
| 3706 | es->s_flags |= cpu_to_le32(EXT2_FLAGS_SIGNED_HASH); | 3709 | if (!(sb->s_flags & MS_RDONLY)) |
| 3710 | es->s_flags |= | ||
| 3711 | cpu_to_le32(EXT2_FLAGS_SIGNED_HASH); | ||
| 3707 | #endif | 3712 | #endif |
| 3713 | } | ||
| 3708 | } | 3714 | } |
| 3709 | 3715 | ||
| 3710 | /* Handle clustersize */ | 3716 | /* Handle clustersize */ |
| @@ -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/fscache/object-list.c b/fs/fscache/object-list.c index e1959efad64f..b5ebc2d7d80d 100644 --- a/fs/fscache/object-list.c +++ b/fs/fscache/object-list.c | |||
| @@ -50,6 +50,8 @@ void fscache_objlist_add(struct fscache_object *obj) | |||
| 50 | struct fscache_object *xobj; | 50 | struct fscache_object *xobj; |
| 51 | struct rb_node **p = &fscache_object_list.rb_node, *parent = NULL; | 51 | struct rb_node **p = &fscache_object_list.rb_node, *parent = NULL; |
| 52 | 52 | ||
| 53 | ASSERT(RB_EMPTY_NODE(&obj->objlist_link)); | ||
| 54 | |||
| 53 | write_lock(&fscache_object_list_lock); | 55 | write_lock(&fscache_object_list_lock); |
| 54 | 56 | ||
| 55 | while (*p) { | 57 | while (*p) { |
| @@ -75,6 +77,9 @@ void fscache_objlist_add(struct fscache_object *obj) | |||
| 75 | */ | 77 | */ |
| 76 | void fscache_objlist_remove(struct fscache_object *obj) | 78 | void fscache_objlist_remove(struct fscache_object *obj) |
| 77 | { | 79 | { |
| 80 | if (RB_EMPTY_NODE(&obj->objlist_link)) | ||
| 81 | return; | ||
| 82 | |||
| 78 | write_lock(&fscache_object_list_lock); | 83 | write_lock(&fscache_object_list_lock); |
| 79 | 84 | ||
| 80 | BUG_ON(RB_EMPTY_ROOT(&fscache_object_list)); | 85 | BUG_ON(RB_EMPTY_ROOT(&fscache_object_list)); |
diff --git a/fs/fscache/object.c b/fs/fscache/object.c index 53d35c504240..d3b4539f1651 100644 --- a/fs/fscache/object.c +++ b/fs/fscache/object.c | |||
| @@ -314,6 +314,9 @@ void fscache_object_init(struct fscache_object *object, | |||
| 314 | object->cache = cache; | 314 | object->cache = cache; |
| 315 | object->cookie = cookie; | 315 | object->cookie = cookie; |
| 316 | object->parent = NULL; | 316 | object->parent = NULL; |
| 317 | #ifdef CONFIG_FSCACHE_OBJECT_LIST | ||
| 318 | RB_CLEAR_NODE(&object->objlist_link); | ||
| 319 | #endif | ||
| 317 | 320 | ||
| 318 | object->oob_event_mask = 0; | 321 | object->oob_event_mask = 0; |
| 319 | for (t = object->oob_table; t->events; t++) | 322 | for (t = object->oob_table; t->events; t++) |
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index 8360674c85bc..60bb365f54a5 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c | |||
| @@ -514,11 +514,13 @@ int jbd2_journal_start_reserved(handle_t *handle, unsigned int type, | |||
| 514 | * similarly constrained call sites | 514 | * similarly constrained call sites |
| 515 | */ | 515 | */ |
| 516 | ret = start_this_handle(journal, handle, GFP_NOFS); | 516 | ret = start_this_handle(journal, handle, GFP_NOFS); |
| 517 | if (ret < 0) | 517 | if (ret < 0) { |
| 518 | jbd2_journal_free_reserved(handle); | 518 | jbd2_journal_free_reserved(handle); |
| 519 | return ret; | ||
| 520 | } | ||
| 519 | handle->h_type = type; | 521 | handle->h_type = type; |
| 520 | handle->h_line_no = line_no; | 522 | handle->h_line_no = line_no; |
| 521 | return ret; | 523 | return 0; |
| 522 | } | 524 | } |
| 523 | EXPORT_SYMBOL(jbd2_journal_start_reserved); | 525 | EXPORT_SYMBOL(jbd2_journal_start_reserved); |
| 524 | 526 | ||
diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c index e973b85d6afd..5a8ea16eedbc 100644 --- a/fs/jfs/acl.c +++ b/fs/jfs/acl.c | |||
| @@ -86,6 +86,8 @@ static int __jfs_set_acl(tid_t tid, struct inode *inode, int type, | |||
| 86 | rc = posix_acl_equiv_mode(acl, &inode->i_mode); | 86 | rc = posix_acl_equiv_mode(acl, &inode->i_mode); |
| 87 | if (rc < 0) | 87 | if (rc < 0) |
| 88 | return rc; | 88 | return rc; |
| 89 | inode->i_ctime = CURRENT_TIME; | ||
| 90 | mark_inode_dirty(inode); | ||
| 89 | if (rc == 0) | 91 | if (rc == 0) |
| 90 | acl = NULL; | 92 | acl = NULL; |
| 91 | break; | 93 | break; |
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/inode.c b/fs/nfs/inode.c index 28a0a3cbd3b7..360114ae8b82 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
| @@ -164,17 +164,16 @@ static void nfs_zap_caches_locked(struct inode *inode) | |||
| 164 | if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) { | 164 | if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) { |
| 165 | nfs_fscache_invalidate(inode); | 165 | nfs_fscache_invalidate(inode); |
| 166 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR | 166 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR |
| 167 | | NFS_INO_INVALID_LABEL | ||
| 168 | | NFS_INO_INVALID_DATA | 167 | | NFS_INO_INVALID_DATA |
| 169 | | NFS_INO_INVALID_ACCESS | 168 | | NFS_INO_INVALID_ACCESS |
| 170 | | NFS_INO_INVALID_ACL | 169 | | NFS_INO_INVALID_ACL |
| 171 | | NFS_INO_REVAL_PAGECACHE; | 170 | | NFS_INO_REVAL_PAGECACHE; |
| 172 | } else | 171 | } else |
| 173 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR | 172 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR |
| 174 | | NFS_INO_INVALID_LABEL | ||
| 175 | | NFS_INO_INVALID_ACCESS | 173 | | NFS_INO_INVALID_ACCESS |
| 176 | | NFS_INO_INVALID_ACL | 174 | | NFS_INO_INVALID_ACL |
| 177 | | NFS_INO_REVAL_PAGECACHE; | 175 | | NFS_INO_REVAL_PAGECACHE; |
| 176 | nfs_zap_label_cache_locked(nfsi); | ||
| 178 | } | 177 | } |
| 179 | 178 | ||
| 180 | void nfs_zap_caches(struct inode *inode) | 179 | void nfs_zap_caches(struct inode *inode) |
| @@ -266,6 +265,13 @@ nfs_init_locked(struct inode *inode, void *opaque) | |||
| 266 | } | 265 | } |
| 267 | 266 | ||
| 268 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL | 267 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL |
| 268 | static void nfs_clear_label_invalid(struct inode *inode) | ||
| 269 | { | ||
| 270 | spin_lock(&inode->i_lock); | ||
| 271 | NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_LABEL; | ||
| 272 | spin_unlock(&inode->i_lock); | ||
| 273 | } | ||
| 274 | |||
| 269 | void nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr, | 275 | void nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr, |
| 270 | struct nfs4_label *label) | 276 | struct nfs4_label *label) |
| 271 | { | 277 | { |
| @@ -283,6 +289,7 @@ void nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr, | |||
| 283 | __func__, | 289 | __func__, |
| 284 | (char *)label->label, | 290 | (char *)label->label, |
| 285 | label->len, error); | 291 | label->len, error); |
| 292 | nfs_clear_label_invalid(inode); | ||
| 286 | } | 293 | } |
| 287 | } | 294 | } |
| 288 | 295 | ||
| @@ -1648,7 +1655,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
| 1648 | inode->i_blocks = fattr->du.nfs2.blocks; | 1655 | inode->i_blocks = fattr->du.nfs2.blocks; |
| 1649 | 1656 | ||
| 1650 | /* Update attrtimeo value if we're out of the unstable period */ | 1657 | /* Update attrtimeo value if we're out of the unstable period */ |
| 1651 | if (invalid & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_LABEL)) { | 1658 | if (invalid & NFS_INO_INVALID_ATTR) { |
| 1652 | nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE); | 1659 | nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE); |
| 1653 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); | 1660 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); |
| 1654 | nfsi->attrtimeo_timestamp = now; | 1661 | nfsi->attrtimeo_timestamp = now; |
| @@ -1661,7 +1668,6 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
| 1661 | } | 1668 | } |
| 1662 | } | 1669 | } |
| 1663 | invalid &= ~NFS_INO_INVALID_ATTR; | 1670 | invalid &= ~NFS_INO_INVALID_ATTR; |
| 1664 | invalid &= ~NFS_INO_INVALID_LABEL; | ||
| 1665 | /* Don't invalidate the data if we were to blame */ | 1671 | /* Don't invalidate the data if we were to blame */ |
| 1666 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) | 1672 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) |
| 1667 | || S_ISLNK(inode->i_mode))) | 1673 | || S_ISLNK(inode->i_mode))) |
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 8b5cc04a8611..b46cf5a67329 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
| @@ -176,7 +176,8 @@ extern struct nfs_server *nfs4_create_server( | |||
| 176 | extern struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *, | 176 | extern struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *, |
| 177 | struct nfs_fh *); | 177 | struct nfs_fh *); |
| 178 | extern int nfs4_update_server(struct nfs_server *server, const char *hostname, | 178 | extern int nfs4_update_server(struct nfs_server *server, const char *hostname, |
| 179 | struct sockaddr *sap, size_t salen); | 179 | struct sockaddr *sap, size_t salen, |
| 180 | struct net *net); | ||
| 180 | extern void nfs_free_server(struct nfs_server *server); | 181 | extern void nfs_free_server(struct nfs_server *server); |
| 181 | extern struct nfs_server *nfs_clone_server(struct nfs_server *, | 182 | extern struct nfs_server *nfs_clone_server(struct nfs_server *, |
| 182 | struct nfs_fh *, | 183 | struct nfs_fh *, |
| @@ -279,9 +280,18 @@ static inline void nfs4_label_free(struct nfs4_label *label) | |||
| 279 | } | 280 | } |
| 280 | return; | 281 | return; |
| 281 | } | 282 | } |
| 283 | |||
| 284 | static inline void nfs_zap_label_cache_locked(struct nfs_inode *nfsi) | ||
| 285 | { | ||
| 286 | if (nfs_server_capable(&nfsi->vfs_inode, NFS_CAP_SECURITY_LABEL)) | ||
| 287 | nfsi->cache_validity |= NFS_INO_INVALID_LABEL; | ||
| 288 | } | ||
| 282 | #else | 289 | #else |
| 283 | static inline struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags) { return NULL; } | 290 | static inline struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags) { return NULL; } |
| 284 | static inline void nfs4_label_free(void *label) {} | 291 | static inline void nfs4_label_free(void *label) {} |
| 292 | static inline void nfs_zap_label_cache_locked(struct nfs_inode *nfsi) | ||
| 293 | { | ||
| 294 | } | ||
| 285 | #endif /* CONFIG_NFS_V4_SECURITY_LABEL */ | 295 | #endif /* CONFIG_NFS_V4_SECURITY_LABEL */ |
| 286 | 296 | ||
| 287 | /* proc.c */ | 297 | /* proc.c */ |
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..0e46d3d1b6cc 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 | } |
| @@ -1135,6 +1135,7 @@ static int nfs_probe_destination(struct nfs_server *server) | |||
| 1135 | * @hostname: new end-point's hostname | 1135 | * @hostname: new end-point's hostname |
| 1136 | * @sap: new end-point's socket address | 1136 | * @sap: new end-point's socket address |
| 1137 | * @salen: size of "sap" | 1137 | * @salen: size of "sap" |
| 1138 | * @net: net namespace | ||
| 1138 | * | 1139 | * |
| 1139 | * The nfs_server must be quiescent before this function is invoked. | 1140 | * The nfs_server must be quiescent before this function is invoked. |
| 1140 | * Either its session is drained (NFSv4.1+), or its transport is | 1141 | * Either its session is drained (NFSv4.1+), or its transport is |
| @@ -1143,13 +1144,13 @@ static int nfs_probe_destination(struct nfs_server *server) | |||
| 1143 | * Returns zero on success, or a negative errno value. | 1144 | * Returns zero on success, or a negative errno value. |
| 1144 | */ | 1145 | */ |
| 1145 | int nfs4_update_server(struct nfs_server *server, const char *hostname, | 1146 | int nfs4_update_server(struct nfs_server *server, const char *hostname, |
| 1146 | struct sockaddr *sap, size_t salen) | 1147 | struct sockaddr *sap, size_t salen, struct net *net) |
| 1147 | { | 1148 | { |
| 1148 | struct nfs_client *clp = server->nfs_client; | 1149 | struct nfs_client *clp = server->nfs_client; |
| 1149 | struct rpc_clnt *clnt = server->client; | 1150 | struct rpc_clnt *clnt = server->client; |
| 1150 | struct xprt_create xargs = { | 1151 | struct xprt_create xargs = { |
| 1151 | .ident = clp->cl_proto, | 1152 | .ident = clp->cl_proto, |
| 1152 | .net = &init_net, | 1153 | .net = net, |
| 1153 | .dstaddr = sap, | 1154 | .dstaddr = sap, |
| 1154 | .addrlen = salen, | 1155 | .addrlen = salen, |
| 1155 | .servername = hostname, | 1156 | .servername = hostname, |
| @@ -1189,7 +1190,7 @@ int nfs4_update_server(struct nfs_server *server, const char *hostname, | |||
| 1189 | error = nfs4_set_client(server, hostname, sap, salen, buf, | 1190 | error = nfs4_set_client(server, hostname, sap, salen, buf, |
| 1190 | clp->cl_rpcclient->cl_auth->au_flavor, | 1191 | clp->cl_rpcclient->cl_auth->au_flavor, |
| 1191 | clp->cl_proto, clnt->cl_timeout, | 1192 | clp->cl_proto, clnt->cl_timeout, |
| 1192 | clp->cl_minorversion, clp->cl_net); | 1193 | clp->cl_minorversion, net); |
| 1193 | nfs_put_client(clp); | 1194 | nfs_put_client(clp); |
| 1194 | if (error != 0) { | 1195 | if (error != 0) { |
| 1195 | nfs_server_insert_lists(server); | 1196 | nfs_server_insert_lists(server); |
diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c index 4e7f05d3e9db..3d5dbf80d46a 100644 --- a/fs/nfs/nfs4namespace.c +++ b/fs/nfs/nfs4namespace.c | |||
| @@ -121,9 +121,8 @@ static int nfs4_validate_fspath(struct dentry *dentry, | |||
| 121 | } | 121 | } |
| 122 | 122 | ||
| 123 | static size_t nfs_parse_server_name(char *string, size_t len, | 123 | static size_t nfs_parse_server_name(char *string, size_t len, |
| 124 | struct sockaddr *sa, size_t salen, struct nfs_server *server) | 124 | struct sockaddr *sa, size_t salen, struct net *net) |
| 125 | { | 125 | { |
| 126 | struct net *net = rpc_net_ns(server->client); | ||
| 127 | ssize_t ret; | 126 | ssize_t ret; |
| 128 | 127 | ||
| 129 | ret = rpc_pton(net, string, len, sa, salen); | 128 | ret = rpc_pton(net, string, len, sa, salen); |
| @@ -223,6 +222,7 @@ static struct vfsmount *try_location(struct nfs_clone_mount *mountdata, | |||
| 223 | const struct nfs4_fs_location *location) | 222 | const struct nfs4_fs_location *location) |
| 224 | { | 223 | { |
| 225 | const size_t addr_bufsize = sizeof(struct sockaddr_storage); | 224 | const size_t addr_bufsize = sizeof(struct sockaddr_storage); |
| 225 | struct net *net = rpc_net_ns(NFS_SB(mountdata->sb)->client); | ||
| 226 | struct vfsmount *mnt = ERR_PTR(-ENOENT); | 226 | struct vfsmount *mnt = ERR_PTR(-ENOENT); |
| 227 | char *mnt_path; | 227 | char *mnt_path; |
| 228 | unsigned int maxbuflen; | 228 | unsigned int maxbuflen; |
| @@ -248,8 +248,7 @@ static struct vfsmount *try_location(struct nfs_clone_mount *mountdata, | |||
| 248 | continue; | 248 | continue; |
| 249 | 249 | ||
| 250 | mountdata->addrlen = nfs_parse_server_name(buf->data, buf->len, | 250 | mountdata->addrlen = nfs_parse_server_name(buf->data, buf->len, |
| 251 | mountdata->addr, addr_bufsize, | 251 | mountdata->addr, addr_bufsize, net); |
| 252 | NFS_SB(mountdata->sb)); | ||
| 253 | if (mountdata->addrlen == 0) | 252 | if (mountdata->addrlen == 0) |
| 254 | continue; | 253 | continue; |
| 255 | 254 | ||
| @@ -419,6 +418,7 @@ static int nfs4_try_replacing_one_location(struct nfs_server *server, | |||
| 419 | const struct nfs4_fs_location *location) | 418 | const struct nfs4_fs_location *location) |
| 420 | { | 419 | { |
| 421 | const size_t addr_bufsize = sizeof(struct sockaddr_storage); | 420 | const size_t addr_bufsize = sizeof(struct sockaddr_storage); |
| 421 | struct net *net = rpc_net_ns(server->client); | ||
| 422 | struct sockaddr *sap; | 422 | struct sockaddr *sap; |
| 423 | unsigned int s; | 423 | unsigned int s; |
| 424 | size_t salen; | 424 | size_t salen; |
| @@ -440,7 +440,7 @@ static int nfs4_try_replacing_one_location(struct nfs_server *server, | |||
| 440 | continue; | 440 | continue; |
| 441 | 441 | ||
| 442 | salen = nfs_parse_server_name(buf->data, buf->len, | 442 | salen = nfs_parse_server_name(buf->data, buf->len, |
| 443 | sap, addr_bufsize, server); | 443 | sap, addr_bufsize, net); |
| 444 | if (salen == 0) | 444 | if (salen == 0) |
| 445 | continue; | 445 | continue; |
| 446 | rpc_set_port(sap, NFS_PORT); | 446 | rpc_set_port(sap, NFS_PORT); |
| @@ -450,7 +450,7 @@ static int nfs4_try_replacing_one_location(struct nfs_server *server, | |||
| 450 | if (hostname == NULL) | 450 | if (hostname == NULL) |
| 451 | break; | 451 | break; |
| 452 | 452 | ||
| 453 | error = nfs4_update_server(server, hostname, sap, salen); | 453 | error = nfs4_update_server(server, hostname, sap, salen, net); |
| 454 | kfree(hostname); | 454 | kfree(hostname); |
| 455 | if (error == 0) | 455 | if (error == 0) |
| 456 | break; | 456 | break; |
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/nfs/nfs4state.c b/fs/nfs/nfs4state.c index e5be72518bd7..e1a47217c05e 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
| @@ -1015,8 +1015,11 @@ int nfs4_select_rw_stateid(nfs4_stateid *dst, struct nfs4_state *state, | |||
| 1015 | if (ret == -EIO) | 1015 | if (ret == -EIO) |
| 1016 | /* A lost lock - don't even consider delegations */ | 1016 | /* A lost lock - don't even consider delegations */ |
| 1017 | goto out; | 1017 | goto out; |
| 1018 | if (nfs4_copy_delegation_stateid(dst, state->inode, fmode)) | 1018 | /* returns true if delegation stateid found and copied */ |
| 1019 | if (nfs4_copy_delegation_stateid(dst, state->inode, fmode)) { | ||
| 1020 | ret = 0; | ||
| 1019 | goto out; | 1021 | goto out; |
| 1022 | } | ||
| 1020 | if (ret != -ENOENT) | 1023 | if (ret != -ENOENT) |
| 1021 | /* nfs4_copy_delegation_stateid() didn't over-write | 1024 | /* nfs4_copy_delegation_stateid() didn't over-write |
| 1022 | * dst, so it still has the lock stateid which we now | 1025 | * dst, so it still has the lock stateid which we now |
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; |
diff --git a/fs/reiserfs/do_balan.c b/fs/reiserfs/do_balan.c index 2b7882b508db..9a3c68cf6026 100644 --- a/fs/reiserfs/do_balan.c +++ b/fs/reiserfs/do_balan.c | |||
| @@ -324,23 +324,17 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h | |||
| 324 | switch (flag) { | 324 | switch (flag) { |
| 325 | case M_INSERT: /* insert item into L[0] */ | 325 | case M_INSERT: /* insert item into L[0] */ |
| 326 | 326 | ||
| 327 | if (item_pos == tb->lnum[0] - 1 | 327 | if (item_pos == tb->lnum[0] - 1 && tb->lbytes != -1) { |
| 328 | && tb->lbytes != -1) { | ||
| 329 | /* part of new item falls into L[0] */ | 328 | /* part of new item falls into L[0] */ |
| 330 | int new_item_len; | 329 | int new_item_len; |
| 331 | int version; | 330 | int version; |
| 332 | 331 | ||
| 333 | ret_val = | 332 | ret_val = leaf_shift_left(tb, tb->lnum[0] - 1, -1); |
| 334 | leaf_shift_left(tb, tb->lnum[0] - 1, | ||
| 335 | -1); | ||
| 336 | 333 | ||
| 337 | /* Calculate item length to insert to S[0] */ | 334 | /* Calculate item length to insert to S[0] */ |
| 338 | new_item_len = | 335 | new_item_len = ih_item_len(ih) - tb->lbytes; |
| 339 | ih_item_len(ih) - tb->lbytes; | ||
| 340 | /* Calculate and check item length to insert to L[0] */ | 336 | /* Calculate and check item length to insert to L[0] */ |
| 341 | put_ih_item_len(ih, | 337 | put_ih_item_len(ih, ih_item_len(ih) - new_item_len); |
| 342 | ih_item_len(ih) - | ||
| 343 | new_item_len); | ||
| 344 | 338 | ||
| 345 | RFALSE(ih_item_len(ih) <= 0, | 339 | RFALSE(ih_item_len(ih) <= 0, |
| 346 | "PAP-12080: there is nothing to insert into L[0]: ih_item_len=%d", | 340 | "PAP-12080: there is nothing to insert into L[0]: ih_item_len=%d", |
| @@ -349,30 +343,18 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h | |||
| 349 | /* Insert new item into L[0] */ | 343 | /* Insert new item into L[0] */ |
| 350 | buffer_info_init_left(tb, &bi); | 344 | buffer_info_init_left(tb, &bi); |
| 351 | leaf_insert_into_buf(&bi, | 345 | leaf_insert_into_buf(&bi, |
| 352 | n + item_pos - | 346 | n + item_pos - ret_val, ih, body, |
| 353 | ret_val, ih, body, | 347 | zeros_num > ih_item_len(ih) ? ih_item_len(ih) : zeros_num); |
| 354 | zeros_num > | ||
| 355 | ih_item_len(ih) ? | ||
| 356 | ih_item_len(ih) : | ||
| 357 | zeros_num); | ||
| 358 | 348 | ||
| 359 | version = ih_version(ih); | 349 | version = ih_version(ih); |
| 360 | 350 | ||
| 361 | /* Calculate key component, item length and body to insert into S[0] */ | 351 | /* Calculate key component, item length and body to insert into S[0] */ |
| 362 | set_le_ih_k_offset(ih, | 352 | set_le_ih_k_offset(ih, le_ih_k_offset(ih) + |
| 363 | le_ih_k_offset(ih) + | 353 | (tb-> lbytes << (is_indirect_le_ih(ih) ? tb->tb_sb-> s_blocksize_bits - UNFM_P_SHIFT : 0))); |
| 364 | (tb-> | ||
| 365 | lbytes << | ||
| 366 | (is_indirect_le_ih | ||
| 367 | (ih) ? tb->tb_sb-> | ||
| 368 | s_blocksize_bits - | ||
| 369 | UNFM_P_SHIFT : | ||
| 370 | 0))); | ||
| 371 | 354 | ||
| 372 | put_ih_item_len(ih, new_item_len); | 355 | put_ih_item_len(ih, new_item_len); |
| 373 | if (tb->lbytes > zeros_num) { | 356 | if (tb->lbytes > zeros_num) { |
| 374 | body += | 357 | body += (tb->lbytes - zeros_num); |
| 375 | (tb->lbytes - zeros_num); | ||
| 376 | zeros_num = 0; | 358 | zeros_num = 0; |
| 377 | } else | 359 | } else |
| 378 | zeros_num -= tb->lbytes; | 360 | zeros_num -= tb->lbytes; |
| @@ -383,15 +365,10 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h | |||
| 383 | } else { | 365 | } else { |
| 384 | /* new item in whole falls into L[0] */ | 366 | /* new item in whole falls into L[0] */ |
| 385 | /* Shift lnum[0]-1 items to L[0] */ | 367 | /* Shift lnum[0]-1 items to L[0] */ |
| 386 | ret_val = | 368 | ret_val = leaf_shift_left(tb, tb->lnum[0] - 1, tb->lbytes); |
| 387 | leaf_shift_left(tb, tb->lnum[0] - 1, | ||
| 388 | tb->lbytes); | ||
| 389 | /* Insert new item into L[0] */ | 369 | /* Insert new item into L[0] */ |
| 390 | buffer_info_init_left(tb, &bi); | 370 | buffer_info_init_left(tb, &bi); |
| 391 | leaf_insert_into_buf(&bi, | 371 | leaf_insert_into_buf(&bi, n + item_pos - ret_val, ih, body, zeros_num); |
| 392 | n + item_pos - | ||
| 393 | ret_val, ih, body, | ||
| 394 | zeros_num); | ||
| 395 | tb->insert_size[0] = 0; | 372 | tb->insert_size[0] = 0; |
| 396 | zeros_num = 0; | 373 | zeros_num = 0; |
| 397 | } | 374 | } |
| @@ -399,264 +376,117 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h | |||
| 399 | 376 | ||
| 400 | case M_PASTE: /* append item in L[0] */ | 377 | case M_PASTE: /* append item in L[0] */ |
| 401 | 378 | ||
| 402 | if (item_pos == tb->lnum[0] - 1 | 379 | if (item_pos == tb->lnum[0] - 1 && tb->lbytes != -1) { |
| 403 | && tb->lbytes != -1) { | ||
| 404 | /* we must shift the part of the appended item */ | 380 | /* we must shift the part of the appended item */ |
| 405 | if (is_direntry_le_ih | 381 | if (is_direntry_le_ih(B_N_PITEM_HEAD(tbS0, item_pos))) { |
| 406 | (B_N_PITEM_HEAD(tbS0, item_pos))) { | ||
| 407 | 382 | ||
| 408 | RFALSE(zeros_num, | 383 | RFALSE(zeros_num, |
| 409 | "PAP-12090: invalid parameter in case of a directory"); | 384 | "PAP-12090: invalid parameter in case of a directory"); |
| 410 | /* directory item */ | 385 | /* directory item */ |
| 411 | if (tb->lbytes > pos_in_item) { | 386 | if (tb->lbytes > pos_in_item) { |
| 412 | /* new directory entry falls into L[0] */ | 387 | /* new directory entry falls into L[0] */ |
| 413 | struct item_head | 388 | struct item_head *pasted; |
| 414 | *pasted; | 389 | int l_pos_in_item = pos_in_item; |
| 415 | int l_pos_in_item = | ||
| 416 | pos_in_item; | ||
| 417 | 390 | ||
| 418 | /* Shift lnum[0] - 1 items in whole. Shift lbytes - 1 entries from given directory item */ | 391 | /* Shift lnum[0] - 1 items in whole. Shift lbytes - 1 entries from given directory item */ |
| 419 | ret_val = | 392 | ret_val = leaf_shift_left(tb, tb->lnum[0], tb->lbytes-1); |
| 420 | leaf_shift_left(tb, | 393 | if (ret_val && !item_pos) { |
| 421 | tb-> | 394 | pasted = B_N_PITEM_HEAD(tb->L[0], B_NR_ITEMS(tb->L[0]) - 1); |
| 422 | lnum | 395 | l_pos_in_item += I_ENTRY_COUNT(pasted) - (tb->lbytes -1); |
| 423 | [0], | ||
| 424 | tb-> | ||
| 425 | lbytes | ||
| 426 | - | ||
| 427 | 1); | ||
| 428 | if (ret_val | ||
| 429 | && !item_pos) { | ||
| 430 | pasted = | ||
| 431 | B_N_PITEM_HEAD | ||
| 432 | (tb->L[0], | ||
| 433 | B_NR_ITEMS | ||
| 434 | (tb-> | ||
| 435 | L[0]) - | ||
| 436 | 1); | ||
| 437 | l_pos_in_item += | ||
| 438 | I_ENTRY_COUNT | ||
| 439 | (pasted) - | ||
| 440 | (tb-> | ||
| 441 | lbytes - | ||
| 442 | 1); | ||
| 443 | } | 396 | } |
| 444 | 397 | ||
| 445 | /* Append given directory entry to directory item */ | 398 | /* Append given directory entry to directory item */ |
| 446 | buffer_info_init_left(tb, &bi); | 399 | buffer_info_init_left(tb, &bi); |
| 447 | leaf_paste_in_buffer | 400 | leaf_paste_in_buffer(&bi, n + item_pos - ret_val, l_pos_in_item, tb->insert_size[0], body, zeros_num); |
| 448 | (&bi, | ||
| 449 | n + item_pos - | ||
| 450 | ret_val, | ||
| 451 | l_pos_in_item, | ||
| 452 | tb->insert_size[0], | ||
| 453 | body, zeros_num); | ||
| 454 | 401 | ||
| 455 | /* previous string prepared space for pasting new entry, following string pastes this entry */ | 402 | /* previous string prepared space for pasting new entry, following string pastes this entry */ |
| 456 | 403 | ||
| 457 | /* when we have merge directory item, pos_in_item has been changed too */ | 404 | /* when we have merge directory item, pos_in_item has been changed too */ |
| 458 | 405 | ||
| 459 | /* paste new directory entry. 1 is entry number */ | 406 | /* paste new directory entry. 1 is entry number */ |
| 460 | leaf_paste_entries(&bi, | 407 | leaf_paste_entries(&bi, n + item_pos - ret_val, l_pos_in_item, |
| 461 | n + | 408 | 1, (struct reiserfs_de_head *) body, |
| 462 | item_pos | 409 | body + DEH_SIZE, tb->insert_size[0]); |
| 463 | - | ||
| 464 | ret_val, | ||
| 465 | l_pos_in_item, | ||
| 466 | 1, | ||
| 467 | (struct | ||
| 468 | reiserfs_de_head | ||
| 469 | *) | ||
| 470 | body, | ||
| 471 | body | ||
| 472 | + | ||
| 473 | DEH_SIZE, | ||
| 474 | tb-> | ||
| 475 | insert_size | ||
| 476 | [0] | ||
| 477 | ); | ||
| 478 | tb->insert_size[0] = 0; | 410 | tb->insert_size[0] = 0; |
| 479 | } else { | 411 | } else { |
| 480 | /* new directory item doesn't fall into L[0] */ | 412 | /* new directory item doesn't fall into L[0] */ |
| 481 | /* Shift lnum[0]-1 items in whole. Shift lbytes directory entries from directory item number lnum[0] */ | 413 | /* Shift lnum[0]-1 items in whole. Shift lbytes directory entries from directory item number lnum[0] */ |
| 482 | leaf_shift_left(tb, | 414 | leaf_shift_left(tb, tb->lnum[0], tb->lbytes); |
| 483 | tb-> | ||
| 484 | lnum[0], | ||
| 485 | tb-> | ||
| 486 | lbytes); | ||
| 487 | } | 415 | } |
| 488 | /* Calculate new position to append in item body */ | 416 | /* Calculate new position to append in item body */ |
| 489 | pos_in_item -= tb->lbytes; | 417 | pos_in_item -= tb->lbytes; |
| 490 | } else { | 418 | } else { |
| 491 | /* regular object */ | 419 | /* regular object */ |
| 492 | RFALSE(tb->lbytes <= 0, | 420 | RFALSE(tb->lbytes <= 0, "PAP-12095: there is nothing to shift to L[0]. lbytes=%d", tb->lbytes); |
| 493 | "PAP-12095: there is nothing to shift to L[0]. lbytes=%d", | 421 | RFALSE(pos_in_item != ih_item_len(B_N_PITEM_HEAD(tbS0, item_pos)), |
| 494 | tb->lbytes); | ||
| 495 | RFALSE(pos_in_item != | ||
| 496 | ih_item_len | ||
| 497 | (B_N_PITEM_HEAD | ||
| 498 | (tbS0, item_pos)), | ||
| 499 | "PAP-12100: incorrect position to paste: item_len=%d, pos_in_item=%d", | 422 | "PAP-12100: incorrect position to paste: item_len=%d, pos_in_item=%d", |
| 500 | ih_item_len | 423 | ih_item_len(B_N_PITEM_HEAD(tbS0, item_pos)),pos_in_item); |
| 501 | (B_N_PITEM_HEAD | ||
| 502 | (tbS0, item_pos)), | ||
| 503 | pos_in_item); | ||
| 504 | 424 | ||
| 505 | if (tb->lbytes >= pos_in_item) { | 425 | if (tb->lbytes >= pos_in_item) { |
| 506 | /* appended item will be in L[0] in whole */ | 426 | /* appended item will be in L[0] in whole */ |
| 507 | int l_n; | 427 | int l_n; |
| 508 | 428 | ||
| 509 | /* this bytes number must be appended to the last item of L[h] */ | 429 | /* this bytes number must be appended to the last item of L[h] */ |
| 510 | l_n = | 430 | l_n = tb->lbytes - pos_in_item; |
| 511 | tb->lbytes - | ||
| 512 | pos_in_item; | ||
| 513 | 431 | ||
| 514 | /* Calculate new insert_size[0] */ | 432 | /* Calculate new insert_size[0] */ |
| 515 | tb->insert_size[0] -= | 433 | tb->insert_size[0] -= l_n; |
| 516 | l_n; | ||
| 517 | 434 | ||
| 518 | RFALSE(tb-> | 435 | RFALSE(tb->insert_size[0] <= 0, |
| 519 | insert_size[0] <= | ||
| 520 | 0, | ||
| 521 | "PAP-12105: there is nothing to paste into L[0]. insert_size=%d", | 436 | "PAP-12105: there is nothing to paste into L[0]. insert_size=%d", |
| 522 | tb-> | 437 | tb->insert_size[0]); |
| 523 | insert_size[0]); | 438 | ret_val = leaf_shift_left(tb, tb->lnum[0], ih_item_len |
| 524 | ret_val = | 439 | (B_N_PITEM_HEAD(tbS0, item_pos))); |
| 525 | leaf_shift_left(tb, | ||
| 526 | tb-> | ||
| 527 | lnum | ||
| 528 | [0], | ||
| 529 | ih_item_len | ||
| 530 | (B_N_PITEM_HEAD | ||
| 531 | (tbS0, | ||
| 532 | item_pos))); | ||
| 533 | /* Append to body of item in L[0] */ | 440 | /* Append to body of item in L[0] */ |
| 534 | buffer_info_init_left(tb, &bi); | 441 | buffer_info_init_left(tb, &bi); |
| 535 | leaf_paste_in_buffer | 442 | leaf_paste_in_buffer |
| 536 | (&bi, | 443 | (&bi, n + item_pos - ret_val, ih_item_len |
| 537 | n + item_pos - | 444 | (B_N_PITEM_HEAD(tb->L[0], n + item_pos - ret_val)), |
| 538 | ret_val, | 445 | l_n, body, |
| 539 | ih_item_len | 446 | zeros_num > l_n ? l_n : zeros_num); |
| 540 | (B_N_PITEM_HEAD | ||
| 541 | (tb->L[0], | ||
| 542 | n + item_pos - | ||
| 543 | ret_val)), l_n, | ||
| 544 | body, | ||
| 545 | zeros_num > | ||
| 546 | l_n ? l_n : | ||
| 547 | zeros_num); | ||
| 548 | /* 0-th item in S0 can be only of DIRECT type when l_n != 0 */ | 447 | /* 0-th item in S0 can be only of DIRECT type when l_n != 0 */ |
| 549 | { | 448 | { |
| 550 | int version; | 449 | int version; |
| 551 | int temp_l = | 450 | int temp_l = l_n; |
| 552 | l_n; | 451 | |
| 553 | 452 | RFALSE(ih_item_len(B_N_PITEM_HEAD(tbS0, 0)), | |
| 554 | RFALSE | ||
| 555 | (ih_item_len | ||
| 556 | (B_N_PITEM_HEAD | ||
| 557 | (tbS0, | ||
| 558 | 0)), | ||
| 559 | "PAP-12106: item length must be 0"); | 453 | "PAP-12106: item length must be 0"); |
| 560 | RFALSE | 454 | RFALSE(comp_short_le_keys(B_N_PKEY(tbS0, 0), B_N_PKEY |
| 561 | (comp_short_le_keys | 455 | (tb->L[0], n + item_pos - ret_val)), |
| 562 | (B_N_PKEY | ||
| 563 | (tbS0, 0), | ||
| 564 | B_N_PKEY | ||
| 565 | (tb->L[0], | ||
| 566 | n + | ||
| 567 | item_pos | ||
| 568 | - | ||
| 569 | ret_val)), | ||
| 570 | "PAP-12107: items must be of the same file"); | 456 | "PAP-12107: items must be of the same file"); |
| 571 | if (is_indirect_le_ih(B_N_PITEM_HEAD(tb->L[0], n + item_pos - ret_val))) { | 457 | if (is_indirect_le_ih(B_N_PITEM_HEAD(tb->L[0], n + item_pos - ret_val))) { |
| 572 | temp_l = | 458 | temp_l = l_n << (tb->tb_sb-> s_blocksize_bits - UNFM_P_SHIFT); |
| 573 | l_n | ||
| 574 | << | ||
| 575 | (tb-> | ||
| 576 | tb_sb-> | ||
| 577 | s_blocksize_bits | ||
| 578 | - | ||
| 579 | UNFM_P_SHIFT); | ||
| 580 | } | 459 | } |
| 581 | /* update key of first item in S0 */ | 460 | /* update key of first item in S0 */ |
| 582 | version = | 461 | version = ih_version(B_N_PITEM_HEAD(tbS0, 0)); |
| 583 | ih_version | 462 | set_le_key_k_offset(version, B_N_PKEY(tbS0, 0), |
| 584 | (B_N_PITEM_HEAD | 463 | le_key_k_offset(version,B_N_PKEY(tbS0, 0)) + temp_l); |
| 585 | (tbS0, 0)); | ||
| 586 | set_le_key_k_offset | ||
| 587 | (version, | ||
| 588 | B_N_PKEY | ||
| 589 | (tbS0, 0), | ||
| 590 | le_key_k_offset | ||
| 591 | (version, | ||
| 592 | B_N_PKEY | ||
| 593 | (tbS0, | ||
| 594 | 0)) + | ||
| 595 | temp_l); | ||
| 596 | /* update left delimiting key */ | 464 | /* update left delimiting key */ |
| 597 | set_le_key_k_offset | 465 | set_le_key_k_offset(version, B_N_PDELIM_KEY(tb->CFL[0], tb->lkey[0]), |
| 598 | (version, | 466 | le_key_k_offset(version, B_N_PDELIM_KEY(tb->CFL[0], tb->lkey[0])) + temp_l); |
| 599 | B_N_PDELIM_KEY | ||
| 600 | (tb-> | ||
| 601 | CFL[0], | ||
| 602 | tb-> | ||
| 603 | lkey[0]), | ||
| 604 | le_key_k_offset | ||
| 605 | (version, | ||
| 606 | B_N_PDELIM_KEY | ||
| 607 | (tb-> | ||
| 608 | CFL[0], | ||
| 609 | tb-> | ||
| 610 | lkey[0])) | ||
| 611 | + temp_l); | ||
| 612 | } | 467 | } |
| 613 | 468 | ||
| 614 | /* Calculate new body, position in item and insert_size[0] */ | 469 | /* Calculate new body, position in item and insert_size[0] */ |
| 615 | if (l_n > zeros_num) { | 470 | if (l_n > zeros_num) { |
| 616 | body += | 471 | body += (l_n - zeros_num); |
| 617 | (l_n - | ||
| 618 | zeros_num); | ||
| 619 | zeros_num = 0; | 472 | zeros_num = 0; |
| 620 | } else | 473 | } else |
| 621 | zeros_num -= | 474 | zeros_num -= l_n; |
| 622 | l_n; | ||
| 623 | pos_in_item = 0; | 475 | pos_in_item = 0; |
| 624 | 476 | ||
| 625 | RFALSE | 477 | RFALSE(comp_short_le_keys(B_N_PKEY(tbS0, 0), B_N_PKEY(tb->L[0], B_NR_ITEMS(tb->L[0]) - 1)) |
| 626 | (comp_short_le_keys | 478 | || !op_is_left_mergeable(B_N_PKEY(tbS0, 0), tbS0->b_size) |
| 627 | (B_N_PKEY(tbS0, 0), | 479 | || !op_is_left_mergeable(B_N_PDELIM_KEY(tb->CFL[0], tb->lkey[0]), tbS0->b_size), |
| 628 | B_N_PKEY(tb->L[0], | ||
| 629 | B_NR_ITEMS | ||
| 630 | (tb-> | ||
| 631 | L[0]) - | ||
| 632 | 1)) | ||
| 633 | || | ||
| 634 | !op_is_left_mergeable | ||
| 635 | (B_N_PKEY(tbS0, 0), | ||
| 636 | tbS0->b_size) | ||
| 637 | || | ||
| 638 | !op_is_left_mergeable | ||
| 639 | (B_N_PDELIM_KEY | ||
| 640 | (tb->CFL[0], | ||
| 641 | tb->lkey[0]), | ||
| 642 | tbS0->b_size), | ||
| 643 | "PAP-12120: item must be merge-able with left neighboring item"); | 480 | "PAP-12120: item must be merge-able with left neighboring item"); |
| 644 | } else { /* only part of the appended item will be in L[0] */ | 481 | } else { /* only part of the appended item will be in L[0] */ |
| 645 | 482 | ||
| 646 | /* Calculate position in item for append in S[0] */ | 483 | /* Calculate position in item for append in S[0] */ |
| 647 | pos_in_item -= | 484 | pos_in_item -= tb->lbytes; |
| 648 | tb->lbytes; | ||
| 649 | 485 | ||
| 650 | RFALSE(pos_in_item <= 0, | 486 | RFALSE(pos_in_item <= 0, "PAP-12125: no place for paste. pos_in_item=%d", pos_in_item); |
| 651 | "PAP-12125: no place for paste. pos_in_item=%d", | ||
| 652 | pos_in_item); | ||
| 653 | 487 | ||
| 654 | /* Shift lnum[0] - 1 items in whole. Shift lbytes - 1 byte from item number lnum[0] */ | 488 | /* Shift lnum[0] - 1 items in whole. Shift lbytes - 1 byte from item number lnum[0] */ |
| 655 | leaf_shift_left(tb, | 489 | leaf_shift_left(tb, tb->lnum[0], tb->lbytes); |
| 656 | tb-> | ||
| 657 | lnum[0], | ||
| 658 | tb-> | ||
| 659 | lbytes); | ||
| 660 | } | 490 | } |
| 661 | } | 491 | } |
| 662 | } else { /* appended item will be in L[0] in whole */ | 492 | } else { /* appended item will be in L[0] in whole */ |
| @@ -665,52 +495,30 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h | |||
| 665 | 495 | ||
| 666 | if (!item_pos && op_is_left_mergeable(B_N_PKEY(tbS0, 0), tbS0->b_size)) { /* if we paste into first item of S[0] and it is left mergable */ | 496 | if (!item_pos && op_is_left_mergeable(B_N_PKEY(tbS0, 0), tbS0->b_size)) { /* if we paste into first item of S[0] and it is left mergable */ |
| 667 | /* then increment pos_in_item by the size of the last item in L[0] */ | 497 | /* then increment pos_in_item by the size of the last item in L[0] */ |
| 668 | pasted = | 498 | pasted = B_N_PITEM_HEAD(tb->L[0], n - 1); |
| 669 | B_N_PITEM_HEAD(tb->L[0], | ||
| 670 | n - 1); | ||
| 671 | if (is_direntry_le_ih(pasted)) | 499 | if (is_direntry_le_ih(pasted)) |
| 672 | pos_in_item += | 500 | pos_in_item += ih_entry_count(pasted); |
| 673 | ih_entry_count | ||
| 674 | (pasted); | ||
| 675 | else | 501 | else |
| 676 | pos_in_item += | 502 | pos_in_item += ih_item_len(pasted); |
| 677 | ih_item_len(pasted); | ||
| 678 | } | 503 | } |
| 679 | 504 | ||
| 680 | /* Shift lnum[0] - 1 items in whole. Shift lbytes - 1 byte from item number lnum[0] */ | 505 | /* Shift lnum[0] - 1 items in whole. Shift lbytes - 1 byte from item number lnum[0] */ |
| 681 | ret_val = | 506 | ret_val = leaf_shift_left(tb, tb->lnum[0], tb->lbytes); |
| 682 | leaf_shift_left(tb, tb->lnum[0], | ||
| 683 | tb->lbytes); | ||
| 684 | /* Append to body of item in L[0] */ | 507 | /* Append to body of item in L[0] */ |
| 685 | buffer_info_init_left(tb, &bi); | 508 | buffer_info_init_left(tb, &bi); |
| 686 | leaf_paste_in_buffer(&bi, | 509 | leaf_paste_in_buffer(&bi, n + item_pos - ret_val, |
| 687 | n + item_pos - | ||
| 688 | ret_val, | ||
| 689 | pos_in_item, | 510 | pos_in_item, |
| 690 | tb->insert_size[0], | 511 | tb->insert_size[0], |
| 691 | body, zeros_num); | 512 | body, zeros_num); |
| 692 | 513 | ||
| 693 | /* if appended item is directory, paste entry */ | 514 | /* if appended item is directory, paste entry */ |
| 694 | pasted = | 515 | pasted = B_N_PITEM_HEAD(tb->L[0], n + item_pos - ret_val); |
| 695 | B_N_PITEM_HEAD(tb->L[0], | ||
| 696 | n + item_pos - | ||
| 697 | ret_val); | ||
| 698 | if (is_direntry_le_ih(pasted)) | 516 | if (is_direntry_le_ih(pasted)) |
| 699 | leaf_paste_entries(&bi, | 517 | leaf_paste_entries(&bi, n + item_pos - ret_val, |
| 700 | n + | 518 | pos_in_item, 1, |
| 701 | item_pos - | 519 | (struct reiserfs_de_head *) body, |
| 702 | ret_val, | 520 | body + DEH_SIZE, |
| 703 | pos_in_item, | 521 | tb->insert_size[0]); |
| 704 | 1, | ||
| 705 | (struct | ||
| 706 | reiserfs_de_head | ||
| 707 | *)body, | ||
| 708 | body + | ||
| 709 | DEH_SIZE, | ||
| 710 | tb-> | ||
| 711 | insert_size | ||
| 712 | [0] | ||
| 713 | ); | ||
| 714 | /* if appended item is indirect item, put unformatted node into un list */ | 522 | /* if appended item is indirect item, put unformatted node into un list */ |
| 715 | if (is_indirect_le_ih(pasted)) | 523 | if (is_indirect_le_ih(pasted)) |
| 716 | set_ih_free_space(pasted, 0); | 524 | set_ih_free_space(pasted, 0); |
| @@ -722,13 +530,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h | |||
| 722 | reiserfs_panic(tb->tb_sb, "PAP-12130", | 530 | reiserfs_panic(tb->tb_sb, "PAP-12130", |
| 723 | "lnum > 0: unexpected mode: " | 531 | "lnum > 0: unexpected mode: " |
| 724 | " %s(%d)", | 532 | " %s(%d)", |
| 725 | (flag == | 533 | (flag == M_DELETE) ? "DELETE" : ((flag == M_CUT) ? "CUT" : "UNKNOWN"), flag); |
| 726 | M_DELETE) ? "DELETE" : ((flag == | ||
| 727 | M_CUT) | ||
| 728 | ? "CUT" | ||
| 729 | : | ||
| 730 | "UNKNOWN"), | ||
| 731 | flag); | ||
| 732 | } | 534 | } |
| 733 | } else { | 535 | } else { |
| 734 | /* new item doesn't fall into L[0] */ | 536 | /* new item doesn't fall into L[0] */ |
| @@ -748,14 +550,12 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h | |||
| 748 | case M_INSERT: /* insert item */ | 550 | case M_INSERT: /* insert item */ |
| 749 | if (n - tb->rnum[0] < item_pos) { /* new item or its part falls to R[0] */ | 551 | if (n - tb->rnum[0] < item_pos) { /* new item or its part falls to R[0] */ |
| 750 | if (item_pos == n - tb->rnum[0] + 1 && tb->rbytes != -1) { /* part of new item falls into R[0] */ | 552 | if (item_pos == n - tb->rnum[0] + 1 && tb->rbytes != -1) { /* part of new item falls into R[0] */ |
| 751 | loff_t old_key_comp, old_len, | 553 | loff_t old_key_comp, old_len, r_zeros_number; |
| 752 | r_zeros_number; | ||
| 753 | const char *r_body; | 554 | const char *r_body; |
| 754 | int version; | 555 | int version; |
| 755 | loff_t offset; | 556 | loff_t offset; |
| 756 | 557 | ||
| 757 | leaf_shift_right(tb, tb->rnum[0] - 1, | 558 | leaf_shift_right(tb, tb->rnum[0] - 1, -1); |
| 758 | -1); | ||
| 759 | 559 | ||
| 760 | version = ih_version(ih); | 560 | version = ih_version(ih); |
| 761 | /* Remember key component and item length */ | 561 | /* Remember key component and item length */ |
| @@ -763,29 +563,17 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h | |||
| 763 | old_len = ih_item_len(ih); | 563 | old_len = ih_item_len(ih); |
| 764 | 564 | ||
| 765 | /* Calculate key component and item length to insert into R[0] */ | 565 | /* Calculate key component and item length to insert into R[0] */ |
| 766 | offset = | 566 | offset = le_ih_k_offset(ih) + ((old_len - tb->rbytes) << (is_indirect_le_ih(ih) ? tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT : 0)); |
| 767 | le_ih_k_offset(ih) + | ||
| 768 | ((old_len - | ||
| 769 | tb-> | ||
| 770 | rbytes) << (is_indirect_le_ih(ih) | ||
| 771 | ? tb->tb_sb-> | ||
| 772 | s_blocksize_bits - | ||
| 773 | UNFM_P_SHIFT : 0)); | ||
| 774 | set_le_ih_k_offset(ih, offset); | 567 | set_le_ih_k_offset(ih, offset); |
| 775 | put_ih_item_len(ih, tb->rbytes); | 568 | put_ih_item_len(ih, tb->rbytes); |
| 776 | /* Insert part of the item into R[0] */ | 569 | /* Insert part of the item into R[0] */ |
| 777 | buffer_info_init_right(tb, &bi); | 570 | buffer_info_init_right(tb, &bi); |
| 778 | if ((old_len - tb->rbytes) > zeros_num) { | 571 | if ((old_len - tb->rbytes) > zeros_num) { |
| 779 | r_zeros_number = 0; | 572 | r_zeros_number = 0; |
| 780 | r_body = | 573 | r_body = body + (old_len - tb->rbytes) - zeros_num; |
| 781 | body + (old_len - | ||
| 782 | tb->rbytes) - | ||
| 783 | zeros_num; | ||
| 784 | } else { | 574 | } else { |
| 785 | r_body = body; | 575 | r_body = body; |
| 786 | r_zeros_number = | 576 | r_zeros_number = zeros_num - (old_len - tb->rbytes); |
| 787 | zeros_num - (old_len - | ||
| 788 | tb->rbytes); | ||
| 789 | zeros_num -= r_zeros_number; | 577 | zeros_num -= r_zeros_number; |
| 790 | } | 578 | } |
| 791 | 579 | ||
| @@ -798,25 +586,18 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h | |||
| 798 | 586 | ||
| 799 | /* Calculate key component and item length to insert into S[0] */ | 587 | /* Calculate key component and item length to insert into S[0] */ |
| 800 | set_le_ih_k_offset(ih, old_key_comp); | 588 | set_le_ih_k_offset(ih, old_key_comp); |
| 801 | put_ih_item_len(ih, | 589 | put_ih_item_len(ih, old_len - tb->rbytes); |
| 802 | old_len - tb->rbytes); | ||
| 803 | 590 | ||
| 804 | tb->insert_size[0] -= tb->rbytes; | 591 | tb->insert_size[0] -= tb->rbytes; |
| 805 | 592 | ||
| 806 | } else { /* whole new item falls into R[0] */ | 593 | } else { /* whole new item falls into R[0] */ |
| 807 | 594 | ||
| 808 | /* Shift rnum[0]-1 items to R[0] */ | 595 | /* Shift rnum[0]-1 items to R[0] */ |
| 809 | ret_val = | 596 | ret_val = leaf_shift_right(tb, tb->rnum[0] - 1, tb->rbytes); |
| 810 | leaf_shift_right(tb, | ||
| 811 | tb->rnum[0] - 1, | ||
| 812 | tb->rbytes); | ||
| 813 | /* Insert new item into R[0] */ | 597 | /* Insert new item into R[0] */ |
| 814 | buffer_info_init_right(tb, &bi); | 598 | buffer_info_init_right(tb, &bi); |
| 815 | leaf_insert_into_buf(&bi, | 599 | leaf_insert_into_buf(&bi, item_pos - n + tb->rnum[0] - 1, |
| 816 | item_pos - n + | 600 | ih, body, zeros_num); |
| 817 | tb->rnum[0] - 1, | ||
| 818 | ih, body, | ||
| 819 | zeros_num); | ||
| 820 | 601 | ||
| 821 | if (item_pos - n + tb->rnum[0] - 1 == 0) { | 602 | if (item_pos - n + tb->rnum[0] - 1 == 0) { |
| 822 | replace_key(tb, tb->CFR[0], | 603 | replace_key(tb, tb->CFR[0], |
| @@ -841,200 +622,97 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h | |||
| 841 | 622 | ||
| 842 | RFALSE(zeros_num, | 623 | RFALSE(zeros_num, |
| 843 | "PAP-12145: invalid parameter in case of a directory"); | 624 | "PAP-12145: invalid parameter in case of a directory"); |
| 844 | entry_count = | 625 | entry_count = I_ENTRY_COUNT(B_N_PITEM_HEAD |
| 845 | I_ENTRY_COUNT(B_N_PITEM_HEAD | 626 | (tbS0, item_pos)); |
| 846 | (tbS0, | ||
| 847 | item_pos)); | ||
| 848 | if (entry_count - tb->rbytes < | 627 | if (entry_count - tb->rbytes < |
| 849 | pos_in_item) | 628 | pos_in_item) |
| 850 | /* new directory entry falls into R[0] */ | 629 | /* new directory entry falls into R[0] */ |
| 851 | { | 630 | { |
| 852 | int paste_entry_position; | 631 | int paste_entry_position; |
| 853 | 632 | ||
| 854 | RFALSE(tb->rbytes - 1 >= | 633 | RFALSE(tb->rbytes - 1 >= entry_count || !tb-> insert_size[0], |
| 855 | entry_count | ||
| 856 | || !tb-> | ||
| 857 | insert_size[0], | ||
| 858 | "PAP-12150: no enough of entries to shift to R[0]: rbytes=%d, entry_count=%d", | 634 | "PAP-12150: no enough of entries to shift to R[0]: rbytes=%d, entry_count=%d", |
| 859 | tb->rbytes, | 635 | tb->rbytes, entry_count); |
| 860 | entry_count); | ||
| 861 | /* Shift rnum[0]-1 items in whole. Shift rbytes-1 directory entries from directory item number rnum[0] */ | 636 | /* Shift rnum[0]-1 items in whole. Shift rbytes-1 directory entries from directory item number rnum[0] */ |
| 862 | leaf_shift_right(tb, | 637 | leaf_shift_right(tb, tb->rnum[0], tb->rbytes - 1); |
| 863 | tb-> | ||
| 864 | rnum | ||
| 865 | [0], | ||
| 866 | tb-> | ||
| 867 | rbytes | ||
| 868 | - 1); | ||
| 869 | /* Paste given directory entry to directory item */ | 638 | /* Paste given directory entry to directory item */ |
| 870 | paste_entry_position = | 639 | paste_entry_position = pos_in_item - entry_count + tb->rbytes - 1; |
| 871 | pos_in_item - | ||
| 872 | entry_count + | ||
| 873 | tb->rbytes - 1; | ||
| 874 | buffer_info_init_right(tb, &bi); | 640 | buffer_info_init_right(tb, &bi); |
| 875 | leaf_paste_in_buffer | 641 | leaf_paste_in_buffer(&bi, 0, paste_entry_position, tb->insert_size[0], body, zeros_num); |
| 876 | (&bi, 0, | ||
| 877 | paste_entry_position, | ||
| 878 | tb->insert_size[0], | ||
| 879 | body, zeros_num); | ||
| 880 | /* paste entry */ | 642 | /* paste entry */ |
| 881 | leaf_paste_entries(&bi, | 643 | leaf_paste_entries(&bi, 0, paste_entry_position, 1, |
| 882 | 0, | 644 | (struct reiserfs_de_head *) body, |
| 883 | paste_entry_position, | 645 | body + DEH_SIZE, tb->insert_size[0]); |
| 884 | 1, | 646 | |
| 885 | (struct | 647 | if (paste_entry_position == 0) { |
| 886 | reiserfs_de_head | ||
| 887 | *) | ||
| 888 | body, | ||
| 889 | body | ||
| 890 | + | ||
| 891 | DEH_SIZE, | ||
| 892 | tb-> | ||
| 893 | insert_size | ||
| 894 | [0] | ||
| 895 | ); | ||
| 896 | |||
| 897 | if (paste_entry_position | ||
| 898 | == 0) { | ||
| 899 | /* change delimiting keys */ | 648 | /* change delimiting keys */ |
| 900 | replace_key(tb, | 649 | replace_key(tb, tb->CFR[0], tb->rkey[0], tb->R[0],0); |
| 901 | tb-> | ||
| 902 | CFR | ||
| 903 | [0], | ||
| 904 | tb-> | ||
| 905 | rkey | ||
| 906 | [0], | ||
| 907 | tb-> | ||
| 908 | R | ||
| 909 | [0], | ||
| 910 | 0); | ||
| 911 | } | 650 | } |
| 912 | 651 | ||
| 913 | tb->insert_size[0] = 0; | 652 | tb->insert_size[0] = 0; |
| 914 | pos_in_item++; | 653 | pos_in_item++; |
| 915 | } else { /* new directory entry doesn't fall into R[0] */ | 654 | } else { /* new directory entry doesn't fall into R[0] */ |
| 916 | 655 | ||
| 917 | leaf_shift_right(tb, | 656 | leaf_shift_right(tb, tb->rnum[0], tb->rbytes); |
| 918 | tb-> | ||
| 919 | rnum | ||
| 920 | [0], | ||
| 921 | tb-> | ||
| 922 | rbytes); | ||
| 923 | } | 657 | } |
| 924 | } else { /* regular object */ | 658 | } else { /* regular object */ |
| 925 | 659 | ||
| 926 | int n_shift, n_rem, | 660 | int n_shift, n_rem, r_zeros_number; |
| 927 | r_zeros_number; | ||
| 928 | const char *r_body; | 661 | const char *r_body; |
| 929 | 662 | ||
| 930 | /* Calculate number of bytes which must be shifted from appended item */ | 663 | /* Calculate number of bytes which must be shifted from appended item */ |
| 931 | if ((n_shift = | 664 | if ((n_shift = tb->rbytes - tb->insert_size[0]) < 0) |
| 932 | tb->rbytes - | ||
| 933 | tb->insert_size[0]) < 0) | ||
| 934 | n_shift = 0; | 665 | n_shift = 0; |
| 935 | 666 | ||
| 936 | RFALSE(pos_in_item != | 667 | RFALSE(pos_in_item != ih_item_len |
| 937 | ih_item_len | 668 | (B_N_PITEM_HEAD(tbS0, item_pos)), |
| 938 | (B_N_PITEM_HEAD | ||
| 939 | (tbS0, item_pos)), | ||
| 940 | "PAP-12155: invalid position to paste. ih_item_len=%d, pos_in_item=%d", | 669 | "PAP-12155: invalid position to paste. ih_item_len=%d, pos_in_item=%d", |
| 941 | pos_in_item, | 670 | pos_in_item, ih_item_len |
| 942 | ih_item_len | 671 | (B_N_PITEM_HEAD(tbS0, item_pos))); |
| 943 | (B_N_PITEM_HEAD | 672 | |
| 944 | (tbS0, item_pos))); | 673 | leaf_shift_right(tb, tb->rnum[0], n_shift); |
| 945 | |||
| 946 | leaf_shift_right(tb, | ||
| 947 | tb->rnum[0], | ||
| 948 | n_shift); | ||
| 949 | /* Calculate number of bytes which must remain in body after appending to R[0] */ | 674 | /* Calculate number of bytes which must remain in body after appending to R[0] */ |
| 950 | if ((n_rem = | 675 | if ((n_rem = tb->insert_size[0] - tb->rbytes) < 0) |
| 951 | tb->insert_size[0] - | ||
| 952 | tb->rbytes) < 0) | ||
| 953 | n_rem = 0; | 676 | n_rem = 0; |
| 954 | 677 | ||
| 955 | { | 678 | { |
| 956 | int version; | 679 | int version; |
| 957 | unsigned long temp_rem = | 680 | unsigned long temp_rem = n_rem; |
| 958 | n_rem; | 681 | |
| 959 | 682 | version = ih_version(B_N_PITEM_HEAD(tb->R[0], 0)); | |
| 960 | version = | 683 | if (is_indirect_le_key(version, B_N_PKEY(tb->R[0], 0))) { |
| 961 | ih_version | 684 | temp_rem = n_rem << (tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT); |
| 962 | (B_N_PITEM_HEAD | ||
| 963 | (tb->R[0], 0)); | ||
| 964 | if (is_indirect_le_key | ||
| 965 | (version, | ||
| 966 | B_N_PKEY(tb->R[0], | ||
| 967 | 0))) { | ||
| 968 | temp_rem = | ||
| 969 | n_rem << | ||
| 970 | (tb->tb_sb-> | ||
| 971 | s_blocksize_bits | ||
| 972 | - | ||
| 973 | UNFM_P_SHIFT); | ||
| 974 | } | 685 | } |
| 975 | set_le_key_k_offset | 686 | set_le_key_k_offset(version, B_N_PKEY(tb->R[0], 0), |
| 976 | (version, | 687 | le_key_k_offset(version, B_N_PKEY(tb->R[0], 0)) + temp_rem); |
| 977 | B_N_PKEY(tb->R[0], | 688 | set_le_key_k_offset(version, B_N_PDELIM_KEY(tb->CFR[0], tb->rkey[0]), |
| 978 | 0), | 689 | le_key_k_offset(version, B_N_PDELIM_KEY(tb->CFR[0], tb->rkey[0])) + temp_rem); |
| 979 | le_key_k_offset | ||
| 980 | (version, | ||
| 981 | B_N_PKEY(tb->R[0], | ||
| 982 | 0)) + | ||
| 983 | temp_rem); | ||
| 984 | set_le_key_k_offset | ||
| 985 | (version, | ||
| 986 | B_N_PDELIM_KEY(tb-> | ||
| 987 | CFR | ||
| 988 | [0], | ||
| 989 | tb-> | ||
| 990 | rkey | ||
| 991 | [0]), | ||
| 992 | le_key_k_offset | ||
| 993 | (version, | ||
| 994 | B_N_PDELIM_KEY | ||
| 995 | (tb->CFR[0], | ||
| 996 | tb->rkey[0])) + | ||
| 997 | temp_rem); | ||
| 998 | } | 690 | } |
| 999 | /* k_offset (B_N_PKEY(tb->R[0],0)) += n_rem; | 691 | /* k_offset (B_N_PKEY(tb->R[0],0)) += n_rem; |
| 1000 | k_offset (B_N_PDELIM_KEY(tb->CFR[0],tb->rkey[0])) += n_rem;*/ | 692 | k_offset (B_N_PDELIM_KEY(tb->CFR[0],tb->rkey[0])) += n_rem;*/ |
| 1001 | do_balance_mark_internal_dirty | 693 | do_balance_mark_internal_dirty(tb, tb->CFR[0], 0); |
| 1002 | (tb, tb->CFR[0], 0); | ||
| 1003 | 694 | ||
| 1004 | /* Append part of body into R[0] */ | 695 | /* Append part of body into R[0] */ |
| 1005 | buffer_info_init_right(tb, &bi); | 696 | buffer_info_init_right(tb, &bi); |
| 1006 | if (n_rem > zeros_num) { | 697 | if (n_rem > zeros_num) { |
| 1007 | r_zeros_number = 0; | 698 | r_zeros_number = 0; |
| 1008 | r_body = | 699 | r_body = body + n_rem - zeros_num; |
| 1009 | body + n_rem - | ||
| 1010 | zeros_num; | ||
| 1011 | } else { | 700 | } else { |
| 1012 | r_body = body; | 701 | r_body = body; |
| 1013 | r_zeros_number = | 702 | r_zeros_number = zeros_num - n_rem; |
| 1014 | zeros_num - n_rem; | 703 | zeros_num -= r_zeros_number; |
| 1015 | zeros_num -= | ||
| 1016 | r_zeros_number; | ||
| 1017 | } | 704 | } |
| 1018 | 705 | ||
| 1019 | leaf_paste_in_buffer(&bi, 0, | 706 | leaf_paste_in_buffer(&bi, 0, n_shift, |
| 1020 | n_shift, | 707 | tb->insert_size[0] - n_rem, |
| 1021 | tb-> | 708 | r_body, r_zeros_number); |
| 1022 | insert_size | 709 | |
| 1023 | [0] - | 710 | if (is_indirect_le_ih(B_N_PITEM_HEAD(tb->R[0], 0))) { |
| 1024 | n_rem, | ||
| 1025 | r_body, | ||
| 1026 | r_zeros_number); | ||
| 1027 | |||
| 1028 | if (is_indirect_le_ih | ||
| 1029 | (B_N_PITEM_HEAD | ||
| 1030 | (tb->R[0], 0))) { | ||
| 1031 | #if 0 | 711 | #if 0 |
| 1032 | RFALSE(n_rem, | 712 | RFALSE(n_rem, |
| 1033 | "PAP-12160: paste more than one unformatted node pointer"); | 713 | "PAP-12160: paste more than one unformatted node pointer"); |
| 1034 | #endif | 714 | #endif |
| 1035 | set_ih_free_space | 715 | set_ih_free_space(B_N_PITEM_HEAD(tb->R[0], 0), 0); |
| 1036 | (B_N_PITEM_HEAD | ||
| 1037 | (tb->R[0], 0), 0); | ||
| 1038 | } | 716 | } |
| 1039 | tb->insert_size[0] = n_rem; | 717 | tb->insert_size[0] = n_rem; |
| 1040 | if (!n_rem) | 718 | if (!n_rem) |
| @@ -1044,58 +722,28 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h | |||
| 1044 | 722 | ||
| 1045 | struct item_head *pasted; | 723 | struct item_head *pasted; |
| 1046 | 724 | ||
| 1047 | ret_val = | 725 | ret_val = leaf_shift_right(tb, tb->rnum[0], tb->rbytes); |
| 1048 | leaf_shift_right(tb, tb->rnum[0], | ||
| 1049 | tb->rbytes); | ||
| 1050 | /* append item in R[0] */ | 726 | /* append item in R[0] */ |
| 1051 | if (pos_in_item >= 0) { | 727 | if (pos_in_item >= 0) { |
| 1052 | buffer_info_init_right(tb, &bi); | 728 | buffer_info_init_right(tb, &bi); |
| 1053 | leaf_paste_in_buffer(&bi, | 729 | leaf_paste_in_buffer(&bi, item_pos - n + tb->rnum[0], pos_in_item, |
| 1054 | item_pos - | 730 | tb->insert_size[0], body, zeros_num); |
| 1055 | n + | ||
| 1056 | tb-> | ||
| 1057 | rnum[0], | ||
| 1058 | pos_in_item, | ||
| 1059 | tb-> | ||
| 1060 | insert_size | ||
| 1061 | [0], body, | ||
| 1062 | zeros_num); | ||
| 1063 | } | 731 | } |
| 1064 | 732 | ||
| 1065 | /* paste new entry, if item is directory item */ | 733 | /* paste new entry, if item is directory item */ |
| 1066 | pasted = | 734 | pasted = B_N_PITEM_HEAD(tb->R[0], item_pos - n + tb->rnum[0]); |
| 1067 | B_N_PITEM_HEAD(tb->R[0], | 735 | if (is_direntry_le_ih(pasted) && pos_in_item >= 0) { |
| 1068 | item_pos - n + | 736 | leaf_paste_entries(&bi, item_pos - n + tb->rnum[0], |
| 1069 | tb->rnum[0]); | 737 | pos_in_item, 1, |
| 1070 | if (is_direntry_le_ih(pasted) | 738 | (struct reiserfs_de_head *) body, |
| 1071 | && pos_in_item >= 0) { | 739 | body + DEH_SIZE, tb->insert_size[0]); |
| 1072 | leaf_paste_entries(&bi, | ||
| 1073 | item_pos - | ||
| 1074 | n + | ||
| 1075 | tb->rnum[0], | ||
| 1076 | pos_in_item, | ||
| 1077 | 1, | ||
| 1078 | (struct | ||
| 1079 | reiserfs_de_head | ||
| 1080 | *)body, | ||
| 1081 | body + | ||
| 1082 | DEH_SIZE, | ||
| 1083 | tb-> | ||
| 1084 | insert_size | ||
| 1085 | [0] | ||
| 1086 | ); | ||
| 1087 | if (!pos_in_item) { | 740 | if (!pos_in_item) { |
| 1088 | 741 | ||
| 1089 | RFALSE(item_pos - n + | 742 | RFALSE(item_pos - n + tb->rnum[0], |
| 1090 | tb->rnum[0], | ||
| 1091 | "PAP-12165: directory item must be first item of node when pasting is in 0th position"); | 743 | "PAP-12165: directory item must be first item of node when pasting is in 0th position"); |
| 1092 | 744 | ||
| 1093 | /* update delimiting keys */ | 745 | /* update delimiting keys */ |
| 1094 | replace_key(tb, | 746 | replace_key(tb, tb->CFR[0], tb->rkey[0], tb->R[0], 0); |
| 1095 | tb->CFR[0], | ||
| 1096 | tb->rkey[0], | ||
| 1097 | tb->R[0], | ||
| 1098 | 0); | ||
| 1099 | } | 747 | } |
| 1100 | } | 748 | } |
| 1101 | 749 | ||
| @@ -1111,22 +759,16 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h | |||
| 1111 | default: /* cases d and t */ | 759 | default: /* cases d and t */ |
| 1112 | reiserfs_panic(tb->tb_sb, "PAP-12175", | 760 | reiserfs_panic(tb->tb_sb, "PAP-12175", |
| 1113 | "rnum > 0: unexpected mode: %s(%d)", | 761 | "rnum > 0: unexpected mode: %s(%d)", |
| 1114 | (flag == | 762 | (flag == M_DELETE) ? "DELETE" : ((flag == M_CUT) ? "CUT" : "UNKNOWN"), flag); |
| 1115 | M_DELETE) ? "DELETE" : ((flag == | ||
| 1116 | M_CUT) ? "CUT" | ||
| 1117 | : "UNKNOWN"), | ||
| 1118 | flag); | ||
| 1119 | } | 763 | } |
| 1120 | 764 | ||
| 1121 | } | 765 | } |
| 1122 | 766 | ||
| 1123 | /* tb->rnum[0] > 0 */ | 767 | /* tb->rnum[0] > 0 */ |
| 1124 | RFALSE(tb->blknum[0] > 3, | 768 | RFALSE(tb->blknum[0] > 3, |
| 1125 | "PAP-12180: blknum can not be %d. It must be <= 3", | 769 | "PAP-12180: blknum can not be %d. It must be <= 3", tb->blknum[0]); |
| 1126 | tb->blknum[0]); | ||
| 1127 | RFALSE(tb->blknum[0] < 0, | 770 | RFALSE(tb->blknum[0] < 0, |
| 1128 | "PAP-12185: blknum can not be %d. It must be >= 0", | 771 | "PAP-12185: blknum can not be %d. It must be >= 0", tb->blknum[0]); |
| 1129 | tb->blknum[0]); | ||
| 1130 | 772 | ||
| 1131 | /* if while adding to a node we discover that it is possible to split | 773 | /* if while adding to a node we discover that it is possible to split |
| 1132 | it in two, and merge the left part into the left neighbor and the | 774 | it in two, and merge the left part into the left neighbor and the |
| @@ -1177,8 +819,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h | |||
| 1177 | 819 | ||
| 1178 | if (n - snum[i] < item_pos) { /* new item or it's part falls to first new node S_new[i] */ | 820 | if (n - snum[i] < item_pos) { /* new item or it's part falls to first new node S_new[i] */ |
| 1179 | if (item_pos == n - snum[i] + 1 && sbytes[i] != -1) { /* part of new item falls into S_new[i] */ | 821 | if (item_pos == n - snum[i] + 1 && sbytes[i] != -1) { /* part of new item falls into S_new[i] */ |
| 1180 | int old_key_comp, old_len, | 822 | int old_key_comp, old_len, r_zeros_number; |
| 1181 | r_zeros_number; | ||
| 1182 | const char *r_body; | 823 | const char *r_body; |
| 1183 | int version; | 824 | int version; |
| 1184 | 825 | ||
| @@ -1192,15 +833,8 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h | |||
| 1192 | old_len = ih_item_len(ih); | 833 | old_len = ih_item_len(ih); |
| 1193 | 834 | ||
| 1194 | /* Calculate key component and item length to insert into S_new[i] */ | 835 | /* Calculate key component and item length to insert into S_new[i] */ |
| 1195 | set_le_ih_k_offset(ih, | 836 | set_le_ih_k_offset(ih, le_ih_k_offset(ih) + |
| 1196 | le_ih_k_offset(ih) + | 837 | ((old_len - sbytes[i]) << (is_indirect_le_ih(ih) ? tb->tb_sb-> s_blocksize_bits - UNFM_P_SHIFT : 0))); |
| 1197 | ((old_len - | ||
| 1198 | sbytes[i]) << | ||
| 1199 | (is_indirect_le_ih | ||
| 1200 | (ih) ? tb->tb_sb-> | ||
| 1201 | s_blocksize_bits - | ||
| 1202 | UNFM_P_SHIFT : | ||
| 1203 | 0))); | ||
| 1204 | 838 | ||
| 1205 | put_ih_item_len(ih, sbytes[i]); | 839 | put_ih_item_len(ih, sbytes[i]); |
| 1206 | 840 | ||
| @@ -1209,39 +843,29 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h | |||
| 1209 | 843 | ||
| 1210 | if ((old_len - sbytes[i]) > zeros_num) { | 844 | if ((old_len - sbytes[i]) > zeros_num) { |
| 1211 | r_zeros_number = 0; | 845 | r_zeros_number = 0; |
| 1212 | r_body = | 846 | r_body = body + (old_len - sbytes[i]) - zeros_num; |
| 1213 | body + (old_len - | ||
| 1214 | sbytes[i]) - | ||
| 1215 | zeros_num; | ||
| 1216 | } else { | 847 | } else { |
| 1217 | r_body = body; | 848 | r_body = body; |
| 1218 | r_zeros_number = | 849 | r_zeros_number = zeros_num - (old_len - sbytes[i]); |
| 1219 | zeros_num - (old_len - | ||
| 1220 | sbytes[i]); | ||
| 1221 | zeros_num -= r_zeros_number; | 850 | zeros_num -= r_zeros_number; |
| 1222 | } | 851 | } |
| 1223 | 852 | ||
| 1224 | leaf_insert_into_buf(&bi, 0, ih, r_body, | 853 | leaf_insert_into_buf(&bi, 0, ih, r_body, r_zeros_number); |
| 1225 | r_zeros_number); | ||
| 1226 | 854 | ||
| 1227 | /* Calculate key component and item length to insert into S[i] */ | 855 | /* Calculate key component and item length to insert into S[i] */ |
| 1228 | set_le_ih_k_offset(ih, old_key_comp); | 856 | set_le_ih_k_offset(ih, old_key_comp); |
| 1229 | put_ih_item_len(ih, | 857 | put_ih_item_len(ih, old_len - sbytes[i]); |
| 1230 | old_len - sbytes[i]); | ||
| 1231 | tb->insert_size[0] -= sbytes[i]; | 858 | tb->insert_size[0] -= sbytes[i]; |
| 1232 | } else { /* whole new item falls into S_new[i] */ | 859 | } else { /* whole new item falls into S_new[i] */ |
| 1233 | 860 | ||
| 1234 | /* Shift snum[0] - 1 items to S_new[i] (sbytes[i] of split item) */ | 861 | /* Shift snum[0] - 1 items to S_new[i] (sbytes[i] of split item) */ |
| 1235 | leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, | 862 | leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, |
| 1236 | snum[i] - 1, sbytes[i], | 863 | snum[i] - 1, sbytes[i], S_new[i]); |
| 1237 | S_new[i]); | ||
| 1238 | 864 | ||
| 1239 | /* Insert new item into S_new[i] */ | 865 | /* Insert new item into S_new[i] */ |
| 1240 | buffer_info_init_bh(tb, &bi, S_new[i]); | 866 | buffer_info_init_bh(tb, &bi, S_new[i]); |
| 1241 | leaf_insert_into_buf(&bi, | 867 | leaf_insert_into_buf(&bi, item_pos - n + snum[i] - 1, |
| 1242 | item_pos - n + | 868 | ih, body, zeros_num); |
| 1243 | snum[i] - 1, ih, | ||
| 1244 | body, zeros_num); | ||
| 1245 | 869 | ||
| 1246 | zeros_num = tb->insert_size[0] = 0; | 870 | zeros_num = tb->insert_size[0] = 0; |
| 1247 | } | 871 | } |
| @@ -1268,150 +892,73 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h | |||
| 1268 | 892 | ||
| 1269 | int entry_count; | 893 | int entry_count; |
| 1270 | 894 | ||
| 1271 | entry_count = | 895 | entry_count = ih_entry_count(aux_ih); |
| 1272 | ih_entry_count(aux_ih); | ||
| 1273 | 896 | ||
| 1274 | if (entry_count - sbytes[i] < | 897 | if (entry_count - sbytes[i] < pos_in_item && pos_in_item <= entry_count) { |
| 1275 | pos_in_item | ||
| 1276 | && pos_in_item <= | ||
| 1277 | entry_count) { | ||
| 1278 | /* new directory entry falls into S_new[i] */ | 898 | /* new directory entry falls into S_new[i] */ |
| 1279 | 899 | ||
| 1280 | RFALSE(!tb-> | 900 | RFALSE(!tb->insert_size[0], "PAP-12215: insert_size is already 0"); |
| 1281 | insert_size[0], | 901 | RFALSE(sbytes[i] - 1 >= entry_count, |
| 1282 | "PAP-12215: insert_size is already 0"); | ||
| 1283 | RFALSE(sbytes[i] - 1 >= | ||
| 1284 | entry_count, | ||
| 1285 | "PAP-12220: there are no so much entries (%d), only %d", | 902 | "PAP-12220: there are no so much entries (%d), only %d", |
| 1286 | sbytes[i] - 1, | 903 | sbytes[i] - 1, entry_count); |
| 1287 | entry_count); | ||
| 1288 | 904 | ||
| 1289 | /* Shift snum[i]-1 items in whole. Shift sbytes[i] directory entries from directory item number snum[i] */ | 905 | /* Shift snum[i]-1 items in whole. Shift sbytes[i] directory entries from directory item number snum[i] */ |
| 1290 | leaf_move_items | 906 | leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, snum[i], sbytes[i] - 1, S_new[i]); |
| 1291 | (LEAF_FROM_S_TO_SNEW, | ||
| 1292 | tb, snum[i], | ||
| 1293 | sbytes[i] - 1, | ||
| 1294 | S_new[i]); | ||
| 1295 | /* Paste given directory entry to directory item */ | 907 | /* Paste given directory entry to directory item */ |
| 1296 | buffer_info_init_bh(tb, &bi, S_new[i]); | 908 | buffer_info_init_bh(tb, &bi, S_new[i]); |
| 1297 | leaf_paste_in_buffer | 909 | leaf_paste_in_buffer(&bi, 0, pos_in_item - entry_count + sbytes[i] - 1, |
| 1298 | (&bi, 0, | 910 | tb->insert_size[0], body, zeros_num); |
| 1299 | pos_in_item - | ||
| 1300 | entry_count + | ||
| 1301 | sbytes[i] - 1, | ||
| 1302 | tb->insert_size[0], | ||
| 1303 | body, zeros_num); | ||
| 1304 | /* paste new directory entry */ | 911 | /* paste new directory entry */ |
| 1305 | leaf_paste_entries(&bi, | 912 | leaf_paste_entries(&bi, 0, pos_in_item - entry_count + sbytes[i] - 1, 1, |
| 1306 | 0, | 913 | (struct reiserfs_de_head *) body, |
| 1307 | pos_in_item | 914 | body + DEH_SIZE, tb->insert_size[0]); |
| 1308 | - | ||
| 1309 | entry_count | ||
| 1310 | + | ||
| 1311 | sbytes | ||
| 1312 | [i] - | ||
| 1313 | 1, 1, | ||
| 1314 | (struct | ||
| 1315 | reiserfs_de_head | ||
| 1316 | *) | ||
| 1317 | body, | ||
| 1318 | body | ||
| 1319 | + | ||
| 1320 | DEH_SIZE, | ||
| 1321 | tb-> | ||
| 1322 | insert_size | ||
| 1323 | [0] | ||
| 1324 | ); | ||
| 1325 | tb->insert_size[0] = 0; | 915 | tb->insert_size[0] = 0; |
| 1326 | pos_in_item++; | 916 | pos_in_item++; |
| 1327 | } else { /* new directory entry doesn't fall into S_new[i] */ | 917 | } else { /* new directory entry doesn't fall into S_new[i] */ |
| 1328 | leaf_move_items | 918 | leaf_move_items(LEAF_FROM_S_TO_SNEW,tb, snum[i], sbytes[i], S_new[i]); |
| 1329 | (LEAF_FROM_S_TO_SNEW, | ||
| 1330 | tb, snum[i], | ||
| 1331 | sbytes[i], | ||
| 1332 | S_new[i]); | ||
| 1333 | } | 919 | } |
| 1334 | } else { /* regular object */ | 920 | } else { /* regular object */ |
| 1335 | 921 | ||
| 1336 | int n_shift, n_rem, | 922 | int n_shift, n_rem, r_zeros_number; |
| 1337 | r_zeros_number; | ||
| 1338 | const char *r_body; | 923 | const char *r_body; |
| 1339 | 924 | ||
| 1340 | RFALSE(pos_in_item != | 925 | RFALSE(pos_in_item != ih_item_len(B_N_PITEM_HEAD(tbS0, item_pos)) || tb->insert_size[0] <= 0, |
| 1341 | ih_item_len | ||
| 1342 | (B_N_PITEM_HEAD | ||
| 1343 | (tbS0, item_pos)) | ||
| 1344 | || tb->insert_size[0] <= | ||
| 1345 | 0, | ||
| 1346 | "PAP-12225: item too short or insert_size <= 0"); | 926 | "PAP-12225: item too short or insert_size <= 0"); |
| 1347 | 927 | ||
| 1348 | /* Calculate number of bytes which must be shifted from appended item */ | 928 | /* Calculate number of bytes which must be shifted from appended item */ |
| 1349 | n_shift = | 929 | n_shift = sbytes[i] - tb->insert_size[0]; |
| 1350 | sbytes[i] - | ||
| 1351 | tb->insert_size[0]; | ||
| 1352 | if (n_shift < 0) | 930 | if (n_shift < 0) |
| 1353 | n_shift = 0; | 931 | n_shift = 0; |
| 1354 | leaf_move_items | 932 | leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, snum[i], n_shift, S_new[i]); |
| 1355 | (LEAF_FROM_S_TO_SNEW, tb, | ||
| 1356 | snum[i], n_shift, | ||
| 1357 | S_new[i]); | ||
| 1358 | 933 | ||
| 1359 | /* Calculate number of bytes which must remain in body after append to S_new[i] */ | 934 | /* Calculate number of bytes which must remain in body after append to S_new[i] */ |
| 1360 | n_rem = | 935 | n_rem = tb->insert_size[0] - sbytes[i]; |
| 1361 | tb->insert_size[0] - | ||
| 1362 | sbytes[i]; | ||
| 1363 | if (n_rem < 0) | 936 | if (n_rem < 0) |
| 1364 | n_rem = 0; | 937 | n_rem = 0; |
| 1365 | /* Append part of body into S_new[0] */ | 938 | /* Append part of body into S_new[0] */ |
| 1366 | buffer_info_init_bh(tb, &bi, S_new[i]); | 939 | buffer_info_init_bh(tb, &bi, S_new[i]); |
| 1367 | if (n_rem > zeros_num) { | 940 | if (n_rem > zeros_num) { |
| 1368 | r_zeros_number = 0; | 941 | r_zeros_number = 0; |
| 1369 | r_body = | 942 | r_body = body + n_rem - zeros_num; |
| 1370 | body + n_rem - | ||
| 1371 | zeros_num; | ||
| 1372 | } else { | 943 | } else { |
| 1373 | r_body = body; | 944 | r_body = body; |
| 1374 | r_zeros_number = | 945 | r_zeros_number = zeros_num - n_rem; |
| 1375 | zeros_num - n_rem; | 946 | zeros_num -= r_zeros_number; |
| 1376 | zeros_num -= | ||
| 1377 | r_zeros_number; | ||
| 1378 | } | 947 | } |
| 1379 | 948 | ||
| 1380 | leaf_paste_in_buffer(&bi, 0, | 949 | leaf_paste_in_buffer(&bi, 0, n_shift, |
| 1381 | n_shift, | 950 | tb->insert_size[0] - n_rem, |
| 1382 | tb-> | 951 | r_body, r_zeros_number); |
| 1383 | insert_size | ||
| 1384 | [0] - | ||
| 1385 | n_rem, | ||
| 1386 | r_body, | ||
| 1387 | r_zeros_number); | ||
| 1388 | { | 952 | { |
| 1389 | struct item_head *tmp; | 953 | struct item_head *tmp; |
| 1390 | 954 | ||
| 1391 | tmp = | 955 | tmp = B_N_PITEM_HEAD(S_new[i], 0); |
| 1392 | B_N_PITEM_HEAD(S_new | ||
| 1393 | [i], | ||
| 1394 | 0); | ||
| 1395 | if (is_indirect_le_ih | 956 | if (is_indirect_le_ih |
| 1396 | (tmp)) { | 957 | (tmp)) { |
| 1397 | set_ih_free_space | 958 | set_ih_free_space(tmp, 0); |
| 1398 | (tmp, 0); | 959 | set_le_ih_k_offset(tmp, le_ih_k_offset(tmp) + (n_rem << (tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT))); |
| 1399 | set_le_ih_k_offset | ||
| 1400 | (tmp, | ||
| 1401 | le_ih_k_offset | ||
| 1402 | (tmp) + | ||
| 1403 | (n_rem << | ||
| 1404 | (tb-> | ||
| 1405 | tb_sb-> | ||
| 1406 | s_blocksize_bits | ||
| 1407 | - | ||
| 1408 | UNFM_P_SHIFT))); | ||
| 1409 | } else { | 960 | } else { |
| 1410 | set_le_ih_k_offset | 961 | set_le_ih_k_offset(tmp, le_ih_k_offset(tmp) + n_rem); |
| 1411 | (tmp, | ||
| 1412 | le_ih_k_offset | ||
| 1413 | (tmp) + | ||
| 1414 | n_rem); | ||
| 1415 | } | 962 | } |
| 1416 | } | 963 | } |
| 1417 | 964 | ||
| @@ -1426,8 +973,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h | |||
| 1426 | struct item_head *pasted; | 973 | struct item_head *pasted; |
| 1427 | 974 | ||
| 1428 | #ifdef CONFIG_REISERFS_CHECK | 975 | #ifdef CONFIG_REISERFS_CHECK |
| 1429 | struct item_head *ih_check = | 976 | struct item_head *ih_check = B_N_PITEM_HEAD(tbS0, item_pos); |
| 1430 | B_N_PITEM_HEAD(tbS0, item_pos); | ||
| 1431 | 977 | ||
| 1432 | if (!is_direntry_le_ih(ih_check) | 978 | if (!is_direntry_le_ih(ih_check) |
| 1433 | && (pos_in_item != ih_item_len(ih_check) | 979 | && (pos_in_item != ih_item_len(ih_check) |
| @@ -1439,8 +985,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h | |||
| 1439 | "to ih_item_len"); | 985 | "to ih_item_len"); |
| 1440 | #endif /* CONFIG_REISERFS_CHECK */ | 986 | #endif /* CONFIG_REISERFS_CHECK */ |
| 1441 | 987 | ||
| 1442 | leaf_mi = | 988 | leaf_mi = leaf_move_items(LEAF_FROM_S_TO_SNEW, |
| 1443 | leaf_move_items(LEAF_FROM_S_TO_SNEW, | ||
| 1444 | tb, snum[i], | 989 | tb, snum[i], |
| 1445 | sbytes[i], | 990 | sbytes[i], |
| 1446 | S_new[i]); | 991 | S_new[i]); |
| @@ -1452,30 +997,19 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h | |||
| 1452 | /* paste into item */ | 997 | /* paste into item */ |
| 1453 | buffer_info_init_bh(tb, &bi, S_new[i]); | 998 | buffer_info_init_bh(tb, &bi, S_new[i]); |
| 1454 | leaf_paste_in_buffer(&bi, | 999 | leaf_paste_in_buffer(&bi, |
| 1455 | item_pos - n + | 1000 | item_pos - n + snum[i], |
| 1456 | snum[i], | ||
| 1457 | pos_in_item, | 1001 | pos_in_item, |
| 1458 | tb->insert_size[0], | 1002 | tb->insert_size[0], |
| 1459 | body, zeros_num); | 1003 | body, zeros_num); |
| 1460 | 1004 | ||
| 1461 | pasted = | 1005 | pasted = B_N_PITEM_HEAD(S_new[i], item_pos - n + snum[i]); |
| 1462 | B_N_PITEM_HEAD(S_new[i], | ||
| 1463 | item_pos - n + | ||
| 1464 | snum[i]); | ||
| 1465 | if (is_direntry_le_ih(pasted)) { | 1006 | if (is_direntry_le_ih(pasted)) { |
| 1466 | leaf_paste_entries(&bi, | 1007 | leaf_paste_entries(&bi, |
| 1467 | item_pos - | 1008 | item_pos - n + snum[i], |
| 1468 | n + snum[i], | 1009 | pos_in_item, 1, |
| 1469 | pos_in_item, | 1010 | (struct reiserfs_de_head *)body, |
| 1470 | 1, | 1011 | body + DEH_SIZE, |
| 1471 | (struct | 1012 | tb->insert_size[0] |
| 1472 | reiserfs_de_head | ||
| 1473 | *)body, | ||
| 1474 | body + | ||
| 1475 | DEH_SIZE, | ||
| 1476 | tb-> | ||
| 1477 | insert_size | ||
| 1478 | [0] | ||
| 1479 | ); | 1013 | ); |
| 1480 | } | 1014 | } |
| 1481 | 1015 | ||
| @@ -1495,11 +1029,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h | |||
| 1495 | default: /* cases d and t */ | 1029 | default: /* cases d and t */ |
| 1496 | reiserfs_panic(tb->tb_sb, "PAP-12245", | 1030 | reiserfs_panic(tb->tb_sb, "PAP-12245", |
| 1497 | "blknum > 2: unexpected mode: %s(%d)", | 1031 | "blknum > 2: unexpected mode: %s(%d)", |
| 1498 | (flag == | 1032 | (flag == M_DELETE) ? "DELETE" : ((flag == M_CUT) ? "CUT" : "UNKNOWN"), flag); |
| 1499 | M_DELETE) ? "DELETE" : ((flag == | ||
| 1500 | M_CUT) ? "CUT" | ||
| 1501 | : "UNKNOWN"), | ||
| 1502 | flag); | ||
| 1503 | } | 1033 | } |
| 1504 | 1034 | ||
| 1505 | memcpy(insert_key + i, B_N_PKEY(S_new[i], 0), KEY_SIZE); | 1035 | memcpy(insert_key + i, B_N_PKEY(S_new[i], 0), KEY_SIZE); |
| @@ -1524,9 +1054,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h | |||
| 1524 | /* If we insert the first key change the delimiting key */ | 1054 | /* If we insert the first key change the delimiting key */ |
| 1525 | if (item_pos == 0) { | 1055 | if (item_pos == 0) { |
| 1526 | if (tb->CFL[0]) /* can be 0 in reiserfsck */ | 1056 | if (tb->CFL[0]) /* can be 0 in reiserfsck */ |
| 1527 | replace_key(tb, tb->CFL[0], tb->lkey[0], | 1057 | replace_key(tb, tb->CFL[0], tb->lkey[0], tbS0, 0); |
| 1528 | tbS0, 0); | ||
| 1529 | |||
| 1530 | } | 1058 | } |
| 1531 | break; | 1059 | break; |
| 1532 | 1060 | ||
| @@ -1536,53 +1064,27 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h | |||
| 1536 | pasted = B_N_PITEM_HEAD(tbS0, item_pos); | 1064 | pasted = B_N_PITEM_HEAD(tbS0, item_pos); |
| 1537 | /* when directory, may be new entry already pasted */ | 1065 | /* when directory, may be new entry already pasted */ |
| 1538 | if (is_direntry_le_ih(pasted)) { | 1066 | if (is_direntry_le_ih(pasted)) { |
| 1539 | if (pos_in_item >= 0 && | 1067 | if (pos_in_item >= 0 && pos_in_item <= ih_entry_count(pasted)) { |
| 1540 | pos_in_item <= | ||
| 1541 | ih_entry_count(pasted)) { | ||
| 1542 | 1068 | ||
| 1543 | RFALSE(!tb->insert_size[0], | 1069 | RFALSE(!tb->insert_size[0], |
| 1544 | "PAP-12260: insert_size is 0 already"); | 1070 | "PAP-12260: insert_size is 0 already"); |
| 1545 | 1071 | ||
| 1546 | /* prepare space */ | 1072 | /* prepare space */ |
| 1547 | buffer_info_init_tbS0(tb, &bi); | 1073 | buffer_info_init_tbS0(tb, &bi); |
| 1548 | leaf_paste_in_buffer(&bi, | 1074 | leaf_paste_in_buffer(&bi, item_pos, pos_in_item, |
| 1549 | item_pos, | 1075 | tb->insert_size[0], body, |
| 1550 | pos_in_item, | ||
| 1551 | tb-> | ||
| 1552 | insert_size | ||
| 1553 | [0], body, | ||
| 1554 | zeros_num); | 1076 | zeros_num); |
| 1555 | 1077 | ||
| 1556 | /* paste entry */ | 1078 | /* paste entry */ |
| 1557 | leaf_paste_entries(&bi, | 1079 | leaf_paste_entries(&bi, item_pos, pos_in_item, 1, |
| 1558 | item_pos, | 1080 | (struct reiserfs_de_head *)body, |
| 1559 | pos_in_item, | 1081 | body + DEH_SIZE, |
| 1560 | 1, | 1082 | tb->insert_size[0]); |
| 1561 | (struct | ||
| 1562 | reiserfs_de_head | ||
| 1563 | *)body, | ||
| 1564 | body + | ||
| 1565 | DEH_SIZE, | ||
| 1566 | tb-> | ||
| 1567 | insert_size | ||
| 1568 | [0] | ||
| 1569 | ); | ||
| 1570 | if (!item_pos && !pos_in_item) { | 1083 | if (!item_pos && !pos_in_item) { |
| 1571 | RFALSE(!tb->CFL[0] | 1084 | RFALSE(!tb->CFL[0] || !tb->L[0], |
| 1572 | || !tb->L[0], | ||
| 1573 | "PAP-12270: CFL[0]/L[0] must be specified"); | 1085 | "PAP-12270: CFL[0]/L[0] must be specified"); |
| 1574 | if (tb->CFL[0]) { | 1086 | if (tb->CFL[0]) |
| 1575 | replace_key(tb, | 1087 | replace_key(tb, tb->CFL[0], tb->lkey[0], tbS0, 0); |
| 1576 | tb-> | ||
| 1577 | CFL | ||
| 1578 | [0], | ||
| 1579 | tb-> | ||
| 1580 | lkey | ||
| 1581 | [0], | ||
| 1582 | tbS0, | ||
| 1583 | 0); | ||
| 1584 | |||
| 1585 | } | ||
| 1586 | } | 1088 | } |
| 1587 | tb->insert_size[0] = 0; | 1089 | tb->insert_size[0] = 0; |
| 1588 | } | 1090 | } |
| @@ -1593,13 +1095,8 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h | |||
| 1593 | "PAP-12275: insert size must not be %d", | 1095 | "PAP-12275: insert size must not be %d", |
| 1594 | tb->insert_size[0]); | 1096 | tb->insert_size[0]); |
| 1595 | buffer_info_init_tbS0(tb, &bi); | 1097 | buffer_info_init_tbS0(tb, &bi); |
| 1596 | leaf_paste_in_buffer(&bi, | 1098 | leaf_paste_in_buffer(&bi, item_pos, pos_in_item, |
| 1597 | item_pos, | 1099 | tb->insert_size[0], body, zeros_num); |
| 1598 | pos_in_item, | ||
| 1599 | tb-> | ||
| 1600 | insert_size | ||
| 1601 | [0], body, | ||
| 1602 | zeros_num); | ||
| 1603 | 1100 | ||
| 1604 | if (is_indirect_le_ih(pasted)) { | 1101 | if (is_indirect_le_ih(pasted)) { |
| 1605 | #if 0 | 1102 | #if 0 |
| @@ -1611,8 +1108,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h | |||
| 1611 | tb-> | 1108 | tb-> |
| 1612 | insert_size[0]); | 1109 | insert_size[0]); |
| 1613 | #endif | 1110 | #endif |
| 1614 | set_ih_free_space | 1111 | set_ih_free_space(pasted, 0); |
| 1615 | (pasted, 0); | ||
| 1616 | } | 1112 | } |
| 1617 | tb->insert_size[0] = 0; | 1113 | tb->insert_size[0] = 0; |
| 1618 | } | 1114 | } |
| @@ -1620,8 +1116,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h | |||
| 1620 | else { | 1116 | else { |
| 1621 | if (tb->insert_size[0]) { | 1117 | if (tb->insert_size[0]) { |
| 1622 | print_cur_tb("12285"); | 1118 | print_cur_tb("12285"); |
| 1623 | reiserfs_panic(tb-> | 1119 | reiserfs_panic(tb->tb_sb, |
| 1624 | tb_sb, | ||
| 1625 | "PAP-12285", | 1120 | "PAP-12285", |
| 1626 | "insert_size " | 1121 | "insert_size " |
| 1627 | "must be 0 " | 1122 | "must be 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 | } |
