diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-12-22 17:46:24 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-12-22 17:46:24 -0500 |
commit | 25cf0398bdf365d027e171116aa4a281e9cd3c1c (patch) | |
tree | a8be3d3d314625a376be0e62c67809dc22274dd4 /fs | |
parent | 9326845f45650f6af9953a4b6a31e89b54fab82f (diff) | |
parent | 59bdd133561a432c4655146e283caf85fa64c2fb (diff) |
Merge branch 'devel' of git://git.kernel.org/pub/scm/linux/kernel/git/ycmiao/pxa-linux-2.6 into devel-stable
Diffstat (limited to 'fs')
68 files changed, 1016 insertions, 582 deletions
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index d5c1401f0031..d34896cfb19f 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c | |||
@@ -980,19 +980,11 @@ static int autofs4_root_ioctl_unlocked(struct inode *inode, struct file *filp, | |||
980 | } | 980 | } |
981 | } | 981 | } |
982 | 982 | ||
983 | static DEFINE_MUTEX(autofs4_ioctl_mutex); | ||
984 | |||
985 | static long autofs4_root_ioctl(struct file *filp, | 983 | static long autofs4_root_ioctl(struct file *filp, |
986 | unsigned int cmd, unsigned long arg) | 984 | unsigned int cmd, unsigned long arg) |
987 | { | 985 | { |
988 | long ret; | ||
989 | struct inode *inode = filp->f_dentry->d_inode; | 986 | struct inode *inode = filp->f_dentry->d_inode; |
990 | 987 | return autofs4_root_ioctl_unlocked(inode, filp, cmd, arg); | |
991 | mutex_lock(&autofs4_ioctl_mutex); | ||
992 | ret = autofs4_root_ioctl_unlocked(inode, filp, cmd, arg); | ||
993 | mutex_unlock(&autofs4_ioctl_mutex); | ||
994 | |||
995 | return ret; | ||
996 | } | 988 | } |
997 | 989 | ||
998 | #ifdef CONFIG_COMPAT | 990 | #ifdef CONFIG_COMPAT |
@@ -1002,13 +994,11 @@ static long autofs4_root_compat_ioctl(struct file *filp, | |||
1002 | struct inode *inode = filp->f_path.dentry->d_inode; | 994 | struct inode *inode = filp->f_path.dentry->d_inode; |
1003 | int ret; | 995 | int ret; |
1004 | 996 | ||
1005 | mutex_lock(&autofs4_ioctl_mutex); | ||
1006 | if (cmd == AUTOFS_IOC_READY || cmd == AUTOFS_IOC_FAIL) | 997 | if (cmd == AUTOFS_IOC_READY || cmd == AUTOFS_IOC_FAIL) |
1007 | ret = autofs4_root_ioctl_unlocked(inode, filp, cmd, arg); | 998 | ret = autofs4_root_ioctl_unlocked(inode, filp, cmd, arg); |
1008 | else | 999 | else |
1009 | ret = autofs4_root_ioctl_unlocked(inode, filp, cmd, | 1000 | ret = autofs4_root_ioctl_unlocked(inode, filp, cmd, |
1010 | (unsigned long)compat_ptr(arg)); | 1001 | (unsigned long)compat_ptr(arg)); |
1011 | mutex_unlock(&autofs4_ioctl_mutex); | ||
1012 | 1002 | ||
1013 | return ret; | 1003 | return ret; |
1014 | } | 1004 | } |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index c547cca26a26..51d2e4de34eb 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -696,6 +696,7 @@ static int btree_submit_bio_hook(struct inode *inode, int rw, struct bio *bio, | |||
696 | __btree_submit_bio_done); | 696 | __btree_submit_bio_done); |
697 | } | 697 | } |
698 | 698 | ||
699 | #ifdef CONFIG_MIGRATION | ||
699 | static int btree_migratepage(struct address_space *mapping, | 700 | static int btree_migratepage(struct address_space *mapping, |
700 | struct page *newpage, struct page *page) | 701 | struct page *newpage, struct page *page) |
701 | { | 702 | { |
@@ -712,12 +713,9 @@ static int btree_migratepage(struct address_space *mapping, | |||
712 | if (page_has_private(page) && | 713 | if (page_has_private(page) && |
713 | !try_to_release_page(page, GFP_KERNEL)) | 714 | !try_to_release_page(page, GFP_KERNEL)) |
714 | return -EAGAIN; | 715 | return -EAGAIN; |
715 | #ifdef CONFIG_MIGRATION | ||
716 | return migrate_page(mapping, newpage, page); | 716 | return migrate_page(mapping, newpage, page); |
717 | #else | ||
718 | return -ENOSYS; | ||
719 | #endif | ||
720 | } | 717 | } |
718 | #endif | ||
721 | 719 | ||
722 | static int btree_writepage(struct page *page, struct writeback_control *wbc) | 720 | static int btree_writepage(struct page *page, struct writeback_control *wbc) |
723 | { | 721 | { |
@@ -1009,7 +1007,10 @@ static int find_and_setup_root(struct btrfs_root *tree_root, | |||
1009 | blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item)); | 1007 | blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item)); |
1010 | root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item), | 1008 | root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item), |
1011 | blocksize, generation); | 1009 | blocksize, generation); |
1012 | BUG_ON(!root->node); | 1010 | if (!root->node || !btrfs_buffer_uptodate(root->node, generation)) { |
1011 | free_extent_buffer(root->node); | ||
1012 | return -EIO; | ||
1013 | } | ||
1013 | root->commit_root = btrfs_root_node(root); | 1014 | root->commit_root = btrfs_root_node(root); |
1014 | return 0; | 1015 | return 0; |
1015 | } | 1016 | } |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index bcd59c7dfb57..227e5815d838 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -429,6 +429,7 @@ err: | |||
429 | 429 | ||
430 | static int cache_block_group(struct btrfs_block_group_cache *cache, | 430 | static int cache_block_group(struct btrfs_block_group_cache *cache, |
431 | struct btrfs_trans_handle *trans, | 431 | struct btrfs_trans_handle *trans, |
432 | struct btrfs_root *root, | ||
432 | int load_cache_only) | 433 | int load_cache_only) |
433 | { | 434 | { |
434 | struct btrfs_fs_info *fs_info = cache->fs_info; | 435 | struct btrfs_fs_info *fs_info = cache->fs_info; |
@@ -442,9 +443,12 @@ static int cache_block_group(struct btrfs_block_group_cache *cache, | |||
442 | 443 | ||
443 | /* | 444 | /* |
444 | * We can't do the read from on-disk cache during a commit since we need | 445 | * We can't do the read from on-disk cache during a commit since we need |
445 | * to have the normal tree locking. | 446 | * to have the normal tree locking. Also if we are currently trying to |
447 | * allocate blocks for the tree root we can't do the fast caching since | ||
448 | * we likely hold important locks. | ||
446 | */ | 449 | */ |
447 | if (!trans->transaction->in_commit) { | 450 | if (!trans->transaction->in_commit && |
451 | (root && root != root->fs_info->tree_root)) { | ||
448 | spin_lock(&cache->lock); | 452 | spin_lock(&cache->lock); |
449 | if (cache->cached != BTRFS_CACHE_NO) { | 453 | if (cache->cached != BTRFS_CACHE_NO) { |
450 | spin_unlock(&cache->lock); | 454 | spin_unlock(&cache->lock); |
@@ -2741,6 +2745,7 @@ static int cache_save_setup(struct btrfs_block_group_cache *block_group, | |||
2741 | struct btrfs_root *root = block_group->fs_info->tree_root; | 2745 | struct btrfs_root *root = block_group->fs_info->tree_root; |
2742 | struct inode *inode = NULL; | 2746 | struct inode *inode = NULL; |
2743 | u64 alloc_hint = 0; | 2747 | u64 alloc_hint = 0; |
2748 | int dcs = BTRFS_DC_ERROR; | ||
2744 | int num_pages = 0; | 2749 | int num_pages = 0; |
2745 | int retries = 0; | 2750 | int retries = 0; |
2746 | int ret = 0; | 2751 | int ret = 0; |
@@ -2795,6 +2800,8 @@ again: | |||
2795 | 2800 | ||
2796 | spin_lock(&block_group->lock); | 2801 | spin_lock(&block_group->lock); |
2797 | if (block_group->cached != BTRFS_CACHE_FINISHED) { | 2802 | if (block_group->cached != BTRFS_CACHE_FINISHED) { |
2803 | /* We're not cached, don't bother trying to write stuff out */ | ||
2804 | dcs = BTRFS_DC_WRITTEN; | ||
2798 | spin_unlock(&block_group->lock); | 2805 | spin_unlock(&block_group->lock); |
2799 | goto out_put; | 2806 | goto out_put; |
2800 | } | 2807 | } |
@@ -2821,6 +2828,8 @@ again: | |||
2821 | ret = btrfs_prealloc_file_range_trans(inode, trans, 0, 0, num_pages, | 2828 | ret = btrfs_prealloc_file_range_trans(inode, trans, 0, 0, num_pages, |
2822 | num_pages, num_pages, | 2829 | num_pages, num_pages, |
2823 | &alloc_hint); | 2830 | &alloc_hint); |
2831 | if (!ret) | ||
2832 | dcs = BTRFS_DC_SETUP; | ||
2824 | btrfs_free_reserved_data_space(inode, num_pages); | 2833 | btrfs_free_reserved_data_space(inode, num_pages); |
2825 | out_put: | 2834 | out_put: |
2826 | iput(inode); | 2835 | iput(inode); |
@@ -2828,10 +2837,7 @@ out_free: | |||
2828 | btrfs_release_path(root, path); | 2837 | btrfs_release_path(root, path); |
2829 | out: | 2838 | out: |
2830 | spin_lock(&block_group->lock); | 2839 | spin_lock(&block_group->lock); |
2831 | if (ret) | 2840 | block_group->disk_cache_state = dcs; |
2832 | block_group->disk_cache_state = BTRFS_DC_ERROR; | ||
2833 | else | ||
2834 | block_group->disk_cache_state = BTRFS_DC_SETUP; | ||
2835 | spin_unlock(&block_group->lock); | 2841 | spin_unlock(&block_group->lock); |
2836 | 2842 | ||
2837 | return ret; | 2843 | return ret; |
@@ -3037,7 +3043,13 @@ static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags) | |||
3037 | 3043 | ||
3038 | u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags) | 3044 | u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags) |
3039 | { | 3045 | { |
3040 | u64 num_devices = root->fs_info->fs_devices->rw_devices; | 3046 | /* |
3047 | * we add in the count of missing devices because we want | ||
3048 | * to make sure that any RAID levels on a degraded FS | ||
3049 | * continue to be honored. | ||
3050 | */ | ||
3051 | u64 num_devices = root->fs_info->fs_devices->rw_devices + | ||
3052 | root->fs_info->fs_devices->missing_devices; | ||
3041 | 3053 | ||
3042 | if (num_devices == 1) | 3054 | if (num_devices == 1) |
3043 | flags &= ~(BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID0); | 3055 | flags &= ~(BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID0); |
@@ -4080,7 +4092,7 @@ static int update_block_group(struct btrfs_trans_handle *trans, | |||
4080 | * space back to the block group, otherwise we will leak space. | 4092 | * space back to the block group, otherwise we will leak space. |
4081 | */ | 4093 | */ |
4082 | if (!alloc && cache->cached == BTRFS_CACHE_NO) | 4094 | if (!alloc && cache->cached == BTRFS_CACHE_NO) |
4083 | cache_block_group(cache, trans, 1); | 4095 | cache_block_group(cache, trans, NULL, 1); |
4084 | 4096 | ||
4085 | byte_in_group = bytenr - cache->key.objectid; | 4097 | byte_in_group = bytenr - cache->key.objectid; |
4086 | WARN_ON(byte_in_group > cache->key.offset); | 4098 | WARN_ON(byte_in_group > cache->key.offset); |
@@ -4930,11 +4942,31 @@ search: | |||
4930 | btrfs_get_block_group(block_group); | 4942 | btrfs_get_block_group(block_group); |
4931 | search_start = block_group->key.objectid; | 4943 | search_start = block_group->key.objectid; |
4932 | 4944 | ||
4945 | /* | ||
4946 | * this can happen if we end up cycling through all the | ||
4947 | * raid types, but we want to make sure we only allocate | ||
4948 | * for the proper type. | ||
4949 | */ | ||
4950 | if (!block_group_bits(block_group, data)) { | ||
4951 | u64 extra = BTRFS_BLOCK_GROUP_DUP | | ||
4952 | BTRFS_BLOCK_GROUP_RAID1 | | ||
4953 | BTRFS_BLOCK_GROUP_RAID10; | ||
4954 | |||
4955 | /* | ||
4956 | * if they asked for extra copies and this block group | ||
4957 | * doesn't provide them, bail. This does allow us to | ||
4958 | * fill raid0 from raid1. | ||
4959 | */ | ||
4960 | if ((data & extra) && !(block_group->flags & extra)) | ||
4961 | goto loop; | ||
4962 | } | ||
4963 | |||
4933 | have_block_group: | 4964 | have_block_group: |
4934 | if (unlikely(block_group->cached == BTRFS_CACHE_NO)) { | 4965 | if (unlikely(block_group->cached == BTRFS_CACHE_NO)) { |
4935 | u64 free_percent; | 4966 | u64 free_percent; |
4936 | 4967 | ||
4937 | ret = cache_block_group(block_group, trans, 1); | 4968 | ret = cache_block_group(block_group, trans, |
4969 | orig_root, 1); | ||
4938 | if (block_group->cached == BTRFS_CACHE_FINISHED) | 4970 | if (block_group->cached == BTRFS_CACHE_FINISHED) |
4939 | goto have_block_group; | 4971 | goto have_block_group; |
4940 | 4972 | ||
@@ -4958,7 +4990,8 @@ have_block_group: | |||
4958 | if (loop > LOOP_CACHING_NOWAIT || | 4990 | if (loop > LOOP_CACHING_NOWAIT || |
4959 | (loop > LOOP_FIND_IDEAL && | 4991 | (loop > LOOP_FIND_IDEAL && |
4960 | atomic_read(&space_info->caching_threads) < 2)) { | 4992 | atomic_read(&space_info->caching_threads) < 2)) { |
4961 | ret = cache_block_group(block_group, trans, 0); | 4993 | ret = cache_block_group(block_group, trans, |
4994 | orig_root, 0); | ||
4962 | BUG_ON(ret); | 4995 | BUG_ON(ret); |
4963 | } | 4996 | } |
4964 | found_uncached_bg = true; | 4997 | found_uncached_bg = true; |
@@ -5515,7 +5548,7 @@ int btrfs_alloc_logged_file_extent(struct btrfs_trans_handle *trans, | |||
5515 | u64 num_bytes = ins->offset; | 5548 | u64 num_bytes = ins->offset; |
5516 | 5549 | ||
5517 | block_group = btrfs_lookup_block_group(root->fs_info, ins->objectid); | 5550 | block_group = btrfs_lookup_block_group(root->fs_info, ins->objectid); |
5518 | cache_block_group(block_group, trans, 0); | 5551 | cache_block_group(block_group, trans, NULL, 0); |
5519 | caching_ctl = get_caching_control(block_group); | 5552 | caching_ctl = get_caching_control(block_group); |
5520 | 5553 | ||
5521 | if (!caching_ctl) { | 5554 | if (!caching_ctl) { |
@@ -6300,9 +6333,13 @@ int btrfs_drop_snapshot(struct btrfs_root *root, | |||
6300 | NULL, NULL); | 6333 | NULL, NULL); |
6301 | BUG_ON(ret < 0); | 6334 | BUG_ON(ret < 0); |
6302 | if (ret > 0) { | 6335 | if (ret > 0) { |
6303 | ret = btrfs_del_orphan_item(trans, tree_root, | 6336 | /* if we fail to delete the orphan item this time |
6304 | root->root_key.objectid); | 6337 | * around, it'll get picked up the next time. |
6305 | BUG_ON(ret); | 6338 | * |
6339 | * The most common failure here is just -ENOENT. | ||
6340 | */ | ||
6341 | btrfs_del_orphan_item(trans, tree_root, | ||
6342 | root->root_key.objectid); | ||
6306 | } | 6343 | } |
6307 | } | 6344 | } |
6308 | 6345 | ||
@@ -7878,7 +7915,14 @@ static u64 update_block_group_flags(struct btrfs_root *root, u64 flags) | |||
7878 | u64 stripped = BTRFS_BLOCK_GROUP_RAID0 | | 7915 | u64 stripped = BTRFS_BLOCK_GROUP_RAID0 | |
7879 | BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID10; | 7916 | BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID10; |
7880 | 7917 | ||
7881 | num_devices = root->fs_info->fs_devices->rw_devices; | 7918 | /* |
7919 | * we add in the count of missing devices because we want | ||
7920 | * to make sure that any RAID levels on a degraded FS | ||
7921 | * continue to be honored. | ||
7922 | */ | ||
7923 | num_devices = root->fs_info->fs_devices->rw_devices + | ||
7924 | root->fs_info->fs_devices->missing_devices; | ||
7925 | |||
7882 | if (num_devices == 1) { | 7926 | if (num_devices == 1) { |
7883 | stripped |= BTRFS_BLOCK_GROUP_DUP; | 7927 | stripped |= BTRFS_BLOCK_GROUP_DUP; |
7884 | stripped = flags & ~stripped; | 7928 | stripped = flags & ~stripped; |
@@ -8247,7 +8291,6 @@ int btrfs_read_block_groups(struct btrfs_root *root) | |||
8247 | break; | 8291 | break; |
8248 | if (ret != 0) | 8292 | if (ret != 0) |
8249 | goto error; | 8293 | goto error; |
8250 | |||
8251 | leaf = path->nodes[0]; | 8294 | leaf = path->nodes[0]; |
8252 | btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); | 8295 | btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); |
8253 | cache = kzalloc(sizeof(*cache), GFP_NOFS); | 8296 | cache = kzalloc(sizeof(*cache), GFP_NOFS); |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index c1faded5fca0..66836d85763b 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -48,30 +48,34 @@ static noinline int btrfs_copy_from_user(loff_t pos, int num_pages, | |||
48 | struct page **prepared_pages, | 48 | struct page **prepared_pages, |
49 | struct iov_iter *i) | 49 | struct iov_iter *i) |
50 | { | 50 | { |
51 | size_t copied; | 51 | size_t copied = 0; |
52 | int pg = 0; | 52 | int pg = 0; |
53 | int offset = pos & (PAGE_CACHE_SIZE - 1); | 53 | int offset = pos & (PAGE_CACHE_SIZE - 1); |
54 | int total_copied = 0; | ||
54 | 55 | ||
55 | while (write_bytes > 0) { | 56 | while (write_bytes > 0) { |
56 | size_t count = min_t(size_t, | 57 | size_t count = min_t(size_t, |
57 | PAGE_CACHE_SIZE - offset, write_bytes); | 58 | PAGE_CACHE_SIZE - offset, write_bytes); |
58 | struct page *page = prepared_pages[pg]; | 59 | struct page *page = prepared_pages[pg]; |
59 | again: | 60 | /* |
60 | if (unlikely(iov_iter_fault_in_readable(i, count))) | 61 | * Copy data from userspace to the current page |
61 | return -EFAULT; | 62 | * |
62 | 63 | * Disable pagefault to avoid recursive lock since | |
63 | /* Copy data from userspace to the current page */ | 64 | * the pages are already locked |
64 | copied = iov_iter_copy_from_user(page, i, offset, count); | 65 | */ |
66 | pagefault_disable(); | ||
67 | copied = iov_iter_copy_from_user_atomic(page, i, offset, count); | ||
68 | pagefault_enable(); | ||
65 | 69 | ||
66 | /* Flush processor's dcache for this page */ | 70 | /* Flush processor's dcache for this page */ |
67 | flush_dcache_page(page); | 71 | flush_dcache_page(page); |
68 | iov_iter_advance(i, copied); | 72 | iov_iter_advance(i, copied); |
69 | write_bytes -= copied; | 73 | write_bytes -= copied; |
74 | total_copied += copied; | ||
70 | 75 | ||
76 | /* Return to btrfs_file_aio_write to fault page */ | ||
71 | if (unlikely(copied == 0)) { | 77 | if (unlikely(copied == 0)) { |
72 | count = min_t(size_t, PAGE_CACHE_SIZE - offset, | 78 | break; |
73 | iov_iter_single_seg_count(i)); | ||
74 | goto again; | ||
75 | } | 79 | } |
76 | 80 | ||
77 | if (unlikely(copied < PAGE_CACHE_SIZE - offset)) { | 81 | if (unlikely(copied < PAGE_CACHE_SIZE - offset)) { |
@@ -81,7 +85,7 @@ again: | |||
81 | offset = 0; | 85 | offset = 0; |
82 | } | 86 | } |
83 | } | 87 | } |
84 | return 0; | 88 | return total_copied; |
85 | } | 89 | } |
86 | 90 | ||
87 | /* | 91 | /* |
@@ -854,6 +858,8 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | |||
854 | unsigned long last_index; | 858 | unsigned long last_index; |
855 | int will_write; | 859 | int will_write; |
856 | int buffered = 0; | 860 | int buffered = 0; |
861 | int copied = 0; | ||
862 | int dirty_pages = 0; | ||
857 | 863 | ||
858 | will_write = ((file->f_flags & O_DSYNC) || IS_SYNC(inode) || | 864 | will_write = ((file->f_flags & O_DSYNC) || IS_SYNC(inode) || |
859 | (file->f_flags & O_DIRECT)); | 865 | (file->f_flags & O_DIRECT)); |
@@ -970,7 +976,17 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | |||
970 | WARN_ON(num_pages > nrptrs); | 976 | WARN_ON(num_pages > nrptrs); |
971 | memset(pages, 0, sizeof(struct page *) * nrptrs); | 977 | memset(pages, 0, sizeof(struct page *) * nrptrs); |
972 | 978 | ||
973 | ret = btrfs_delalloc_reserve_space(inode, write_bytes); | 979 | /* |
980 | * Fault pages before locking them in prepare_pages | ||
981 | * to avoid recursive lock | ||
982 | */ | ||
983 | if (unlikely(iov_iter_fault_in_readable(&i, write_bytes))) { | ||
984 | ret = -EFAULT; | ||
985 | goto out; | ||
986 | } | ||
987 | |||
988 | ret = btrfs_delalloc_reserve_space(inode, | ||
989 | num_pages << PAGE_CACHE_SHIFT); | ||
974 | if (ret) | 990 | if (ret) |
975 | goto out; | 991 | goto out; |
976 | 992 | ||
@@ -978,37 +994,49 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | |||
978 | pos, first_index, last_index, | 994 | pos, first_index, last_index, |
979 | write_bytes); | 995 | write_bytes); |
980 | if (ret) { | 996 | if (ret) { |
981 | btrfs_delalloc_release_space(inode, write_bytes); | 997 | btrfs_delalloc_release_space(inode, |
998 | num_pages << PAGE_CACHE_SHIFT); | ||
982 | goto out; | 999 | goto out; |
983 | } | 1000 | } |
984 | 1001 | ||
985 | ret = btrfs_copy_from_user(pos, num_pages, | 1002 | copied = btrfs_copy_from_user(pos, num_pages, |
986 | write_bytes, pages, &i); | 1003 | write_bytes, pages, &i); |
987 | if (ret == 0) { | 1004 | dirty_pages = (copied + PAGE_CACHE_SIZE - 1) >> |
1005 | PAGE_CACHE_SHIFT; | ||
1006 | |||
1007 | if (num_pages > dirty_pages) { | ||
1008 | if (copied > 0) | ||
1009 | atomic_inc( | ||
1010 | &BTRFS_I(inode)->outstanding_extents); | ||
1011 | btrfs_delalloc_release_space(inode, | ||
1012 | (num_pages - dirty_pages) << | ||
1013 | PAGE_CACHE_SHIFT); | ||
1014 | } | ||
1015 | |||
1016 | if (copied > 0) { | ||
988 | dirty_and_release_pages(NULL, root, file, pages, | 1017 | dirty_and_release_pages(NULL, root, file, pages, |
989 | num_pages, pos, write_bytes); | 1018 | dirty_pages, pos, copied); |
990 | } | 1019 | } |
991 | 1020 | ||
992 | btrfs_drop_pages(pages, num_pages); | 1021 | btrfs_drop_pages(pages, num_pages); |
993 | if (ret) { | ||
994 | btrfs_delalloc_release_space(inode, write_bytes); | ||
995 | goto out; | ||
996 | } | ||
997 | 1022 | ||
998 | if (will_write) { | 1023 | if (copied > 0) { |
999 | filemap_fdatawrite_range(inode->i_mapping, pos, | 1024 | if (will_write) { |
1000 | pos + write_bytes - 1); | 1025 | filemap_fdatawrite_range(inode->i_mapping, pos, |
1001 | } else { | 1026 | pos + copied - 1); |
1002 | balance_dirty_pages_ratelimited_nr(inode->i_mapping, | 1027 | } else { |
1003 | num_pages); | 1028 | balance_dirty_pages_ratelimited_nr( |
1004 | if (num_pages < | 1029 | inode->i_mapping, |
1005 | (root->leafsize >> PAGE_CACHE_SHIFT) + 1) | 1030 | dirty_pages); |
1006 | btrfs_btree_balance_dirty(root, 1); | 1031 | if (dirty_pages < |
1007 | btrfs_throttle(root); | 1032 | (root->leafsize >> PAGE_CACHE_SHIFT) + 1) |
1033 | btrfs_btree_balance_dirty(root, 1); | ||
1034 | btrfs_throttle(root); | ||
1035 | } | ||
1008 | } | 1036 | } |
1009 | 1037 | ||
1010 | pos += write_bytes; | 1038 | pos += copied; |
1011 | num_written += write_bytes; | 1039 | num_written += copied; |
1012 | 1040 | ||
1013 | cond_resched(); | 1041 | cond_resched(); |
1014 | } | 1042 | } |
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 22ee0dc2e6b8..60d684266959 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c | |||
@@ -290,7 +290,7 @@ int load_free_space_cache(struct btrfs_fs_info *fs_info, | |||
290 | (unsigned long long)BTRFS_I(inode)->generation, | 290 | (unsigned long long)BTRFS_I(inode)->generation, |
291 | (unsigned long long)generation, | 291 | (unsigned long long)generation, |
292 | (unsigned long long)block_group->key.objectid); | 292 | (unsigned long long)block_group->key.objectid); |
293 | goto out; | 293 | goto free_cache; |
294 | } | 294 | } |
295 | 295 | ||
296 | if (!num_entries) | 296 | if (!num_entries) |
@@ -524,6 +524,12 @@ int btrfs_write_out_cache(struct btrfs_root *root, | |||
524 | return 0; | 524 | return 0; |
525 | } | 525 | } |
526 | 526 | ||
527 | node = rb_first(&block_group->free_space_offset); | ||
528 | if (!node) { | ||
529 | iput(inode); | ||
530 | return 0; | ||
531 | } | ||
532 | |||
527 | last_index = (i_size_read(inode) - 1) >> PAGE_CACHE_SHIFT; | 533 | last_index = (i_size_read(inode) - 1) >> PAGE_CACHE_SHIFT; |
528 | filemap_write_and_wait(inode->i_mapping); | 534 | filemap_write_and_wait(inode->i_mapping); |
529 | btrfs_wait_ordered_range(inode, inode->i_size & | 535 | btrfs_wait_ordered_range(inode, inode->i_size & |
@@ -543,10 +549,6 @@ int btrfs_write_out_cache(struct btrfs_root *root, | |||
543 | */ | 549 | */ |
544 | first_page_offset = (sizeof(u32) * num_checksums) + sizeof(u64); | 550 | first_page_offset = (sizeof(u32) * num_checksums) + sizeof(u64); |
545 | 551 | ||
546 | node = rb_first(&block_group->free_space_offset); | ||
547 | if (!node) | ||
548 | goto out_free; | ||
549 | |||
550 | /* | 552 | /* |
551 | * Lock all pages first so we can lock the extent safely. | 553 | * Lock all pages first so we can lock the extent safely. |
552 | * | 554 | * |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 8039390bd6a6..72f31ecb5c90 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -495,7 +495,7 @@ again: | |||
495 | add_async_extent(async_cow, start, num_bytes, | 495 | add_async_extent(async_cow, start, num_bytes, |
496 | total_compressed, pages, nr_pages_ret); | 496 | total_compressed, pages, nr_pages_ret); |
497 | 497 | ||
498 | if (start + num_bytes < end && start + num_bytes < actual_end) { | 498 | if (start + num_bytes < end) { |
499 | start += num_bytes; | 499 | start += num_bytes; |
500 | pages = NULL; | 500 | pages = NULL; |
501 | cond_resched(); | 501 | cond_resched(); |
@@ -5712,9 +5712,9 @@ static void btrfs_end_dio_bio(struct bio *bio, int err) | |||
5712 | 5712 | ||
5713 | if (err) { | 5713 | if (err) { |
5714 | printk(KERN_ERR "btrfs direct IO failed ino %lu rw %lu " | 5714 | printk(KERN_ERR "btrfs direct IO failed ino %lu rw %lu " |
5715 | "disk_bytenr %lu len %u err no %d\n", | 5715 | "sector %#Lx len %u err no %d\n", |
5716 | dip->inode->i_ino, bio->bi_rw, bio->bi_sector, | 5716 | dip->inode->i_ino, bio->bi_rw, |
5717 | bio->bi_size, err); | 5717 | (unsigned long long)bio->bi_sector, bio->bi_size, err); |
5718 | dip->errors = 1; | 5718 | dip->errors = 1; |
5719 | 5719 | ||
5720 | /* | 5720 | /* |
@@ -5934,8 +5934,7 @@ free_ordered: | |||
5934 | */ | 5934 | */ |
5935 | if (write) { | 5935 | if (write) { |
5936 | struct btrfs_ordered_extent *ordered; | 5936 | struct btrfs_ordered_extent *ordered; |
5937 | ordered = btrfs_lookup_ordered_extent(inode, | 5937 | ordered = btrfs_lookup_ordered_extent(inode, file_offset); |
5938 | dip->logical_offset); | ||
5939 | if (!test_bit(BTRFS_ORDERED_PREALLOC, &ordered->flags) && | 5938 | if (!test_bit(BTRFS_ORDERED_PREALLOC, &ordered->flags) && |
5940 | !test_bit(BTRFS_ORDERED_NOCOW, &ordered->flags)) | 5939 | !test_bit(BTRFS_ORDERED_NOCOW, &ordered->flags)) |
5941 | btrfs_free_reserved_extent(root, ordered->start, | 5940 | btrfs_free_reserved_extent(root, ordered->start, |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index f1c9bb4079ed..f87552a1d7ea 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -947,23 +947,42 @@ out: | |||
947 | 947 | ||
948 | static noinline int btrfs_ioctl_snap_create(struct file *file, | 948 | static noinline int btrfs_ioctl_snap_create(struct file *file, |
949 | void __user *arg, int subvol, | 949 | void __user *arg, int subvol, |
950 | int async) | 950 | int v2) |
951 | { | 951 | { |
952 | struct btrfs_ioctl_vol_args *vol_args = NULL; | 952 | struct btrfs_ioctl_vol_args *vol_args = NULL; |
953 | struct btrfs_ioctl_async_vol_args *async_vol_args = NULL; | 953 | struct btrfs_ioctl_vol_args_v2 *vol_args_v2 = NULL; |
954 | char *name; | 954 | char *name; |
955 | u64 fd; | 955 | u64 fd; |
956 | u64 transid = 0; | ||
957 | int ret; | 956 | int ret; |
958 | 957 | ||
959 | if (async) { | 958 | if (v2) { |
960 | async_vol_args = memdup_user(arg, sizeof(*async_vol_args)); | 959 | u64 transid = 0; |
961 | if (IS_ERR(async_vol_args)) | 960 | u64 *ptr = NULL; |
962 | return PTR_ERR(async_vol_args); | ||
963 | 961 | ||
964 | name = async_vol_args->name; | 962 | vol_args_v2 = memdup_user(arg, sizeof(*vol_args_v2)); |
965 | fd = async_vol_args->fd; | 963 | if (IS_ERR(vol_args_v2)) |
966 | async_vol_args->name[BTRFS_SNAPSHOT_NAME_MAX] = '\0'; | 964 | return PTR_ERR(vol_args_v2); |
965 | |||
966 | if (vol_args_v2->flags & ~BTRFS_SUBVOL_CREATE_ASYNC) { | ||
967 | ret = -EINVAL; | ||
968 | goto out; | ||
969 | } | ||
970 | |||
971 | name = vol_args_v2->name; | ||
972 | fd = vol_args_v2->fd; | ||
973 | vol_args_v2->name[BTRFS_SUBVOL_NAME_MAX] = '\0'; | ||
974 | |||
975 | if (vol_args_v2->flags & BTRFS_SUBVOL_CREATE_ASYNC) | ||
976 | ptr = &transid; | ||
977 | |||
978 | ret = btrfs_ioctl_snap_create_transid(file, name, fd, | ||
979 | subvol, ptr); | ||
980 | |||
981 | if (ret == 0 && ptr && | ||
982 | copy_to_user(arg + | ||
983 | offsetof(struct btrfs_ioctl_vol_args_v2, | ||
984 | transid), ptr, sizeof(*ptr))) | ||
985 | ret = -EFAULT; | ||
967 | } else { | 986 | } else { |
968 | vol_args = memdup_user(arg, sizeof(*vol_args)); | 987 | vol_args = memdup_user(arg, sizeof(*vol_args)); |
969 | if (IS_ERR(vol_args)) | 988 | if (IS_ERR(vol_args)) |
@@ -971,20 +990,13 @@ static noinline int btrfs_ioctl_snap_create(struct file *file, | |||
971 | name = vol_args->name; | 990 | name = vol_args->name; |
972 | fd = vol_args->fd; | 991 | fd = vol_args->fd; |
973 | vol_args->name[BTRFS_PATH_NAME_MAX] = '\0'; | 992 | vol_args->name[BTRFS_PATH_NAME_MAX] = '\0'; |
974 | } | ||
975 | |||
976 | ret = btrfs_ioctl_snap_create_transid(file, name, fd, | ||
977 | subvol, &transid); | ||
978 | 993 | ||
979 | if (!ret && async) { | 994 | ret = btrfs_ioctl_snap_create_transid(file, name, fd, |
980 | if (copy_to_user(arg + | 995 | subvol, NULL); |
981 | offsetof(struct btrfs_ioctl_async_vol_args, | ||
982 | transid), &transid, sizeof(transid))) | ||
983 | return -EFAULT; | ||
984 | } | 996 | } |
985 | 997 | out: | |
986 | kfree(vol_args); | 998 | kfree(vol_args); |
987 | kfree(async_vol_args); | 999 | kfree(vol_args_v2); |
988 | 1000 | ||
989 | return ret; | 1001 | return ret; |
990 | } | 1002 | } |
@@ -2246,7 +2258,7 @@ long btrfs_ioctl(struct file *file, unsigned int | |||
2246 | return btrfs_ioctl_getversion(file, argp); | 2258 | return btrfs_ioctl_getversion(file, argp); |
2247 | case BTRFS_IOC_SNAP_CREATE: | 2259 | case BTRFS_IOC_SNAP_CREATE: |
2248 | return btrfs_ioctl_snap_create(file, argp, 0, 0); | 2260 | return btrfs_ioctl_snap_create(file, argp, 0, 0); |
2249 | case BTRFS_IOC_SNAP_CREATE_ASYNC: | 2261 | case BTRFS_IOC_SNAP_CREATE_V2: |
2250 | return btrfs_ioctl_snap_create(file, argp, 0, 1); | 2262 | return btrfs_ioctl_snap_create(file, argp, 0, 1); |
2251 | case BTRFS_IOC_SUBVOL_CREATE: | 2263 | case BTRFS_IOC_SUBVOL_CREATE: |
2252 | return btrfs_ioctl_snap_create(file, argp, 1, 0); | 2264 | return btrfs_ioctl_snap_create(file, argp, 1, 0); |
diff --git a/fs/btrfs/ioctl.h b/fs/btrfs/ioctl.h index 17c99ebdf960..c344d12c646b 100644 --- a/fs/btrfs/ioctl.h +++ b/fs/btrfs/ioctl.h | |||
@@ -30,11 +30,15 @@ struct btrfs_ioctl_vol_args { | |||
30 | char name[BTRFS_PATH_NAME_MAX + 1]; | 30 | char name[BTRFS_PATH_NAME_MAX + 1]; |
31 | }; | 31 | }; |
32 | 32 | ||
33 | #define BTRFS_SNAPSHOT_NAME_MAX 4079 | 33 | #define BTRFS_SUBVOL_CREATE_ASYNC (1ULL << 0) |
34 | struct btrfs_ioctl_async_vol_args { | 34 | |
35 | #define BTRFS_SUBVOL_NAME_MAX 4039 | ||
36 | struct btrfs_ioctl_vol_args_v2 { | ||
35 | __s64 fd; | 37 | __s64 fd; |
36 | __u64 transid; | 38 | __u64 transid; |
37 | char name[BTRFS_SNAPSHOT_NAME_MAX + 1]; | 39 | __u64 flags; |
40 | __u64 unused[4]; | ||
41 | char name[BTRFS_SUBVOL_NAME_MAX + 1]; | ||
38 | }; | 42 | }; |
39 | 43 | ||
40 | #define BTRFS_INO_LOOKUP_PATH_MAX 4080 | 44 | #define BTRFS_INO_LOOKUP_PATH_MAX 4080 |
@@ -187,6 +191,6 @@ struct btrfs_ioctl_space_args { | |||
187 | struct btrfs_ioctl_space_args) | 191 | struct btrfs_ioctl_space_args) |
188 | #define BTRFS_IOC_START_SYNC _IOR(BTRFS_IOCTL_MAGIC, 24, __u64) | 192 | #define BTRFS_IOC_START_SYNC _IOR(BTRFS_IOCTL_MAGIC, 24, __u64) |
189 | #define BTRFS_IOC_WAIT_SYNC _IOW(BTRFS_IOCTL_MAGIC, 22, __u64) | 193 | #define BTRFS_IOC_WAIT_SYNC _IOW(BTRFS_IOCTL_MAGIC, 22, __u64) |
190 | #define BTRFS_IOC_SNAP_CREATE_ASYNC _IOW(BTRFS_IOCTL_MAGIC, 23, \ | 194 | #define BTRFS_IOC_SNAP_CREATE_V2 _IOW(BTRFS_IOCTL_MAGIC, 23, \ |
191 | struct btrfs_ioctl_async_vol_args) | 195 | struct btrfs_ioctl_vol_args_v2) |
192 | #endif | 196 | #endif |
diff --git a/fs/btrfs/orphan.c b/fs/btrfs/orphan.c index 79cba5fbc28e..f8be250963a0 100644 --- a/fs/btrfs/orphan.c +++ b/fs/btrfs/orphan.c | |||
@@ -56,8 +56,12 @@ int btrfs_del_orphan_item(struct btrfs_trans_handle *trans, | |||
56 | return -ENOMEM; | 56 | return -ENOMEM; |
57 | 57 | ||
58 | ret = btrfs_search_slot(trans, root, &key, path, -1, 1); | 58 | ret = btrfs_search_slot(trans, root, &key, path, -1, 1); |
59 | if (ret) | 59 | if (ret < 0) |
60 | goto out; | 60 | goto out; |
61 | if (ret) { | ||
62 | ret = -ENOENT; | ||
63 | goto out; | ||
64 | } | ||
61 | 65 | ||
62 | ret = btrfs_del_item(trans, root, path); | 66 | ret = btrfs_del_item(trans, root, path); |
63 | 67 | ||
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index dbb51ea7a13c..883c6fa1367e 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -685,9 +685,9 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
685 | mutex_unlock(&root->d_inode->i_mutex); | 685 | mutex_unlock(&root->d_inode->i_mutex); |
686 | 686 | ||
687 | if (IS_ERR(new_root)) { | 687 | if (IS_ERR(new_root)) { |
688 | dput(root); | ||
688 | deactivate_locked_super(s); | 689 | deactivate_locked_super(s); |
689 | error = PTR_ERR(new_root); | 690 | error = PTR_ERR(new_root); |
690 | dput(root); | ||
691 | goto error_free_subvol_name; | 691 | goto error_free_subvol_name; |
692 | } | 692 | } |
693 | if (!new_root->d_inode) { | 693 | if (!new_root->d_inode) { |
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index cc04dc1445d6..6b9884507837 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -412,12 +412,16 @@ static noinline int device_list_add(const char *path, | |||
412 | 412 | ||
413 | device->fs_devices = fs_devices; | 413 | device->fs_devices = fs_devices; |
414 | fs_devices->num_devices++; | 414 | fs_devices->num_devices++; |
415 | } else if (strcmp(device->name, path)) { | 415 | } else if (!device->name || strcmp(device->name, path)) { |
416 | name = kstrdup(path, GFP_NOFS); | 416 | name = kstrdup(path, GFP_NOFS); |
417 | if (!name) | 417 | if (!name) |
418 | return -ENOMEM; | 418 | return -ENOMEM; |
419 | kfree(device->name); | 419 | kfree(device->name); |
420 | device->name = name; | 420 | device->name = name; |
421 | if (device->missing) { | ||
422 | fs_devices->missing_devices--; | ||
423 | device->missing = 0; | ||
424 | } | ||
421 | } | 425 | } |
422 | 426 | ||
423 | if (found_transid > fs_devices->latest_trans) { | 427 | if (found_transid > fs_devices->latest_trans) { |
@@ -1236,6 +1240,9 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) | |||
1236 | 1240 | ||
1237 | device->fs_devices->num_devices--; | 1241 | device->fs_devices->num_devices--; |
1238 | 1242 | ||
1243 | if (device->missing) | ||
1244 | root->fs_info->fs_devices->missing_devices--; | ||
1245 | |||
1239 | next_device = list_entry(root->fs_info->fs_devices->devices.next, | 1246 | next_device = list_entry(root->fs_info->fs_devices->devices.next, |
1240 | struct btrfs_device, dev_list); | 1247 | struct btrfs_device, dev_list); |
1241 | if (device->bdev == root->fs_info->sb->s_bdev) | 1248 | if (device->bdev == root->fs_info->sb->s_bdev) |
@@ -3080,7 +3087,9 @@ static struct btrfs_device *add_missing_dev(struct btrfs_root *root, | |||
3080 | device->devid = devid; | 3087 | device->devid = devid; |
3081 | device->work.func = pending_bios_fn; | 3088 | device->work.func = pending_bios_fn; |
3082 | device->fs_devices = fs_devices; | 3089 | device->fs_devices = fs_devices; |
3090 | device->missing = 1; | ||
3083 | fs_devices->num_devices++; | 3091 | fs_devices->num_devices++; |
3092 | fs_devices->missing_devices++; | ||
3084 | spin_lock_init(&device->io_lock); | 3093 | spin_lock_init(&device->io_lock); |
3085 | INIT_LIST_HEAD(&device->dev_alloc_list); | 3094 | INIT_LIST_HEAD(&device->dev_alloc_list); |
3086 | memcpy(device->uuid, dev_uuid, BTRFS_UUID_SIZE); | 3095 | memcpy(device->uuid, dev_uuid, BTRFS_UUID_SIZE); |
@@ -3278,6 +3287,15 @@ static int read_one_dev(struct btrfs_root *root, | |||
3278 | device = add_missing_dev(root, devid, dev_uuid); | 3287 | device = add_missing_dev(root, devid, dev_uuid); |
3279 | if (!device) | 3288 | if (!device) |
3280 | return -ENOMEM; | 3289 | return -ENOMEM; |
3290 | } else if (!device->missing) { | ||
3291 | /* | ||
3292 | * this happens when a device that was properly setup | ||
3293 | * in the device info lists suddenly goes bad. | ||
3294 | * device->bdev is NULL, and so we have to set | ||
3295 | * device->missing to one here | ||
3296 | */ | ||
3297 | root->fs_info->fs_devices->missing_devices++; | ||
3298 | device->missing = 1; | ||
3281 | } | 3299 | } |
3282 | } | 3300 | } |
3283 | 3301 | ||
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index 2b638b6e4eea..2740db49eb04 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h | |||
@@ -44,6 +44,7 @@ struct btrfs_device { | |||
44 | 44 | ||
45 | int writeable; | 45 | int writeable; |
46 | int in_fs_metadata; | 46 | int in_fs_metadata; |
47 | int missing; | ||
47 | 48 | ||
48 | spinlock_t io_lock; | 49 | spinlock_t io_lock; |
49 | 50 | ||
@@ -93,6 +94,7 @@ struct btrfs_fs_devices { | |||
93 | u64 num_devices; | 94 | u64 num_devices; |
94 | u64 open_devices; | 95 | u64 open_devices; |
95 | u64 rw_devices; | 96 | u64 rw_devices; |
97 | u64 missing_devices; | ||
96 | u64 total_rw_bytes; | 98 | u64 total_rw_bytes; |
97 | struct block_device *latest_bdev; | 99 | struct block_device *latest_bdev; |
98 | 100 | ||
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 7d447af84ec4..158c700fdca5 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c | |||
@@ -114,8 +114,8 @@ static int __dcache_readdir(struct file *filp, | |||
114 | spin_lock(&dcache_lock); | 114 | spin_lock(&dcache_lock); |
115 | 115 | ||
116 | /* start at beginning? */ | 116 | /* start at beginning? */ |
117 | if (filp->f_pos == 2 || (last && | 117 | if (filp->f_pos == 2 || last == NULL || |
118 | filp->f_pos < ceph_dentry(last)->offset)) { | 118 | filp->f_pos < ceph_dentry(last)->offset) { |
119 | if (list_empty(&parent->d_subdirs)) | 119 | if (list_empty(&parent->d_subdirs)) |
120 | goto out_unlock; | 120 | goto out_unlock; |
121 | p = parent->d_subdirs.prev; | 121 | p = parent->d_subdirs.prev; |
diff --git a/fs/ceph/ioctl.h b/fs/ceph/ioctl.h index a6ce54e94eb5..52e8fd74d450 100644 --- a/fs/ceph/ioctl.h +++ b/fs/ceph/ioctl.h | |||
@@ -4,7 +4,7 @@ | |||
4 | #include <linux/ioctl.h> | 4 | #include <linux/ioctl.h> |
5 | #include <linux/types.h> | 5 | #include <linux/types.h> |
6 | 6 | ||
7 | #define CEPH_IOCTL_MAGIC 0x98 | 7 | #define CEPH_IOCTL_MAGIC 0x97 |
8 | 8 | ||
9 | /* just use u64 to align sanely on all archs */ | 9 | /* just use u64 to align sanely on all archs */ |
10 | struct ceph_ioctl_layout { | 10 | struct ceph_ioctl_layout { |
diff --git a/fs/ceph/locks.c b/fs/ceph/locks.c index 40abde93c345..476b329867d4 100644 --- a/fs/ceph/locks.c +++ b/fs/ceph/locks.c | |||
@@ -11,40 +11,68 @@ | |||
11 | * Implement fcntl and flock locking functions. | 11 | * Implement fcntl and flock locking functions. |
12 | */ | 12 | */ |
13 | static int ceph_lock_message(u8 lock_type, u16 operation, struct file *file, | 13 | static int ceph_lock_message(u8 lock_type, u16 operation, struct file *file, |
14 | u64 pid, u64 pid_ns, | 14 | int cmd, u8 wait, struct file_lock *fl) |
15 | int cmd, u64 start, u64 length, u8 wait) | ||
16 | { | 15 | { |
17 | struct inode *inode = file->f_dentry->d_inode; | 16 | struct inode *inode = file->f_dentry->d_inode; |
18 | struct ceph_mds_client *mdsc = | 17 | struct ceph_mds_client *mdsc = |
19 | ceph_sb_to_client(inode->i_sb)->mdsc; | 18 | ceph_sb_to_client(inode->i_sb)->mdsc; |
20 | struct ceph_mds_request *req; | 19 | struct ceph_mds_request *req; |
21 | int err; | 20 | int err; |
21 | u64 length = 0; | ||
22 | 22 | ||
23 | req = ceph_mdsc_create_request(mdsc, operation, USE_AUTH_MDS); | 23 | req = ceph_mdsc_create_request(mdsc, operation, USE_AUTH_MDS); |
24 | if (IS_ERR(req)) | 24 | if (IS_ERR(req)) |
25 | return PTR_ERR(req); | 25 | return PTR_ERR(req); |
26 | req->r_inode = igrab(inode); | 26 | req->r_inode = igrab(inode); |
27 | 27 | ||
28 | /* mds requires start and length rather than start and end */ | ||
29 | if (LLONG_MAX == fl->fl_end) | ||
30 | length = 0; | ||
31 | else | ||
32 | length = fl->fl_end - fl->fl_start + 1; | ||
33 | |||
28 | dout("ceph_lock_message: rule: %d, op: %d, pid: %llu, start: %llu, " | 34 | dout("ceph_lock_message: rule: %d, op: %d, pid: %llu, start: %llu, " |
29 | "length: %llu, wait: %d, type`: %d", (int)lock_type, | 35 | "length: %llu, wait: %d, type`: %d", (int)lock_type, |
30 | (int)operation, pid, start, length, wait, cmd); | 36 | (int)operation, (u64)fl->fl_pid, fl->fl_start, |
37 | length, wait, fl->fl_type); | ||
38 | |||
31 | 39 | ||
32 | req->r_args.filelock_change.rule = lock_type; | 40 | req->r_args.filelock_change.rule = lock_type; |
33 | req->r_args.filelock_change.type = cmd; | 41 | req->r_args.filelock_change.type = cmd; |
34 | req->r_args.filelock_change.pid = cpu_to_le64(pid); | 42 | req->r_args.filelock_change.pid = cpu_to_le64((u64)fl->fl_pid); |
35 | /* This should be adjusted, but I'm not sure if | 43 | /* This should be adjusted, but I'm not sure if |
36 | namespaces actually get id numbers*/ | 44 | namespaces actually get id numbers*/ |
37 | req->r_args.filelock_change.pid_namespace = | 45 | req->r_args.filelock_change.pid_namespace = |
38 | cpu_to_le64((u64)pid_ns); | 46 | cpu_to_le64((u64)(unsigned long)fl->fl_nspid); |
39 | req->r_args.filelock_change.start = cpu_to_le64(start); | 47 | req->r_args.filelock_change.start = cpu_to_le64(fl->fl_start); |
40 | req->r_args.filelock_change.length = cpu_to_le64(length); | 48 | req->r_args.filelock_change.length = cpu_to_le64(length); |
41 | req->r_args.filelock_change.wait = wait; | 49 | req->r_args.filelock_change.wait = wait; |
42 | 50 | ||
43 | err = ceph_mdsc_do_request(mdsc, inode, req); | 51 | err = ceph_mdsc_do_request(mdsc, inode, req); |
52 | |||
53 | if ( operation == CEPH_MDS_OP_GETFILELOCK){ | ||
54 | fl->fl_pid = le64_to_cpu(req->r_reply_info.filelock_reply->pid); | ||
55 | if (CEPH_LOCK_SHARED == req->r_reply_info.filelock_reply->type) | ||
56 | fl->fl_type = F_RDLCK; | ||
57 | else if (CEPH_LOCK_EXCL == req->r_reply_info.filelock_reply->type) | ||
58 | fl->fl_type = F_WRLCK; | ||
59 | else | ||
60 | fl->fl_type = F_UNLCK; | ||
61 | |||
62 | fl->fl_start = le64_to_cpu(req->r_reply_info.filelock_reply->start); | ||
63 | length = le64_to_cpu(req->r_reply_info.filelock_reply->start) + | ||
64 | le64_to_cpu(req->r_reply_info.filelock_reply->length); | ||
65 | if (length >= 1) | ||
66 | fl->fl_end = length -1; | ||
67 | else | ||
68 | fl->fl_end = 0; | ||
69 | |||
70 | } | ||
44 | ceph_mdsc_put_request(req); | 71 | ceph_mdsc_put_request(req); |
45 | dout("ceph_lock_message: rule: %d, op: %d, pid: %llu, start: %llu, " | 72 | dout("ceph_lock_message: rule: %d, op: %d, pid: %llu, start: %llu, " |
46 | "length: %llu, wait: %d, type`: %d err code %d", (int)lock_type, | 73 | "length: %llu, wait: %d, type`: %d, err code %d", (int)lock_type, |
47 | (int)operation, pid, start, length, wait, cmd, err); | 74 | (int)operation, (u64)fl->fl_pid, fl->fl_start, |
75 | length, wait, fl->fl_type, err); | ||
48 | return err; | 76 | return err; |
49 | } | 77 | } |
50 | 78 | ||
@@ -54,7 +82,6 @@ static int ceph_lock_message(u8 lock_type, u16 operation, struct file *file, | |||
54 | */ | 82 | */ |
55 | int ceph_lock(struct file *file, int cmd, struct file_lock *fl) | 83 | int ceph_lock(struct file *file, int cmd, struct file_lock *fl) |
56 | { | 84 | { |
57 | u64 length; | ||
58 | u8 lock_cmd; | 85 | u8 lock_cmd; |
59 | int err; | 86 | int err; |
60 | u8 wait = 0; | 87 | u8 wait = 0; |
@@ -76,29 +103,20 @@ int ceph_lock(struct file *file, int cmd, struct file_lock *fl) | |||
76 | else | 103 | else |
77 | lock_cmd = CEPH_LOCK_UNLOCK; | 104 | lock_cmd = CEPH_LOCK_UNLOCK; |
78 | 105 | ||
79 | if (LLONG_MAX == fl->fl_end) | 106 | err = ceph_lock_message(CEPH_LOCK_FCNTL, op, file, lock_cmd, wait, fl); |
80 | length = 0; | ||
81 | else | ||
82 | length = fl->fl_end - fl->fl_start + 1; | ||
83 | |||
84 | err = ceph_lock_message(CEPH_LOCK_FCNTL, op, file, | ||
85 | (u64)fl->fl_pid, | ||
86 | (u64)(unsigned long)fl->fl_nspid, | ||
87 | lock_cmd, fl->fl_start, | ||
88 | length, wait); | ||
89 | if (!err) { | 107 | if (!err) { |
90 | dout("mds locked, locking locally"); | 108 | if ( op != CEPH_MDS_OP_GETFILELOCK ){ |
91 | err = posix_lock_file(file, fl, NULL); | 109 | dout("mds locked, locking locally"); |
92 | if (err && (CEPH_MDS_OP_SETFILELOCK == op)) { | 110 | err = posix_lock_file(file, fl, NULL); |
93 | /* undo! This should only happen if the kernel detects | 111 | if (err && (CEPH_MDS_OP_SETFILELOCK == op)) { |
94 | * local deadlock. */ | 112 | /* undo! This should only happen if the kernel detects |
95 | ceph_lock_message(CEPH_LOCK_FCNTL, op, file, | 113 | * local deadlock. */ |
96 | (u64)fl->fl_pid, | 114 | ceph_lock_message(CEPH_LOCK_FCNTL, op, file, |
97 | (u64)(unsigned long)fl->fl_nspid, | 115 | CEPH_LOCK_UNLOCK, 0, fl); |
98 | CEPH_LOCK_UNLOCK, fl->fl_start, | 116 | dout("got %d on posix_lock_file, undid lock", err); |
99 | length, 0); | 117 | } |
100 | dout("got %d on posix_lock_file, undid lock", err); | ||
101 | } | 118 | } |
119 | |||
102 | } else { | 120 | } else { |
103 | dout("mds returned error code %d", err); | 121 | dout("mds returned error code %d", err); |
104 | } | 122 | } |
@@ -107,7 +125,6 @@ int ceph_lock(struct file *file, int cmd, struct file_lock *fl) | |||
107 | 125 | ||
108 | int ceph_flock(struct file *file, int cmd, struct file_lock *fl) | 126 | int ceph_flock(struct file *file, int cmd, struct file_lock *fl) |
109 | { | 127 | { |
110 | u64 length; | ||
111 | u8 lock_cmd; | 128 | u8 lock_cmd; |
112 | int err; | 129 | int err; |
113 | u8 wait = 1; | 130 | u8 wait = 1; |
@@ -127,26 +144,15 @@ int ceph_flock(struct file *file, int cmd, struct file_lock *fl) | |||
127 | lock_cmd = CEPH_LOCK_EXCL; | 144 | lock_cmd = CEPH_LOCK_EXCL; |
128 | else | 145 | else |
129 | lock_cmd = CEPH_LOCK_UNLOCK; | 146 | lock_cmd = CEPH_LOCK_UNLOCK; |
130 | /* mds requires start and length rather than start and end */ | ||
131 | if (LLONG_MAX == fl->fl_end) | ||
132 | length = 0; | ||
133 | else | ||
134 | length = fl->fl_end - fl->fl_start + 1; | ||
135 | 147 | ||
136 | err = ceph_lock_message(CEPH_LOCK_FLOCK, CEPH_MDS_OP_SETFILELOCK, | 148 | err = ceph_lock_message(CEPH_LOCK_FLOCK, CEPH_MDS_OP_SETFILELOCK, |
137 | file, (u64)fl->fl_pid, | 149 | file, lock_cmd, wait, fl); |
138 | (u64)(unsigned long)fl->fl_nspid, | ||
139 | lock_cmd, fl->fl_start, | ||
140 | length, wait); | ||
141 | if (!err) { | 150 | if (!err) { |
142 | err = flock_lock_file_wait(file, fl); | 151 | err = flock_lock_file_wait(file, fl); |
143 | if (err) { | 152 | if (err) { |
144 | ceph_lock_message(CEPH_LOCK_FLOCK, | 153 | ceph_lock_message(CEPH_LOCK_FLOCK, |
145 | CEPH_MDS_OP_SETFILELOCK, | 154 | CEPH_MDS_OP_SETFILELOCK, |
146 | file, (u64)fl->fl_pid, | 155 | file, CEPH_LOCK_UNLOCK, 0, fl); |
147 | (u64)(unsigned long)fl->fl_nspid, | ||
148 | CEPH_LOCK_UNLOCK, fl->fl_start, | ||
149 | length, 0); | ||
150 | dout("got %d on flock_lock_file_wait, undid lock", err); | 156 | dout("got %d on flock_lock_file_wait, undid lock", err); |
151 | } | 157 | } |
152 | } else { | 158 | } else { |
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 098b18508479..38800eaa81d0 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c | |||
@@ -202,6 +202,38 @@ out_bad: | |||
202 | } | 202 | } |
203 | 203 | ||
204 | /* | 204 | /* |
205 | * parse fcntl F_GETLK results | ||
206 | */ | ||
207 | static int parse_reply_info_filelock(void **p, void *end, | ||
208 | struct ceph_mds_reply_info_parsed *info) | ||
209 | { | ||
210 | if (*p + sizeof(*info->filelock_reply) > end) | ||
211 | goto bad; | ||
212 | |||
213 | info->filelock_reply = *p; | ||
214 | *p += sizeof(*info->filelock_reply); | ||
215 | |||
216 | if (unlikely(*p != end)) | ||
217 | goto bad; | ||
218 | return 0; | ||
219 | |||
220 | bad: | ||
221 | return -EIO; | ||
222 | } | ||
223 | |||
224 | /* | ||
225 | * parse extra results | ||
226 | */ | ||
227 | static int parse_reply_info_extra(void **p, void *end, | ||
228 | struct ceph_mds_reply_info_parsed *info) | ||
229 | { | ||
230 | if (info->head->op == CEPH_MDS_OP_GETFILELOCK) | ||
231 | return parse_reply_info_filelock(p, end, info); | ||
232 | else | ||
233 | return parse_reply_info_dir(p, end, info); | ||
234 | } | ||
235 | |||
236 | /* | ||
205 | * parse entire mds reply | 237 | * parse entire mds reply |
206 | */ | 238 | */ |
207 | static int parse_reply_info(struct ceph_msg *msg, | 239 | static int parse_reply_info(struct ceph_msg *msg, |
@@ -223,10 +255,10 @@ static int parse_reply_info(struct ceph_msg *msg, | |||
223 | goto out_bad; | 255 | goto out_bad; |
224 | } | 256 | } |
225 | 257 | ||
226 | /* dir content */ | 258 | /* extra */ |
227 | ceph_decode_32_safe(&p, end, len, bad); | 259 | ceph_decode_32_safe(&p, end, len, bad); |
228 | if (len > 0) { | 260 | if (len > 0) { |
229 | err = parse_reply_info_dir(&p, p+len, info); | 261 | err = parse_reply_info_extra(&p, p+len, info); |
230 | if (err < 0) | 262 | if (err < 0) |
231 | goto out_bad; | 263 | goto out_bad; |
232 | } | 264 | } |
@@ -2074,7 +2106,7 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg) | |||
2074 | 2106 | ||
2075 | mutex_lock(&session->s_mutex); | 2107 | mutex_lock(&session->s_mutex); |
2076 | if (err < 0) { | 2108 | if (err < 0) { |
2077 | pr_err("mdsc_handle_reply got corrupt reply mds%d\n", mds); | 2109 | pr_err("mdsc_handle_reply got corrupt reply mds%d(tid:%lld)\n", mds, tid); |
2078 | ceph_msg_dump(msg); | 2110 | ceph_msg_dump(msg); |
2079 | goto out_err; | 2111 | goto out_err; |
2080 | } | 2112 | } |
@@ -2094,7 +2126,8 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg) | |||
2094 | mutex_lock(&req->r_fill_mutex); | 2126 | mutex_lock(&req->r_fill_mutex); |
2095 | err = ceph_fill_trace(mdsc->fsc->sb, req, req->r_session); | 2127 | err = ceph_fill_trace(mdsc->fsc->sb, req, req->r_session); |
2096 | if (err == 0) { | 2128 | if (err == 0) { |
2097 | if (result == 0 && rinfo->dir_nr) | 2129 | if (result == 0 && req->r_op != CEPH_MDS_OP_GETFILELOCK && |
2130 | rinfo->dir_nr) | ||
2098 | ceph_readdir_prepopulate(req, req->r_session); | 2131 | ceph_readdir_prepopulate(req, req->r_session); |
2099 | ceph_unreserve_caps(mdsc, &req->r_caps_reservation); | 2132 | ceph_unreserve_caps(mdsc, &req->r_caps_reservation); |
2100 | } | 2133 | } |
diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h index 9341fd4f1432..aabe563b54db 100644 --- a/fs/ceph/mds_client.h +++ b/fs/ceph/mds_client.h | |||
@@ -42,26 +42,37 @@ struct ceph_mds_reply_info_in { | |||
42 | }; | 42 | }; |
43 | 43 | ||
44 | /* | 44 | /* |
45 | * parsed info about an mds reply, including information about the | 45 | * parsed info about an mds reply, including information about |
46 | * target inode and/or its parent directory and dentry, and directory | 46 | * either: 1) the target inode and/or its parent directory and dentry, |
47 | * contents (for readdir results). | 47 | * and directory contents (for readdir results), or |
48 | * 2) the file range lock info (for fcntl F_GETLK results). | ||
48 | */ | 49 | */ |
49 | struct ceph_mds_reply_info_parsed { | 50 | struct ceph_mds_reply_info_parsed { |
50 | struct ceph_mds_reply_head *head; | 51 | struct ceph_mds_reply_head *head; |
51 | 52 | ||
53 | /* trace */ | ||
52 | struct ceph_mds_reply_info_in diri, targeti; | 54 | struct ceph_mds_reply_info_in diri, targeti; |
53 | struct ceph_mds_reply_dirfrag *dirfrag; | 55 | struct ceph_mds_reply_dirfrag *dirfrag; |
54 | char *dname; | 56 | char *dname; |
55 | u32 dname_len; | 57 | u32 dname_len; |
56 | struct ceph_mds_reply_lease *dlease; | 58 | struct ceph_mds_reply_lease *dlease; |
57 | 59 | ||
58 | struct ceph_mds_reply_dirfrag *dir_dir; | 60 | /* extra */ |
59 | int dir_nr; | 61 | union { |
60 | char **dir_dname; | 62 | /* for fcntl F_GETLK results */ |
61 | u32 *dir_dname_len; | 63 | struct ceph_filelock *filelock_reply; |
62 | struct ceph_mds_reply_lease **dir_dlease; | 64 | |
63 | struct ceph_mds_reply_info_in *dir_in; | 65 | /* for readdir results */ |
64 | u8 dir_complete, dir_end; | 66 | struct { |
67 | struct ceph_mds_reply_dirfrag *dir_dir; | ||
68 | int dir_nr; | ||
69 | char **dir_dname; | ||
70 | u32 *dir_dname_len; | ||
71 | struct ceph_mds_reply_lease **dir_dlease; | ||
72 | struct ceph_mds_reply_info_in *dir_in; | ||
73 | u8 dir_complete, dir_end; | ||
74 | }; | ||
75 | }; | ||
65 | 76 | ||
66 | /* encoded blob describing snapshot contexts for certain | 77 | /* encoded blob describing snapshot contexts for certain |
67 | operations (e.g., open) */ | 78 | operations (e.g., open) */ |
diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig index 0ed213970ced..ee45648b0d1a 100644 --- a/fs/cifs/Kconfig +++ b/fs/cifs/Kconfig | |||
@@ -4,6 +4,7 @@ config CIFS | |||
4 | select NLS | 4 | select NLS |
5 | select CRYPTO | 5 | select CRYPTO |
6 | select CRYPTO_MD5 | 6 | select CRYPTO_MD5 |
7 | select CRYPTO_HMAC | ||
7 | select CRYPTO_ARC4 | 8 | select CRYPTO_ARC4 |
8 | help | 9 | help |
9 | This is the client VFS module for the Common Internet File System | 10 | This is the client VFS module for the Common Internet File System |
@@ -143,6 +144,13 @@ config CIFS_FSCACHE | |||
143 | to be cached locally on disk through the general filesystem cache | 144 | to be cached locally on disk through the general filesystem cache |
144 | manager. If unsure, say N. | 145 | manager. If unsure, say N. |
145 | 146 | ||
147 | config CIFS_ACL | ||
148 | bool "Provide CIFS ACL support (EXPERIMENTAL)" | ||
149 | depends on EXPERIMENTAL && CIFS_XATTR | ||
150 | help | ||
151 | Allows to fetch CIFS/NTFS ACL from the server. The DACL blob | ||
152 | is handed over to the application/caller. | ||
153 | |||
146 | config CIFS_EXPERIMENTAL | 154 | config CIFS_EXPERIMENTAL |
147 | bool "CIFS Experimental Features (EXPERIMENTAL)" | 155 | bool "CIFS Experimental Features (EXPERIMENTAL)" |
148 | depends on CIFS && EXPERIMENTAL | 156 | depends on CIFS && EXPERIMENTAL |
diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile index adefa60a9bdc..43b19dd39191 100644 --- a/fs/cifs/Makefile +++ b/fs/cifs/Makefile | |||
@@ -6,7 +6,9 @@ obj-$(CONFIG_CIFS) += cifs.o | |||
6 | cifs-y := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o \ | 6 | cifs-y := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o \ |
7 | link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o \ | 7 | link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o \ |
8 | md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o \ | 8 | md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o \ |
9 | readdir.o ioctl.o sess.o export.o cifsacl.o | 9 | readdir.o ioctl.o sess.o export.o |
10 | |||
11 | cifs-$(CONFIG_CIFS_ACL) += cifsacl.o | ||
10 | 12 | ||
11 | cifs-$(CONFIG_CIFS_UPCALL) += cifs_spnego.o | 13 | cifs-$(CONFIG_CIFS_UPCALL) += cifs_spnego.o |
12 | 14 | ||
diff --git a/fs/cifs/README b/fs/cifs/README index ee68d1036544..46af99ab3614 100644 --- a/fs/cifs/README +++ b/fs/cifs/README | |||
@@ -337,6 +337,15 @@ A partial list of the supported mount options follows: | |||
337 | wsize default write size (default 57344) | 337 | wsize default write size (default 57344) |
338 | maximum wsize currently allowed by CIFS is 57344 (fourteen | 338 | maximum wsize currently allowed by CIFS is 57344 (fourteen |
339 | 4096 byte pages) | 339 | 4096 byte pages) |
340 | actimeo=n attribute cache timeout in seconds (default 1 second). | ||
341 | After this timeout, the cifs client requests fresh attribute | ||
342 | information from the server. This option allows to tune the | ||
343 | attribute cache timeout to suit the workload needs. Shorter | ||
344 | timeouts mean better the cache coherency, but increased number | ||
345 | of calls to the server. Longer timeouts mean reduced number | ||
346 | of calls to the server at the expense of less stricter cache | ||
347 | coherency checks (i.e. incorrect attribute cache for a short | ||
348 | period of time). | ||
340 | rw mount the network share read-write (note that the | 349 | rw mount the network share read-write (note that the |
341 | server may still consider the share read-only) | 350 | server may still consider the share read-only) |
342 | ro mount network share read-only | 351 | ro mount network share read-only |
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h index e9a393c9c2ca..7852cd677051 100644 --- a/fs/cifs/cifs_fs_sb.h +++ b/fs/cifs/cifs_fs_sb.h | |||
@@ -48,6 +48,7 @@ struct cifs_sb_info { | |||
48 | struct nls_table *local_nls; | 48 | struct nls_table *local_nls; |
49 | unsigned int rsize; | 49 | unsigned int rsize; |
50 | unsigned int wsize; | 50 | unsigned int wsize; |
51 | unsigned long actimeo; /* attribute cache timeout (jiffies) */ | ||
51 | atomic_t active; | 52 | atomic_t active; |
52 | uid_t mnt_uid; | 53 | uid_t mnt_uid; |
53 | gid_t mnt_gid; | 54 | gid_t mnt_gid; |
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index c9b4792ae825..a437ec391a01 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c | |||
@@ -30,8 +30,6 @@ | |||
30 | #include "cifs_debug.h" | 30 | #include "cifs_debug.h" |
31 | 31 | ||
32 | 32 | ||
33 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
34 | |||
35 | static struct cifs_wksid wksidarr[NUM_WK_SIDS] = { | 33 | static struct cifs_wksid wksidarr[NUM_WK_SIDS] = { |
36 | {{1, 0, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0} }, "null user"}, | 34 | {{1, 0, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0} }, "null user"}, |
37 | {{1, 1, {0, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0} }, "nobody"}, | 35 | {{1, 1, {0, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0} }, "nobody"}, |
@@ -560,7 +558,7 @@ static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, | |||
560 | struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); | 558 | struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); |
561 | 559 | ||
562 | if (IS_ERR(tlink)) | 560 | if (IS_ERR(tlink)) |
563 | return NULL; | 561 | return ERR_CAST(tlink); |
564 | 562 | ||
565 | xid = GetXid(); | 563 | xid = GetXid(); |
566 | rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), fid, &pntsd, pacllen); | 564 | rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), fid, &pntsd, pacllen); |
@@ -568,7 +566,9 @@ static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, | |||
568 | 566 | ||
569 | cifs_put_tlink(tlink); | 567 | cifs_put_tlink(tlink); |
570 | 568 | ||
571 | cFYI(1, "GetCIFSACL rc = %d ACL len %d", rc, *pacllen); | 569 | cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen); |
570 | if (rc) | ||
571 | return ERR_PTR(rc); | ||
572 | return pntsd; | 572 | return pntsd; |
573 | } | 573 | } |
574 | 574 | ||
@@ -583,7 +583,7 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, | |||
583 | struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); | 583 | struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); |
584 | 584 | ||
585 | if (IS_ERR(tlink)) | 585 | if (IS_ERR(tlink)) |
586 | return NULL; | 586 | return ERR_CAST(tlink); |
587 | 587 | ||
588 | tcon = tlink_tcon(tlink); | 588 | tcon = tlink_tcon(tlink); |
589 | xid = GetXid(); | 589 | xid = GetXid(); |
@@ -591,23 +591,22 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, | |||
591 | rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, READ_CONTROL, 0, | 591 | rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, READ_CONTROL, 0, |
592 | &fid, &oplock, NULL, cifs_sb->local_nls, | 592 | &fid, &oplock, NULL, cifs_sb->local_nls, |
593 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 593 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); |
594 | if (rc) { | 594 | if (!rc) { |
595 | cERROR(1, "Unable to open file to get ACL"); | 595 | rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen); |
596 | goto out; | 596 | CIFSSMBClose(xid, tcon, fid); |
597 | } | 597 | } |
598 | 598 | ||
599 | rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen); | ||
600 | cFYI(1, "GetCIFSACL rc = %d ACL len %d", rc, *pacllen); | ||
601 | |||
602 | CIFSSMBClose(xid, tcon, fid); | ||
603 | out: | ||
604 | cifs_put_tlink(tlink); | 599 | cifs_put_tlink(tlink); |
605 | FreeXid(xid); | 600 | FreeXid(xid); |
601 | |||
602 | cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen); | ||
603 | if (rc) | ||
604 | return ERR_PTR(rc); | ||
606 | return pntsd; | 605 | return pntsd; |
607 | } | 606 | } |
608 | 607 | ||
609 | /* Retrieve an ACL from the server */ | 608 | /* Retrieve an ACL from the server */ |
610 | static struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb, | 609 | struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb, |
611 | struct inode *inode, const char *path, | 610 | struct inode *inode, const char *path, |
612 | u32 *pacllen) | 611 | u32 *pacllen) |
613 | { | 612 | { |
@@ -695,7 +694,7 @@ static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, | |||
695 | } | 694 | } |
696 | 695 | ||
697 | /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */ | 696 | /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */ |
698 | void | 697 | int |
699 | cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, | 698 | cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, |
700 | struct inode *inode, const char *path, const __u16 *pfid) | 699 | struct inode *inode, const char *path, const __u16 *pfid) |
701 | { | 700 | { |
@@ -711,17 +710,21 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, | |||
711 | pntsd = get_cifs_acl(cifs_sb, inode, path, &acllen); | 710 | pntsd = get_cifs_acl(cifs_sb, inode, path, &acllen); |
712 | 711 | ||
713 | /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */ | 712 | /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */ |
714 | if (pntsd) | 713 | if (IS_ERR(pntsd)) { |
714 | rc = PTR_ERR(pntsd); | ||
715 | cERROR(1, "%s: error %d getting sec desc", __func__, rc); | ||
716 | } else { | ||
715 | rc = parse_sec_desc(pntsd, acllen, fattr); | 717 | rc = parse_sec_desc(pntsd, acllen, fattr); |
716 | if (rc) | 718 | kfree(pntsd); |
717 | cFYI(1, "parse sec desc failed rc = %d", rc); | 719 | if (rc) |
720 | cERROR(1, "parse sec desc failed rc = %d", rc); | ||
721 | } | ||
718 | 722 | ||
719 | kfree(pntsd); | 723 | return rc; |
720 | return; | ||
721 | } | 724 | } |
722 | 725 | ||
723 | /* Convert mode bits to an ACL so we can update the ACL on the server */ | 726 | /* Convert mode bits to an ACL so we can update the ACL on the server */ |
724 | int mode_to_acl(struct inode *inode, const char *path, __u64 nmode) | 727 | int mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode) |
725 | { | 728 | { |
726 | int rc = 0; | 729 | int rc = 0; |
727 | __u32 secdesclen = 0; | 730 | __u32 secdesclen = 0; |
@@ -736,7 +739,10 @@ int mode_to_acl(struct inode *inode, const char *path, __u64 nmode) | |||
736 | /* Add three ACEs for owner, group, everyone getting rid of | 739 | /* Add three ACEs for owner, group, everyone getting rid of |
737 | other ACEs as chmod disables ACEs and set the security descriptor */ | 740 | other ACEs as chmod disables ACEs and set the security descriptor */ |
738 | 741 | ||
739 | if (pntsd) { | 742 | if (IS_ERR(pntsd)) { |
743 | rc = PTR_ERR(pntsd); | ||
744 | cERROR(1, "%s: error %d getting sec desc", __func__, rc); | ||
745 | } else { | ||
740 | /* allocate memory for the smb header, | 746 | /* allocate memory for the smb header, |
741 | set security descriptor request security descriptor | 747 | set security descriptor request security descriptor |
742 | parameters, and secuirty descriptor itself */ | 748 | parameters, and secuirty descriptor itself */ |
@@ -766,4 +772,3 @@ int mode_to_acl(struct inode *inode, const char *path, __u64 nmode) | |||
766 | 772 | ||
767 | return rc; | 773 | return rc; |
768 | } | 774 | } |
769 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | ||
diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h index 6c8096cf5155..c4ae7d036563 100644 --- a/fs/cifs/cifsacl.h +++ b/fs/cifs/cifsacl.h | |||
@@ -74,11 +74,7 @@ struct cifs_wksid { | |||
74 | char sidname[SIDNAMELENGTH]; | 74 | char sidname[SIDNAMELENGTH]; |
75 | } __attribute__((packed)); | 75 | } __attribute__((packed)); |
76 | 76 | ||
77 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
78 | |||
79 | extern int match_sid(struct cifs_sid *); | 77 | extern int match_sid(struct cifs_sid *); |
80 | extern int compare_sids(const struct cifs_sid *, const struct cifs_sid *); | 78 | extern int compare_sids(const struct cifs_sid *, const struct cifs_sid *); |
81 | 79 | ||
82 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | ||
83 | |||
84 | #endif /* _CIFSACL_H */ | 80 | #endif /* _CIFSACL_H */ |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 9c3789762ab7..3936aa7f2c22 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -458,9 +458,13 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m) | |||
458 | seq_printf(s, ",acl"); | 458 | seq_printf(s, ",acl"); |
459 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) | 459 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) |
460 | seq_printf(s, ",mfsymlinks"); | 460 | seq_printf(s, ",mfsymlinks"); |
461 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE) | ||
462 | seq_printf(s, ",fsc"); | ||
461 | 463 | ||
462 | seq_printf(s, ",rsize=%d", cifs_sb->rsize); | 464 | seq_printf(s, ",rsize=%d", cifs_sb->rsize); |
463 | seq_printf(s, ",wsize=%d", cifs_sb->wsize); | 465 | seq_printf(s, ",wsize=%d", cifs_sb->wsize); |
466 | /* convert actimeo and display it in seconds */ | ||
467 | seq_printf(s, ",actimeo=%lu", cifs_sb->actimeo / HZ); | ||
464 | 468 | ||
465 | return 0; | 469 | return 0; |
466 | } | 470 | } |
@@ -933,7 +937,6 @@ init_cifs(void) | |||
933 | GlobalCurrentXid = 0; | 937 | GlobalCurrentXid = 0; |
934 | GlobalTotalActiveXid = 0; | 938 | GlobalTotalActiveXid = 0; |
935 | GlobalMaxActiveXid = 0; | 939 | GlobalMaxActiveXid = 0; |
936 | memset(Local_System_Name, 0, 15); | ||
937 | spin_lock_init(&cifs_tcp_ses_lock); | 940 | spin_lock_init(&cifs_tcp_ses_lock); |
938 | spin_lock_init(&cifs_file_list_lock); | 941 | spin_lock_init(&cifs_file_list_lock); |
939 | spin_lock_init(&GlobalMid_Lock); | 942 | spin_lock_init(&GlobalMid_Lock); |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index b577bf0a1bb3..7136c0c3e2f9 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -45,6 +45,16 @@ | |||
45 | #define CIFS_MIN_RCV_POOL 4 | 45 | #define CIFS_MIN_RCV_POOL 4 |
46 | 46 | ||
47 | /* | 47 | /* |
48 | * default attribute cache timeout (jiffies) | ||
49 | */ | ||
50 | #define CIFS_DEF_ACTIMEO (1 * HZ) | ||
51 | |||
52 | /* | ||
53 | * max attribute cache timeout (jiffies) - 2^30 | ||
54 | */ | ||
55 | #define CIFS_MAX_ACTIMEO (1 << 30) | ||
56 | |||
57 | /* | ||
48 | * MAX_REQ is the maximum number of requests that WE will send | 58 | * MAX_REQ is the maximum number of requests that WE will send |
49 | * on one socket concurrently. It also matches the most common | 59 | * on one socket concurrently. It also matches the most common |
50 | * value of max multiplex returned by servers. We may | 60 | * value of max multiplex returned by servers. We may |
@@ -746,8 +756,6 @@ GLOBAL_EXTERN unsigned int GlobalTotalActiveXid; /* prot by GlobalMid_Sem */ | |||
746 | GLOBAL_EXTERN unsigned int GlobalMaxActiveXid; /* prot by GlobalMid_Sem */ | 756 | GLOBAL_EXTERN unsigned int GlobalMaxActiveXid; /* prot by GlobalMid_Sem */ |
747 | GLOBAL_EXTERN spinlock_t GlobalMid_Lock; /* protects above & list operations */ | 757 | GLOBAL_EXTERN spinlock_t GlobalMid_Lock; /* protects above & list operations */ |
748 | /* on midQ entries */ | 758 | /* on midQ entries */ |
749 | GLOBAL_EXTERN char Local_System_Name[15]; | ||
750 | |||
751 | /* | 759 | /* |
752 | * Global counters, updated atomically | 760 | * Global counters, updated atomically |
753 | */ | 761 | */ |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 7ed69b6b5fe6..e6d1481b16c1 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -54,7 +54,8 @@ do { \ | |||
54 | __func__, curr_xid, (int)rc); \ | 54 | __func__, curr_xid, (int)rc); \ |
55 | } while (0) | 55 | } while (0) |
56 | extern char *build_path_from_dentry(struct dentry *); | 56 | extern char *build_path_from_dentry(struct dentry *); |
57 | extern char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb); | 57 | extern char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb, |
58 | struct cifsTconInfo *tcon); | ||
58 | extern char *build_wildcard_path_from_dentry(struct dentry *direntry); | 59 | extern char *build_wildcard_path_from_dentry(struct dentry *direntry); |
59 | extern char *cifs_compose_mount_options(const char *sb_mountdata, | 60 | extern char *cifs_compose_mount_options(const char *sb_mountdata, |
60 | const char *fullpath, const struct dfs_info3_param *ref, | 61 | const char *fullpath, const struct dfs_info3_param *ref, |
@@ -79,9 +80,7 @@ extern bool is_valid_oplock_break(struct smb_hdr *smb, | |||
79 | struct TCP_Server_Info *); | 80 | struct TCP_Server_Info *); |
80 | extern bool is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof); | 81 | extern bool is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof); |
81 | extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, bool); | 82 | extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, bool); |
82 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
83 | extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool); | 83 | extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool); |
84 | #endif | ||
85 | extern unsigned int smbCalcSize(struct smb_hdr *ptr); | 84 | extern unsigned int smbCalcSize(struct smb_hdr *ptr); |
86 | extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr); | 85 | extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr); |
87 | extern int decode_negTokenInit(unsigned char *security_blob, int length, | 86 | extern int decode_negTokenInit(unsigned char *security_blob, int length, |
@@ -130,10 +129,12 @@ extern int cifs_get_file_info_unix(struct file *filp); | |||
130 | extern int cifs_get_inode_info_unix(struct inode **pinode, | 129 | extern int cifs_get_inode_info_unix(struct inode **pinode, |
131 | const unsigned char *search_path, | 130 | const unsigned char *search_path, |
132 | struct super_block *sb, int xid); | 131 | struct super_block *sb, int xid); |
133 | extern void cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, | 132 | extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, |
134 | struct cifs_fattr *fattr, struct inode *inode, | 133 | struct cifs_fattr *fattr, struct inode *inode, |
135 | const char *path, const __u16 *pfid); | 134 | const char *path, const __u16 *pfid); |
136 | extern int mode_to_acl(struct inode *inode, const char *path, __u64); | 135 | extern int mode_to_cifs_acl(struct inode *inode, const char *path, __u64); |
136 | extern struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *, struct inode *, | ||
137 | const char *, u32 *); | ||
137 | 138 | ||
138 | extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *, | 139 | extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *, |
139 | const char *); | 140 | const char *); |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 2f2632b6df5a..67acfb3acad2 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -2478,95 +2478,6 @@ querySymLinkRetry: | |||
2478 | } | 2478 | } |
2479 | 2479 | ||
2480 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 2480 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
2481 | /* Initialize NT TRANSACT SMB into small smb request buffer. | ||
2482 | This assumes that all NT TRANSACTS that we init here have | ||
2483 | total parm and data under about 400 bytes (to fit in small cifs | ||
2484 | buffer size), which is the case so far, it easily fits. NB: | ||
2485 | Setup words themselves and ByteCount | ||
2486 | MaxSetupCount (size of returned setup area) and | ||
2487 | MaxParameterCount (returned parms size) must be set by caller */ | ||
2488 | static int | ||
2489 | smb_init_nttransact(const __u16 sub_command, const int setup_count, | ||
2490 | const int parm_len, struct cifsTconInfo *tcon, | ||
2491 | void **ret_buf) | ||
2492 | { | ||
2493 | int rc; | ||
2494 | __u32 temp_offset; | ||
2495 | struct smb_com_ntransact_req *pSMB; | ||
2496 | |||
2497 | rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon, | ||
2498 | (void **)&pSMB); | ||
2499 | if (rc) | ||
2500 | return rc; | ||
2501 | *ret_buf = (void *)pSMB; | ||
2502 | pSMB->Reserved = 0; | ||
2503 | pSMB->TotalParameterCount = cpu_to_le32(parm_len); | ||
2504 | pSMB->TotalDataCount = 0; | ||
2505 | pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf - | ||
2506 | MAX_CIFS_HDR_SIZE) & 0xFFFFFF00); | ||
2507 | pSMB->ParameterCount = pSMB->TotalParameterCount; | ||
2508 | pSMB->DataCount = pSMB->TotalDataCount; | ||
2509 | temp_offset = offsetof(struct smb_com_ntransact_req, Parms) + | ||
2510 | (setup_count * 2) - 4 /* for rfc1001 length itself */; | ||
2511 | pSMB->ParameterOffset = cpu_to_le32(temp_offset); | ||
2512 | pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len); | ||
2513 | pSMB->SetupCount = setup_count; /* no need to le convert byte fields */ | ||
2514 | pSMB->SubCommand = cpu_to_le16(sub_command); | ||
2515 | return 0; | ||
2516 | } | ||
2517 | |||
2518 | static int | ||
2519 | validate_ntransact(char *buf, char **ppparm, char **ppdata, | ||
2520 | __u32 *pparmlen, __u32 *pdatalen) | ||
2521 | { | ||
2522 | char *end_of_smb; | ||
2523 | __u32 data_count, data_offset, parm_count, parm_offset; | ||
2524 | struct smb_com_ntransact_rsp *pSMBr; | ||
2525 | |||
2526 | *pdatalen = 0; | ||
2527 | *pparmlen = 0; | ||
2528 | |||
2529 | if (buf == NULL) | ||
2530 | return -EINVAL; | ||
2531 | |||
2532 | pSMBr = (struct smb_com_ntransact_rsp *)buf; | ||
2533 | |||
2534 | /* ByteCount was converted from little endian in SendReceive */ | ||
2535 | end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount + | ||
2536 | (char *)&pSMBr->ByteCount; | ||
2537 | |||
2538 | data_offset = le32_to_cpu(pSMBr->DataOffset); | ||
2539 | data_count = le32_to_cpu(pSMBr->DataCount); | ||
2540 | parm_offset = le32_to_cpu(pSMBr->ParameterOffset); | ||
2541 | parm_count = le32_to_cpu(pSMBr->ParameterCount); | ||
2542 | |||
2543 | *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset; | ||
2544 | *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset; | ||
2545 | |||
2546 | /* should we also check that parm and data areas do not overlap? */ | ||
2547 | if (*ppparm > end_of_smb) { | ||
2548 | cFYI(1, "parms start after end of smb"); | ||
2549 | return -EINVAL; | ||
2550 | } else if (parm_count + *ppparm > end_of_smb) { | ||
2551 | cFYI(1, "parm end after end of smb"); | ||
2552 | return -EINVAL; | ||
2553 | } else if (*ppdata > end_of_smb) { | ||
2554 | cFYI(1, "data starts after end of smb"); | ||
2555 | return -EINVAL; | ||
2556 | } else if (data_count + *ppdata > end_of_smb) { | ||
2557 | cFYI(1, "data %p + count %d (%p) past smb end %p start %p", | ||
2558 | *ppdata, data_count, (data_count + *ppdata), | ||
2559 | end_of_smb, pSMBr); | ||
2560 | return -EINVAL; | ||
2561 | } else if (parm_count + data_count > pSMBr->ByteCount) { | ||
2562 | cFYI(1, "parm count and data count larger than SMB"); | ||
2563 | return -EINVAL; | ||
2564 | } | ||
2565 | *pdatalen = data_count; | ||
2566 | *pparmlen = parm_count; | ||
2567 | return 0; | ||
2568 | } | ||
2569 | |||
2570 | int | 2481 | int |
2571 | CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, | 2482 | CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, |
2572 | const unsigned char *searchName, | 2483 | const unsigned char *searchName, |
@@ -3056,7 +2967,97 @@ GetExtAttrOut: | |||
3056 | 2967 | ||
3057 | #endif /* CONFIG_POSIX */ | 2968 | #endif /* CONFIG_POSIX */ |
3058 | 2969 | ||
3059 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 2970 | #ifdef CONFIG_CIFS_ACL |
2971 | /* | ||
2972 | * Initialize NT TRANSACT SMB into small smb request buffer. This assumes that | ||
2973 | * all NT TRANSACTS that we init here have total parm and data under about 400 | ||
2974 | * bytes (to fit in small cifs buffer size), which is the case so far, it | ||
2975 | * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of | ||
2976 | * returned setup area) and MaxParameterCount (returned parms size) must be set | ||
2977 | * by caller | ||
2978 | */ | ||
2979 | static int | ||
2980 | smb_init_nttransact(const __u16 sub_command, const int setup_count, | ||
2981 | const int parm_len, struct cifsTconInfo *tcon, | ||
2982 | void **ret_buf) | ||
2983 | { | ||
2984 | int rc; | ||
2985 | __u32 temp_offset; | ||
2986 | struct smb_com_ntransact_req *pSMB; | ||
2987 | |||
2988 | rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon, | ||
2989 | (void **)&pSMB); | ||
2990 | if (rc) | ||
2991 | return rc; | ||
2992 | *ret_buf = (void *)pSMB; | ||
2993 | pSMB->Reserved = 0; | ||
2994 | pSMB->TotalParameterCount = cpu_to_le32(parm_len); | ||
2995 | pSMB->TotalDataCount = 0; | ||
2996 | pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf - | ||
2997 | MAX_CIFS_HDR_SIZE) & 0xFFFFFF00); | ||
2998 | pSMB->ParameterCount = pSMB->TotalParameterCount; | ||
2999 | pSMB->DataCount = pSMB->TotalDataCount; | ||
3000 | temp_offset = offsetof(struct smb_com_ntransact_req, Parms) + | ||
3001 | (setup_count * 2) - 4 /* for rfc1001 length itself */; | ||
3002 | pSMB->ParameterOffset = cpu_to_le32(temp_offset); | ||
3003 | pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len); | ||
3004 | pSMB->SetupCount = setup_count; /* no need to le convert byte fields */ | ||
3005 | pSMB->SubCommand = cpu_to_le16(sub_command); | ||
3006 | return 0; | ||
3007 | } | ||
3008 | |||
3009 | static int | ||
3010 | validate_ntransact(char *buf, char **ppparm, char **ppdata, | ||
3011 | __u32 *pparmlen, __u32 *pdatalen) | ||
3012 | { | ||
3013 | char *end_of_smb; | ||
3014 | __u32 data_count, data_offset, parm_count, parm_offset; | ||
3015 | struct smb_com_ntransact_rsp *pSMBr; | ||
3016 | |||
3017 | *pdatalen = 0; | ||
3018 | *pparmlen = 0; | ||
3019 | |||
3020 | if (buf == NULL) | ||
3021 | return -EINVAL; | ||
3022 | |||
3023 | pSMBr = (struct smb_com_ntransact_rsp *)buf; | ||
3024 | |||
3025 | /* ByteCount was converted from little endian in SendReceive */ | ||
3026 | end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount + | ||
3027 | (char *)&pSMBr->ByteCount; | ||
3028 | |||
3029 | data_offset = le32_to_cpu(pSMBr->DataOffset); | ||
3030 | data_count = le32_to_cpu(pSMBr->DataCount); | ||
3031 | parm_offset = le32_to_cpu(pSMBr->ParameterOffset); | ||
3032 | parm_count = le32_to_cpu(pSMBr->ParameterCount); | ||
3033 | |||
3034 | *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset; | ||
3035 | *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset; | ||
3036 | |||
3037 | /* should we also check that parm and data areas do not overlap? */ | ||
3038 | if (*ppparm > end_of_smb) { | ||
3039 | cFYI(1, "parms start after end of smb"); | ||
3040 | return -EINVAL; | ||
3041 | } else if (parm_count + *ppparm > end_of_smb) { | ||
3042 | cFYI(1, "parm end after end of smb"); | ||
3043 | return -EINVAL; | ||
3044 | } else if (*ppdata > end_of_smb) { | ||
3045 | cFYI(1, "data starts after end of smb"); | ||
3046 | return -EINVAL; | ||
3047 | } else if (data_count + *ppdata > end_of_smb) { | ||
3048 | cFYI(1, "data %p + count %d (%p) past smb end %p start %p", | ||
3049 | *ppdata, data_count, (data_count + *ppdata), | ||
3050 | end_of_smb, pSMBr); | ||
3051 | return -EINVAL; | ||
3052 | } else if (parm_count + data_count > pSMBr->ByteCount) { | ||
3053 | cFYI(1, "parm count and data count larger than SMB"); | ||
3054 | return -EINVAL; | ||
3055 | } | ||
3056 | *pdatalen = data_count; | ||
3057 | *pparmlen = parm_count; | ||
3058 | return 0; | ||
3059 | } | ||
3060 | |||
3060 | /* Get Security Descriptor (by handle) from remote server for a file or dir */ | 3061 | /* Get Security Descriptor (by handle) from remote server for a file or dir */ |
3061 | int | 3062 | int |
3062 | CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, | 3063 | CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, |
@@ -3214,7 +3215,7 @@ setCifsAclRetry: | |||
3214 | return (rc); | 3215 | return (rc); |
3215 | } | 3216 | } |
3216 | 3217 | ||
3217 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | 3218 | #endif /* CONFIG_CIFS_ACL */ |
3218 | 3219 | ||
3219 | /* Legacy Query Path Information call for lookup to old servers such | 3220 | /* Legacy Query Path Information call for lookup to old servers such |
3220 | as Win9x/WinME */ | 3221 | as Win9x/WinME */ |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 251a17c03545..cc1a8604a790 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -105,6 +105,7 @@ struct smb_vol { | |||
105 | unsigned int wsize; | 105 | unsigned int wsize; |
106 | bool sockopt_tcp_nodelay:1; | 106 | bool sockopt_tcp_nodelay:1; |
107 | unsigned short int port; | 107 | unsigned short int port; |
108 | unsigned long actimeo; /* attribute cache timeout (jiffies) */ | ||
108 | char *prepath; | 109 | char *prepath; |
109 | struct sockaddr_storage srcaddr; /* allow binding to a local IP */ | 110 | struct sockaddr_storage srcaddr; /* allow binding to a local IP */ |
110 | struct nls_table *local_nls; | 111 | struct nls_table *local_nls; |
@@ -806,23 +807,20 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
806 | short int override_gid = -1; | 807 | short int override_gid = -1; |
807 | bool uid_specified = false; | 808 | bool uid_specified = false; |
808 | bool gid_specified = false; | 809 | bool gid_specified = false; |
810 | char *nodename = utsname()->nodename; | ||
809 | 811 | ||
810 | separator[0] = ','; | 812 | separator[0] = ','; |
811 | separator[1] = 0; | 813 | separator[1] = 0; |
812 | 814 | ||
813 | if (Local_System_Name[0] != 0) | 815 | /* |
814 | memcpy(vol->source_rfc1001_name, Local_System_Name, 15); | 816 | * does not have to be perfect mapping since field is |
815 | else { | 817 | * informational, only used for servers that do not support |
816 | char *nodename = utsname()->nodename; | 818 | * port 445 and it can be overridden at mount time |
817 | int n = strnlen(nodename, 15); | 819 | */ |
818 | memset(vol->source_rfc1001_name, 0x20, 15); | 820 | memset(vol->source_rfc1001_name, 0x20, 15); |
819 | for (i = 0; i < n; i++) { | 821 | for (i = 0; i < strnlen(nodename, 15); i++) |
820 | /* does not have to be perfect mapping since field is | 822 | vol->source_rfc1001_name[i] = toupper(nodename[i]); |
821 | informational, only used for servers that do not support | 823 | |
822 | port 445 and it can be overridden at mount time */ | ||
823 | vol->source_rfc1001_name[i] = toupper(nodename[i]); | ||
824 | } | ||
825 | } | ||
826 | vol->source_rfc1001_name[15] = 0; | 824 | vol->source_rfc1001_name[15] = 0; |
827 | /* null target name indicates to use *SMBSERVR default called name | 825 | /* null target name indicates to use *SMBSERVR default called name |
828 | if we end up sending RFC1001 session initialize */ | 826 | if we end up sending RFC1001 session initialize */ |
@@ -840,6 +838,8 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
840 | /* default to using server inode numbers where available */ | 838 | /* default to using server inode numbers where available */ |
841 | vol->server_ino = 1; | 839 | vol->server_ino = 1; |
842 | 840 | ||
841 | vol->actimeo = CIFS_DEF_ACTIMEO; | ||
842 | |||
843 | if (!options) | 843 | if (!options) |
844 | return 1; | 844 | return 1; |
845 | 845 | ||
@@ -1214,6 +1214,16 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
1214 | printk(KERN_WARNING "CIFS: server net" | 1214 | printk(KERN_WARNING "CIFS: server net" |
1215 | "biosname longer than 15 truncated.\n"); | 1215 | "biosname longer than 15 truncated.\n"); |
1216 | } | 1216 | } |
1217 | } else if (strnicmp(data, "actimeo", 7) == 0) { | ||
1218 | if (value && *value) { | ||
1219 | vol->actimeo = HZ * simple_strtoul(value, | ||
1220 | &value, 0); | ||
1221 | if (vol->actimeo > CIFS_MAX_ACTIMEO) { | ||
1222 | cERROR(1, "CIFS: attribute cache" | ||
1223 | "timeout too large"); | ||
1224 | return 1; | ||
1225 | } | ||
1226 | } | ||
1217 | } else if (strnicmp(data, "credentials", 4) == 0) { | 1227 | } else if (strnicmp(data, "credentials", 4) == 0) { |
1218 | /* ignore */ | 1228 | /* ignore */ |
1219 | } else if (strnicmp(data, "version", 3) == 0) { | 1229 | } else if (strnicmp(data, "version", 3) == 0) { |
@@ -1352,6 +1362,11 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
1352 | "supported. Instead set " | 1362 | "supported. Instead set " |
1353 | "/proc/fs/cifs/LookupCacheEnabled to 0\n"); | 1363 | "/proc/fs/cifs/LookupCacheEnabled to 0\n"); |
1354 | } else if (strnicmp(data, "fsc", 3) == 0) { | 1364 | } else if (strnicmp(data, "fsc", 3) == 0) { |
1365 | #ifndef CONFIG_CIFS_FSCACHE | ||
1366 | cERROR(1, "FS-Cache support needs CONFIG_CIFS_FSCACHE" | ||
1367 | "kernel config option set"); | ||
1368 | return 1; | ||
1369 | #endif | ||
1355 | vol->fsc = true; | 1370 | vol->fsc = true; |
1356 | } else if (strnicmp(data, "mfsymlinks", 10) == 0) { | 1371 | } else if (strnicmp(data, "mfsymlinks", 10) == 0) { |
1357 | vol->mfsymlinks = true; | 1372 | vol->mfsymlinks = true; |
@@ -2566,6 +2581,8 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info, | |||
2566 | cFYI(1, "file mode: 0x%x dir mode: 0x%x", | 2581 | cFYI(1, "file mode: 0x%x dir mode: 0x%x", |
2567 | cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode); | 2582 | cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode); |
2568 | 2583 | ||
2584 | cifs_sb->actimeo = pvolume_info->actimeo; | ||
2585 | |||
2569 | if (pvolume_info->noperm) | 2586 | if (pvolume_info->noperm) |
2570 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM; | 2587 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM; |
2571 | if (pvolume_info->setuids) | 2588 | if (pvolume_info->setuids) |
@@ -2816,13 +2833,13 @@ remote_path_check: | |||
2816 | /* check if a whole path (including prepath) is not remote */ | 2833 | /* check if a whole path (including prepath) is not remote */ |
2817 | if (!rc && cifs_sb->prepathlen && tcon) { | 2834 | if (!rc && cifs_sb->prepathlen && tcon) { |
2818 | /* build_path_to_root works only when we have a valid tcon */ | 2835 | /* build_path_to_root works only when we have a valid tcon */ |
2819 | full_path = cifs_build_path_to_root(cifs_sb); | 2836 | full_path = cifs_build_path_to_root(cifs_sb, tcon); |
2820 | if (full_path == NULL) { | 2837 | if (full_path == NULL) { |
2821 | rc = -ENOMEM; | 2838 | rc = -ENOMEM; |
2822 | goto mount_fail_check; | 2839 | goto mount_fail_check; |
2823 | } | 2840 | } |
2824 | rc = is_path_accessible(xid, tcon, cifs_sb, full_path); | 2841 | rc = is_path_accessible(xid, tcon, cifs_sb, full_path); |
2825 | if (rc != -EREMOTE) { | 2842 | if (rc != 0 && rc != -EREMOTE) { |
2826 | kfree(full_path); | 2843 | kfree(full_path); |
2827 | goto mount_fail_check; | 2844 | goto mount_fail_check; |
2828 | } | 2845 | } |
diff --git a/fs/cifs/dns_resolve.c b/fs/cifs/dns_resolve.c index 0eb87026cad3..548f06230a6d 100644 --- a/fs/cifs/dns_resolve.c +++ b/fs/cifs/dns_resolve.c | |||
@@ -66,7 +66,7 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr) | |||
66 | /* Search for server name delimiter */ | 66 | /* Search for server name delimiter */ |
67 | sep = memchr(hostname, '\\', len); | 67 | sep = memchr(hostname, '\\', len); |
68 | if (sep) | 68 | if (sep) |
69 | len = sep - unc; | 69 | len = sep - hostname; |
70 | else | 70 | else |
71 | cFYI(1, "%s: probably server name is whole unc: %s", | 71 | cFYI(1, "%s: probably server name is whole unc: %s", |
72 | __func__, unc); | 72 | __func__, unc); |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 06c3e83fa387..5a28660ca2b5 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -1108,7 +1108,6 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file, | |||
1108 | return total_written; | 1108 | return total_written; |
1109 | } | 1109 | } |
1110 | 1110 | ||
1111 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
1112 | struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode, | 1111 | struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode, |
1113 | bool fsuid_only) | 1112 | bool fsuid_only) |
1114 | { | 1113 | { |
@@ -1142,7 +1141,6 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode, | |||
1142 | spin_unlock(&cifs_file_list_lock); | 1141 | spin_unlock(&cifs_file_list_lock); |
1143 | return NULL; | 1142 | return NULL; |
1144 | } | 1143 | } |
1145 | #endif | ||
1146 | 1144 | ||
1147 | struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode, | 1145 | struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode, |
1148 | bool fsuid_only) | 1146 | bool fsuid_only) |
@@ -2271,8 +2269,10 @@ void cifs_oplock_break_get(struct cifsFileInfo *cfile) | |||
2271 | 2269 | ||
2272 | void cifs_oplock_break_put(struct cifsFileInfo *cfile) | 2270 | void cifs_oplock_break_put(struct cifsFileInfo *cfile) |
2273 | { | 2271 | { |
2272 | struct super_block *sb = cfile->dentry->d_sb; | ||
2273 | |||
2274 | cifsFileInfo_put(cfile); | 2274 | cifsFileInfo_put(cfile); |
2275 | cifs_sb_deactive(cfile->dentry->d_sb); | 2275 | cifs_sb_deactive(sb); |
2276 | } | 2276 | } |
2277 | 2277 | ||
2278 | const struct address_space_operations cifs_addr_ops = { | 2278 | const struct address_space_operations cifs_addr_ops = { |
diff --git a/fs/cifs/fscache.c b/fs/cifs/fscache.c index a2ad94efcfe6..297a43d0ff7f 100644 --- a/fs/cifs/fscache.c +++ b/fs/cifs/fscache.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * fs/cifs/fscache.c - CIFS filesystem cache interface | 2 | * fs/cifs/fscache.c - CIFS filesystem cache interface |
3 | * | 3 | * |
4 | * Copyright (c) 2010 Novell, Inc. | 4 | * Copyright (c) 2010 Novell, Inc. |
5 | * Author(s): Suresh Jayaraman (sjayaraman@suse.de> | 5 | * Author(s): Suresh Jayaraman <sjayaraman@suse.de> |
6 | * | 6 | * |
7 | * This library is free software; you can redistribute it and/or modify | 7 | * This library is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU Lesser General Public License as published | 8 | * it under the terms of the GNU Lesser General Public License as published |
@@ -67,10 +67,12 @@ static void cifs_fscache_enable_inode_cookie(struct inode *inode) | |||
67 | if (cifsi->fscache) | 67 | if (cifsi->fscache) |
68 | return; | 68 | return; |
69 | 69 | ||
70 | cifsi->fscache = fscache_acquire_cookie(tcon->fscache, | 70 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE) { |
71 | cifsi->fscache = fscache_acquire_cookie(tcon->fscache, | ||
71 | &cifs_fscache_inode_object_def, cifsi); | 72 | &cifs_fscache_inode_object_def, cifsi); |
72 | cFYI(1, "CIFS: got FH cookie (0x%p/0x%p)", tcon->fscache, | 73 | cFYI(1, "CIFS: got FH cookie (0x%p/0x%p)", tcon->fscache, |
73 | cifsi->fscache); | 74 | cifsi->fscache); |
75 | } | ||
74 | } | 76 | } |
75 | 77 | ||
76 | void cifs_fscache_release_inode_cookie(struct inode *inode) | 78 | void cifs_fscache_release_inode_cookie(struct inode *inode) |
@@ -101,10 +103,8 @@ void cifs_fscache_set_inode_cookie(struct inode *inode, struct file *filp) | |||
101 | { | 103 | { |
102 | if ((filp->f_flags & O_ACCMODE) != O_RDONLY) | 104 | if ((filp->f_flags & O_ACCMODE) != O_RDONLY) |
103 | cifs_fscache_disable_inode_cookie(inode); | 105 | cifs_fscache_disable_inode_cookie(inode); |
104 | else { | 106 | else |
105 | cifs_fscache_enable_inode_cookie(inode); | 107 | cifs_fscache_enable_inode_cookie(inode); |
106 | cFYI(1, "CIFS: fscache inode cookie set"); | ||
107 | } | ||
108 | } | 108 | } |
109 | 109 | ||
110 | void cifs_fscache_reset_inode_cookie(struct inode *inode) | 110 | void cifs_fscache_reset_inode_cookie(struct inode *inode) |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index ef3a55bf86b6..589f3e3f6e00 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -686,13 +686,18 @@ int cifs_get_inode_info(struct inode **pinode, | |||
686 | cFYI(1, "cifs_sfu_type failed: %d", tmprc); | 686 | cFYI(1, "cifs_sfu_type failed: %d", tmprc); |
687 | } | 687 | } |
688 | 688 | ||
689 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 689 | #ifdef CONFIG_CIFS_ACL |
690 | /* fill in 0777 bits from ACL */ | 690 | /* fill in 0777 bits from ACL */ |
691 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { | 691 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { |
692 | cFYI(1, "Getting mode bits from ACL"); | 692 | rc = cifs_acl_to_fattr(cifs_sb, &fattr, *pinode, full_path, |
693 | cifs_acl_to_fattr(cifs_sb, &fattr, *pinode, full_path, pfid); | 693 | pfid); |
694 | if (rc) { | ||
695 | cFYI(1, "%s: Getting ACL failed with error: %d", | ||
696 | __func__, rc); | ||
697 | goto cgii_exit; | ||
698 | } | ||
694 | } | 699 | } |
695 | #endif | 700 | #endif /* CONFIG_CIFS_ACL */ |
696 | 701 | ||
697 | /* fill in remaining high mode bits e.g. SUID, VTX */ | 702 | /* fill in remaining high mode bits e.g. SUID, VTX */ |
698 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) | 703 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) |
@@ -723,12 +728,12 @@ static const struct inode_operations cifs_ipc_inode_ops = { | |||
723 | .lookup = cifs_lookup, | 728 | .lookup = cifs_lookup, |
724 | }; | 729 | }; |
725 | 730 | ||
726 | char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb) | 731 | char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb, |
732 | struct cifsTconInfo *tcon) | ||
727 | { | 733 | { |
728 | int pplen = cifs_sb->prepathlen; | 734 | int pplen = cifs_sb->prepathlen; |
729 | int dfsplen; | 735 | int dfsplen; |
730 | char *full_path = NULL; | 736 | char *full_path = NULL; |
731 | struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb); | ||
732 | 737 | ||
733 | /* if no prefix path, simply set path to the root of share to "" */ | 738 | /* if no prefix path, simply set path to the root of share to "" */ |
734 | if (pplen == 0) { | 739 | if (pplen == 0) { |
@@ -870,7 +875,7 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) | |||
870 | char *full_path; | 875 | char *full_path; |
871 | struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb); | 876 | struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb); |
872 | 877 | ||
873 | full_path = cifs_build_path_to_root(cifs_sb); | 878 | full_path = cifs_build_path_to_root(cifs_sb, tcon); |
874 | if (full_path == NULL) | 879 | if (full_path == NULL) |
875 | return ERR_PTR(-ENOMEM); | 880 | return ERR_PTR(-ENOMEM); |
876 | 881 | ||
@@ -881,8 +886,10 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) | |||
881 | rc = cifs_get_inode_info(&inode, full_path, NULL, sb, | 886 | rc = cifs_get_inode_info(&inode, full_path, NULL, sb, |
882 | xid, NULL); | 887 | xid, NULL); |
883 | 888 | ||
884 | if (!inode) | 889 | if (!inode) { |
885 | return ERR_PTR(rc); | 890 | inode = ERR_PTR(rc); |
891 | goto out; | ||
892 | } | ||
886 | 893 | ||
887 | #ifdef CONFIG_CIFS_FSCACHE | 894 | #ifdef CONFIG_CIFS_FSCACHE |
888 | /* populate tcon->resource_id */ | 895 | /* populate tcon->resource_id */ |
@@ -898,13 +905,11 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) | |||
898 | inode->i_uid = cifs_sb->mnt_uid; | 905 | inode->i_uid = cifs_sb->mnt_uid; |
899 | inode->i_gid = cifs_sb->mnt_gid; | 906 | inode->i_gid = cifs_sb->mnt_gid; |
900 | } else if (rc) { | 907 | } else if (rc) { |
901 | kfree(full_path); | ||
902 | _FreeXid(xid); | ||
903 | iget_failed(inode); | 908 | iget_failed(inode); |
904 | return ERR_PTR(rc); | 909 | inode = ERR_PTR(rc); |
905 | } | 910 | } |
906 | 911 | ||
907 | 912 | out: | |
908 | kfree(full_path); | 913 | kfree(full_path); |
909 | /* can not call macro FreeXid here since in a void func | 914 | /* can not call macro FreeXid here since in a void func |
910 | * TODO: This is no longer true | 915 | * TODO: This is no longer true |
@@ -1648,6 +1653,7 @@ static bool | |||
1648 | cifs_inode_needs_reval(struct inode *inode) | 1653 | cifs_inode_needs_reval(struct inode *inode) |
1649 | { | 1654 | { |
1650 | struct cifsInodeInfo *cifs_i = CIFS_I(inode); | 1655 | struct cifsInodeInfo *cifs_i = CIFS_I(inode); |
1656 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | ||
1651 | 1657 | ||
1652 | if (cifs_i->clientCanCacheRead) | 1658 | if (cifs_i->clientCanCacheRead) |
1653 | return false; | 1659 | return false; |
@@ -1658,19 +1664,21 @@ cifs_inode_needs_reval(struct inode *inode) | |||
1658 | if (cifs_i->time == 0) | 1664 | if (cifs_i->time == 0) |
1659 | return true; | 1665 | return true; |
1660 | 1666 | ||
1661 | /* FIXME: the actimeo should be tunable */ | 1667 | if (!time_in_range(jiffies, cifs_i->time, |
1662 | if (time_after_eq(jiffies, cifs_i->time + HZ)) | 1668 | cifs_i->time + cifs_sb->actimeo)) |
1663 | return true; | 1669 | return true; |
1664 | 1670 | ||
1665 | /* hardlinked files w/ noserverino get "special" treatment */ | 1671 | /* hardlinked files w/ noserverino get "special" treatment */ |
1666 | if (!(CIFS_SB(inode->i_sb)->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) && | 1672 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) && |
1667 | S_ISREG(inode->i_mode) && inode->i_nlink != 1) | 1673 | S_ISREG(inode->i_mode) && inode->i_nlink != 1) |
1668 | return true; | 1674 | return true; |
1669 | 1675 | ||
1670 | return false; | 1676 | return false; |
1671 | } | 1677 | } |
1672 | 1678 | ||
1673 | /* check invalid_mapping flag and zap the cache if it's set */ | 1679 | /* |
1680 | * Zap the cache. Called when invalid_mapping flag is set. | ||
1681 | */ | ||
1674 | static void | 1682 | static void |
1675 | cifs_invalidate_mapping(struct inode *inode) | 1683 | cifs_invalidate_mapping(struct inode *inode) |
1676 | { | 1684 | { |
@@ -2114,11 +2122,16 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) | |||
2114 | 2122 | ||
2115 | if (attrs->ia_valid & ATTR_MODE) { | 2123 | if (attrs->ia_valid & ATTR_MODE) { |
2116 | rc = 0; | 2124 | rc = 0; |
2117 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 2125 | #ifdef CONFIG_CIFS_ACL |
2118 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) | 2126 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { |
2119 | rc = mode_to_acl(inode, full_path, mode); | 2127 | rc = mode_to_cifs_acl(inode, full_path, mode); |
2120 | else | 2128 | if (rc) { |
2121 | #endif | 2129 | cFYI(1, "%s: Setting ACL failed with error: %d", |
2130 | __func__, rc); | ||
2131 | goto cifs_setattr_exit; | ||
2132 | } | ||
2133 | } else | ||
2134 | #endif /* CONFIG_CIFS_ACL */ | ||
2122 | if (((mode & S_IWUGO) == 0) && | 2135 | if (((mode & S_IWUGO) == 0) && |
2123 | (cifsInode->cifsAttrs & ATTR_READONLY) == 0) { | 2136 | (cifsInode->cifsAttrs & ATTR_READONLY) == 0) { |
2124 | 2137 | ||
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index ef7bb7b50f58..a73eb9f4bdaf 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
@@ -226,26 +226,29 @@ static int initiate_cifs_search(const int xid, struct file *file) | |||
226 | char *full_path = NULL; | 226 | char *full_path = NULL; |
227 | struct cifsFileInfo *cifsFile; | 227 | struct cifsFileInfo *cifsFile; |
228 | struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | 228 | struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); |
229 | struct tcon_link *tlink; | 229 | struct tcon_link *tlink = NULL; |
230 | struct cifsTconInfo *pTcon; | 230 | struct cifsTconInfo *pTcon; |
231 | 231 | ||
232 | tlink = cifs_sb_tlink(cifs_sb); | ||
233 | if (IS_ERR(tlink)) | ||
234 | return PTR_ERR(tlink); | ||
235 | pTcon = tlink_tcon(tlink); | ||
236 | |||
237 | if (file->private_data == NULL) | ||
238 | file->private_data = | ||
239 | kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); | ||
240 | if (file->private_data == NULL) { | 232 | if (file->private_data == NULL) { |
241 | rc = -ENOMEM; | 233 | tlink = cifs_sb_tlink(cifs_sb); |
242 | goto error_exit; | 234 | if (IS_ERR(tlink)) |
235 | return PTR_ERR(tlink); | ||
236 | |||
237 | cifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); | ||
238 | if (cifsFile == NULL) { | ||
239 | rc = -ENOMEM; | ||
240 | goto error_exit; | ||
241 | } | ||
242 | file->private_data = cifsFile; | ||
243 | cifsFile->tlink = cifs_get_tlink(tlink); | ||
244 | pTcon = tlink_tcon(tlink); | ||
245 | } else { | ||
246 | cifsFile = file->private_data; | ||
247 | pTcon = tlink_tcon(cifsFile->tlink); | ||
243 | } | 248 | } |
244 | 249 | ||
245 | cifsFile = file->private_data; | ||
246 | cifsFile->invalidHandle = true; | 250 | cifsFile->invalidHandle = true; |
247 | cifsFile->srch_inf.endOfSearch = false; | 251 | cifsFile->srch_inf.endOfSearch = false; |
248 | cifsFile->tlink = cifs_get_tlink(tlink); | ||
249 | 252 | ||
250 | full_path = build_path_from_dentry(file->f_path.dentry); | 253 | full_path = build_path_from_dentry(file->f_path.dentry); |
251 | if (full_path == NULL) { | 254 | if (full_path == NULL) { |
@@ -756,18 +759,6 @@ static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir, | |||
756 | rc = filldir(direntry, qstring.name, qstring.len, file->f_pos, | 759 | rc = filldir(direntry, qstring.name, qstring.len, file->f_pos, |
757 | ino, fattr.cf_dtype); | 760 | ino, fattr.cf_dtype); |
758 | 761 | ||
759 | /* | ||
760 | * we can not return filldir errors to the caller since they are | ||
761 | * "normal" when the stat blocksize is too small - we return remapped | ||
762 | * error instead | ||
763 | * | ||
764 | * FIXME: This looks bogus. filldir returns -EOVERFLOW in the above | ||
765 | * case already. Why should we be clobbering other errors from it? | ||
766 | */ | ||
767 | if (rc) { | ||
768 | cFYI(1, "filldir rc = %d", rc); | ||
769 | rc = -EOVERFLOW; | ||
770 | } | ||
771 | dput(tmp_dentry); | 762 | dput(tmp_dentry); |
772 | return rc; | 763 | return rc; |
773 | } | 764 | } |
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index a264b744bb41..eae2a1491608 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c | |||
@@ -30,10 +30,11 @@ | |||
30 | 30 | ||
31 | #define MAX_EA_VALUE_SIZE 65535 | 31 | #define MAX_EA_VALUE_SIZE 65535 |
32 | #define CIFS_XATTR_DOS_ATTRIB "user.DosAttrib" | 32 | #define CIFS_XATTR_DOS_ATTRIB "user.DosAttrib" |
33 | #define CIFS_XATTR_CIFS_ACL "system.cifs_acl" | ||
33 | #define CIFS_XATTR_USER_PREFIX "user." | 34 | #define CIFS_XATTR_USER_PREFIX "user." |
34 | #define CIFS_XATTR_SYSTEM_PREFIX "system." | 35 | #define CIFS_XATTR_SYSTEM_PREFIX "system." |
35 | #define CIFS_XATTR_OS2_PREFIX "os2." | 36 | #define CIFS_XATTR_OS2_PREFIX "os2." |
36 | #define CIFS_XATTR_SECURITY_PREFIX ".security" | 37 | #define CIFS_XATTR_SECURITY_PREFIX "security." |
37 | #define CIFS_XATTR_TRUSTED_PREFIX "trusted." | 38 | #define CIFS_XATTR_TRUSTED_PREFIX "trusted." |
38 | #define XATTR_TRUSTED_PREFIX_LEN 8 | 39 | #define XATTR_TRUSTED_PREFIX_LEN 8 |
39 | #define XATTR_SECURITY_PREFIX_LEN 9 | 40 | #define XATTR_SECURITY_PREFIX_LEN 9 |
@@ -277,29 +278,8 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, | |||
277 | cifs_sb->local_nls, | 278 | cifs_sb->local_nls, |
278 | cifs_sb->mnt_cifs_flags & | 279 | cifs_sb->mnt_cifs_flags & |
279 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 280 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
280 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
281 | else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { | ||
282 | __u16 fid; | ||
283 | int oplock = 0; | ||
284 | struct cifs_ntsd *pacl = NULL; | ||
285 | __u32 buflen = 0; | ||
286 | if (experimEnabled) | ||
287 | rc = CIFSSMBOpen(xid, pTcon, full_path, | ||
288 | FILE_OPEN, GENERIC_READ, 0, &fid, | ||
289 | &oplock, NULL, cifs_sb->local_nls, | ||
290 | cifs_sb->mnt_cifs_flags & | ||
291 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
292 | /* else rc is EOPNOTSUPP from above */ | ||
293 | |||
294 | if (rc == 0) { | ||
295 | rc = CIFSSMBGetCIFSACL(xid, pTcon, fid, &pacl, | ||
296 | &buflen); | ||
297 | CIFSSMBClose(xid, pTcon, fid); | ||
298 | } | ||
299 | } | ||
300 | #endif /* EXPERIMENTAL */ | ||
301 | #else | 281 | #else |
302 | cFYI(1, "query POSIX ACL not supported yet"); | 282 | cFYI(1, "Query POSIX ACL not supported yet"); |
303 | #endif /* CONFIG_CIFS_POSIX */ | 283 | #endif /* CONFIG_CIFS_POSIX */ |
304 | } else if (strncmp(ea_name, POSIX_ACL_XATTR_DEFAULT, | 284 | } else if (strncmp(ea_name, POSIX_ACL_XATTR_DEFAULT, |
305 | strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) { | 285 | strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) { |
@@ -311,8 +291,33 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, | |||
311 | cifs_sb->mnt_cifs_flags & | 291 | cifs_sb->mnt_cifs_flags & |
312 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 292 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
313 | #else | 293 | #else |
314 | cFYI(1, "query POSIX default ACL not supported yet"); | 294 | cFYI(1, "Query POSIX default ACL not supported yet"); |
315 | #endif | 295 | #endif /* CONFIG_CIFS_POSIX */ |
296 | } else if (strncmp(ea_name, CIFS_XATTR_CIFS_ACL, | ||
297 | strlen(CIFS_XATTR_CIFS_ACL)) == 0) { | ||
298 | #ifdef CONFIG_CIFS_ACL | ||
299 | u32 acllen; | ||
300 | struct cifs_ntsd *pacl; | ||
301 | |||
302 | pacl = get_cifs_acl(cifs_sb, direntry->d_inode, | ||
303 | full_path, &acllen); | ||
304 | if (IS_ERR(pacl)) { | ||
305 | rc = PTR_ERR(pacl); | ||
306 | cERROR(1, "%s: error %zd getting sec desc", | ||
307 | __func__, rc); | ||
308 | } else { | ||
309 | if (ea_value) { | ||
310 | if (acllen > buf_size) | ||
311 | acllen = -ERANGE; | ||
312 | else | ||
313 | memcpy(ea_value, pacl, acllen); | ||
314 | } | ||
315 | rc = acllen; | ||
316 | kfree(pacl); | ||
317 | } | ||
318 | #else | ||
319 | cFYI(1, "Query CIFS ACL not supported yet"); | ||
320 | #endif /* CONFIG_CIFS_ACL */ | ||
316 | } else if (strncmp(ea_name, | 321 | } else if (strncmp(ea_name, |
317 | CIFS_XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) == 0) { | 322 | CIFS_XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) == 0) { |
318 | cFYI(1, "Trusted xattr namespace not supported yet"); | 323 | cFYI(1, "Trusted xattr namespace not supported yet"); |
diff --git a/fs/compat.c b/fs/compat.c index c580c322fa6b..eb1740ac8c0a 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
@@ -1350,6 +1350,10 @@ static int compat_count(compat_uptr_t __user *argv, int max) | |||
1350 | argv++; | 1350 | argv++; |
1351 | if (i++ >= max) | 1351 | if (i++ >= max) |
1352 | return -E2BIG; | 1352 | return -E2BIG; |
1353 | |||
1354 | if (fatal_signal_pending(current)) | ||
1355 | return -ERESTARTNOHAND; | ||
1356 | cond_resched(); | ||
1353 | } | 1357 | } |
1354 | } | 1358 | } |
1355 | return i; | 1359 | return i; |
@@ -1391,6 +1395,12 @@ static int compat_copy_strings(int argc, compat_uptr_t __user *argv, | |||
1391 | while (len > 0) { | 1395 | while (len > 0) { |
1392 | int offset, bytes_to_copy; | 1396 | int offset, bytes_to_copy; |
1393 | 1397 | ||
1398 | if (fatal_signal_pending(current)) { | ||
1399 | ret = -ERESTARTNOHAND; | ||
1400 | goto out; | ||
1401 | } | ||
1402 | cond_resched(); | ||
1403 | |||
1394 | offset = pos % PAGE_SIZE; | 1404 | offset = pos % PAGE_SIZE; |
1395 | if (offset == 0) | 1405 | if (offset == 0) |
1396 | offset = PAGE_SIZE; | 1406 | offset = PAGE_SIZE; |
@@ -1407,18 +1417,8 @@ static int compat_copy_strings(int argc, compat_uptr_t __user *argv, | |||
1407 | if (!kmapped_page || kpos != (pos & PAGE_MASK)) { | 1417 | if (!kmapped_page || kpos != (pos & PAGE_MASK)) { |
1408 | struct page *page; | 1418 | struct page *page; |
1409 | 1419 | ||
1410 | #ifdef CONFIG_STACK_GROWSUP | 1420 | page = get_arg_page(bprm, pos, 1); |
1411 | ret = expand_stack_downwards(bprm->vma, pos); | 1421 | if (!page) { |
1412 | if (ret < 0) { | ||
1413 | /* We've exceed the stack rlimit. */ | ||
1414 | ret = -E2BIG; | ||
1415 | goto out; | ||
1416 | } | ||
1417 | #endif | ||
1418 | ret = get_user_pages(current, bprm->mm, pos, | ||
1419 | 1, 1, 1, &page, NULL); | ||
1420 | if (ret <= 0) { | ||
1421 | /* We've exceed the stack rlimit. */ | ||
1422 | ret = -E2BIG; | 1422 | ret = -E2BIG; |
1423 | goto out; | 1423 | goto out; |
1424 | } | 1424 | } |
@@ -1539,8 +1539,10 @@ int compat_do_execve(char * filename, | |||
1539 | return retval; | 1539 | return retval; |
1540 | 1540 | ||
1541 | out: | 1541 | out: |
1542 | if (bprm->mm) | 1542 | if (bprm->mm) { |
1543 | acct_arg_size(bprm, 0); | ||
1543 | mmput(bprm->mm); | 1544 | mmput(bprm->mm); |
1545 | } | ||
1544 | 1546 | ||
1545 | out_file: | 1547 | out_file: |
1546 | if (bprm->file) { | 1548 | if (bprm->file) { |
@@ -164,7 +164,26 @@ out: | |||
164 | 164 | ||
165 | #ifdef CONFIG_MMU | 165 | #ifdef CONFIG_MMU |
166 | 166 | ||
167 | static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, | 167 | void acct_arg_size(struct linux_binprm *bprm, unsigned long pages) |
168 | { | ||
169 | struct mm_struct *mm = current->mm; | ||
170 | long diff = (long)(pages - bprm->vma_pages); | ||
171 | |||
172 | if (!mm || !diff) | ||
173 | return; | ||
174 | |||
175 | bprm->vma_pages = pages; | ||
176 | |||
177 | #ifdef SPLIT_RSS_COUNTING | ||
178 | add_mm_counter(mm, MM_ANONPAGES, diff); | ||
179 | #else | ||
180 | spin_lock(&mm->page_table_lock); | ||
181 | add_mm_counter(mm, MM_ANONPAGES, diff); | ||
182 | spin_unlock(&mm->page_table_lock); | ||
183 | #endif | ||
184 | } | ||
185 | |||
186 | struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, | ||
168 | int write) | 187 | int write) |
169 | { | 188 | { |
170 | struct page *page; | 189 | struct page *page; |
@@ -186,6 +205,8 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, | |||
186 | unsigned long size = bprm->vma->vm_end - bprm->vma->vm_start; | 205 | unsigned long size = bprm->vma->vm_end - bprm->vma->vm_start; |
187 | struct rlimit *rlim; | 206 | struct rlimit *rlim; |
188 | 207 | ||
208 | acct_arg_size(bprm, size / PAGE_SIZE); | ||
209 | |||
189 | /* | 210 | /* |
190 | * We've historically supported up to 32 pages (ARG_MAX) | 211 | * We've historically supported up to 32 pages (ARG_MAX) |
191 | * of argument strings even with small stacks | 212 | * of argument strings even with small stacks |
@@ -254,6 +275,11 @@ static int __bprm_mm_init(struct linux_binprm *bprm) | |||
254 | vma->vm_flags = VM_STACK_FLAGS | VM_STACK_INCOMPLETE_SETUP; | 275 | vma->vm_flags = VM_STACK_FLAGS | VM_STACK_INCOMPLETE_SETUP; |
255 | vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); | 276 | vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); |
256 | INIT_LIST_HEAD(&vma->anon_vma_chain); | 277 | INIT_LIST_HEAD(&vma->anon_vma_chain); |
278 | |||
279 | err = security_file_mmap(NULL, 0, 0, 0, vma->vm_start, 1); | ||
280 | if (err) | ||
281 | goto err; | ||
282 | |||
257 | err = insert_vm_struct(mm, vma); | 283 | err = insert_vm_struct(mm, vma); |
258 | if (err) | 284 | if (err) |
259 | goto err; | 285 | goto err; |
@@ -276,7 +302,11 @@ static bool valid_arg_len(struct linux_binprm *bprm, long len) | |||
276 | 302 | ||
277 | #else | 303 | #else |
278 | 304 | ||
279 | static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, | 305 | void acct_arg_size(struct linux_binprm *bprm, unsigned long pages) |
306 | { | ||
307 | } | ||
308 | |||
309 | struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, | ||
280 | int write) | 310 | int write) |
281 | { | 311 | { |
282 | struct page *page; | 312 | struct page *page; |
@@ -1003,6 +1033,7 @@ int flush_old_exec(struct linux_binprm * bprm) | |||
1003 | /* | 1033 | /* |
1004 | * Release all of the old mmap stuff | 1034 | * Release all of the old mmap stuff |
1005 | */ | 1035 | */ |
1036 | acct_arg_size(bprm, 0); | ||
1006 | retval = exec_mmap(bprm->mm); | 1037 | retval = exec_mmap(bprm->mm); |
1007 | if (retval) | 1038 | if (retval) |
1008 | goto out; | 1039 | goto out; |
@@ -1426,8 +1457,10 @@ int do_execve(const char * filename, | |||
1426 | return retval; | 1457 | return retval; |
1427 | 1458 | ||
1428 | out: | 1459 | out: |
1429 | if (bprm->mm) | 1460 | if (bprm->mm) { |
1430 | mmput (bprm->mm); | 1461 | acct_arg_size(bprm, 0); |
1462 | mmput(bprm->mm); | ||
1463 | } | ||
1431 | 1464 | ||
1432 | out_file: | 1465 | out_file: |
1433 | if (bprm->file) { | 1466 | if (bprm->file) { |
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 6a5edea2d70b..94ce3d7a1c4b 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -910,6 +910,7 @@ struct ext4_inode_info { | |||
910 | #define EXT4_MOUNT_JOURNAL_CHECKSUM 0x800000 /* Journal checksums */ | 910 | #define EXT4_MOUNT_JOURNAL_CHECKSUM 0x800000 /* Journal checksums */ |
911 | #define EXT4_MOUNT_JOURNAL_ASYNC_COMMIT 0x1000000 /* Journal Async Commit */ | 911 | #define EXT4_MOUNT_JOURNAL_ASYNC_COMMIT 0x1000000 /* Journal Async Commit */ |
912 | #define EXT4_MOUNT_I_VERSION 0x2000000 /* i_version support */ | 912 | #define EXT4_MOUNT_I_VERSION 0x2000000 /* i_version support */ |
913 | #define EXT4_MOUNT_MBLK_IO_SUBMIT 0x4000000 /* multi-block io submits */ | ||
913 | #define EXT4_MOUNT_DELALLOC 0x8000000 /* Delalloc support */ | 914 | #define EXT4_MOUNT_DELALLOC 0x8000000 /* Delalloc support */ |
914 | #define EXT4_MOUNT_DATA_ERR_ABORT 0x10000000 /* Abort on file data write */ | 915 | #define EXT4_MOUNT_DATA_ERR_ABORT 0x10000000 /* Abort on file data write */ |
915 | #define EXT4_MOUNT_BLOCK_VALIDITY 0x20000000 /* Block validity checking */ | 916 | #define EXT4_MOUNT_BLOCK_VALIDITY 0x20000000 /* Block validity checking */ |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index bdbe69902207..e659597b690b 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -2125,9 +2125,12 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd, | |||
2125 | */ | 2125 | */ |
2126 | if (unlikely(journal_data && PageChecked(page))) | 2126 | if (unlikely(journal_data && PageChecked(page))) |
2127 | err = __ext4_journalled_writepage(page, len); | 2127 | err = __ext4_journalled_writepage(page, len); |
2128 | else | 2128 | else if (test_opt(inode->i_sb, MBLK_IO_SUBMIT)) |
2129 | err = ext4_bio_write_page(&io_submit, page, | 2129 | err = ext4_bio_write_page(&io_submit, page, |
2130 | len, mpd->wbc); | 2130 | len, mpd->wbc); |
2131 | else | ||
2132 | err = block_write_full_page(page, | ||
2133 | noalloc_get_block_write, mpd->wbc); | ||
2131 | 2134 | ||
2132 | if (!err) | 2135 | if (!err) |
2133 | mpd->pages_written++; | 2136 | mpd->pages_written++; |
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 92203b8a099f..dc40e75cba88 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c | |||
@@ -872,7 +872,7 @@ static struct buffer_head * ext4_find_entry (struct inode *dir, | |||
872 | if (namelen > EXT4_NAME_LEN) | 872 | if (namelen > EXT4_NAME_LEN) |
873 | return NULL; | 873 | return NULL; |
874 | if ((namelen <= 2) && (name[0] == '.') && | 874 | if ((namelen <= 2) && (name[0] == '.') && |
875 | (name[1] == '.' || name[1] == '0')) { | 875 | (name[1] == '.' || name[1] == '\0')) { |
876 | /* | 876 | /* |
877 | * "." or ".." will only be in the first block | 877 | * "." or ".." will only be in the first block |
878 | * NFS may look up ".."; "." should be handled by the VFS | 878 | * NFS may look up ".."; "." should be handled by the VFS |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index e32195d6aac3..fb15c9c0be74 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -1026,6 +1026,8 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
1026 | !(def_mount_opts & EXT4_DEFM_NODELALLOC)) | 1026 | !(def_mount_opts & EXT4_DEFM_NODELALLOC)) |
1027 | seq_puts(seq, ",nodelalloc"); | 1027 | seq_puts(seq, ",nodelalloc"); |
1028 | 1028 | ||
1029 | if (test_opt(sb, MBLK_IO_SUBMIT)) | ||
1030 | seq_puts(seq, ",mblk_io_submit"); | ||
1029 | if (sbi->s_stripe) | 1031 | if (sbi->s_stripe) |
1030 | seq_printf(seq, ",stripe=%lu", sbi->s_stripe); | 1032 | seq_printf(seq, ",stripe=%lu", sbi->s_stripe); |
1031 | /* | 1033 | /* |
@@ -1239,8 +1241,8 @@ enum { | |||
1239 | Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_jqfmt_vfsv1, Opt_quota, | 1241 | Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_jqfmt_vfsv1, Opt_quota, |
1240 | Opt_noquota, Opt_ignore, Opt_barrier, Opt_nobarrier, Opt_err, | 1242 | Opt_noquota, Opt_ignore, Opt_barrier, Opt_nobarrier, Opt_err, |
1241 | Opt_resize, Opt_usrquota, Opt_grpquota, Opt_i_version, | 1243 | Opt_resize, Opt_usrquota, Opt_grpquota, Opt_i_version, |
1242 | Opt_stripe, Opt_delalloc, Opt_nodelalloc, | 1244 | Opt_stripe, Opt_delalloc, Opt_nodelalloc, Opt_mblk_io_submit, |
1243 | Opt_block_validity, Opt_noblock_validity, | 1245 | Opt_nomblk_io_submit, Opt_block_validity, Opt_noblock_validity, |
1244 | Opt_inode_readahead_blks, Opt_journal_ioprio, | 1246 | Opt_inode_readahead_blks, Opt_journal_ioprio, |
1245 | Opt_dioread_nolock, Opt_dioread_lock, | 1247 | Opt_dioread_nolock, Opt_dioread_lock, |
1246 | Opt_discard, Opt_nodiscard, | 1248 | Opt_discard, Opt_nodiscard, |
@@ -1304,6 +1306,8 @@ static const match_table_t tokens = { | |||
1304 | {Opt_resize, "resize"}, | 1306 | {Opt_resize, "resize"}, |
1305 | {Opt_delalloc, "delalloc"}, | 1307 | {Opt_delalloc, "delalloc"}, |
1306 | {Opt_nodelalloc, "nodelalloc"}, | 1308 | {Opt_nodelalloc, "nodelalloc"}, |
1309 | {Opt_mblk_io_submit, "mblk_io_submit"}, | ||
1310 | {Opt_nomblk_io_submit, "nomblk_io_submit"}, | ||
1307 | {Opt_block_validity, "block_validity"}, | 1311 | {Opt_block_validity, "block_validity"}, |
1308 | {Opt_noblock_validity, "noblock_validity"}, | 1312 | {Opt_noblock_validity, "noblock_validity"}, |
1309 | {Opt_inode_readahead_blks, "inode_readahead_blks=%u"}, | 1313 | {Opt_inode_readahead_blks, "inode_readahead_blks=%u"}, |
@@ -1725,6 +1729,12 @@ set_qf_format: | |||
1725 | case Opt_nodelalloc: | 1729 | case Opt_nodelalloc: |
1726 | clear_opt(sbi->s_mount_opt, DELALLOC); | 1730 | clear_opt(sbi->s_mount_opt, DELALLOC); |
1727 | break; | 1731 | break; |
1732 | case Opt_mblk_io_submit: | ||
1733 | set_opt(sbi->s_mount_opt, MBLK_IO_SUBMIT); | ||
1734 | break; | ||
1735 | case Opt_nomblk_io_submit: | ||
1736 | clear_opt(sbi->s_mount_opt, MBLK_IO_SUBMIT); | ||
1737 | break; | ||
1728 | case Opt_stripe: | 1738 | case Opt_stripe: |
1729 | if (match_int(&args[0], &option)) | 1739 | if (match_int(&args[0], &option)) |
1730 | return 0; | 1740 | return 0; |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 9242d294fe90..8b984a2cebbd 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/sched.h> | 14 | #include <linux/sched.h> |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/compat.h> | ||
16 | 17 | ||
17 | static const struct file_operations fuse_direct_io_file_operations; | 18 | static const struct file_operations fuse_direct_io_file_operations; |
18 | 19 | ||
@@ -1628,6 +1629,58 @@ static int fuse_ioctl_copy_user(struct page **pages, struct iovec *iov, | |||
1628 | } | 1629 | } |
1629 | 1630 | ||
1630 | /* | 1631 | /* |
1632 | * CUSE servers compiled on 32bit broke on 64bit kernels because the | ||
1633 | * ABI was defined to be 'struct iovec' which is different on 32bit | ||
1634 | * and 64bit. Fortunately we can determine which structure the server | ||
1635 | * used from the size of the reply. | ||
1636 | */ | ||
1637 | static int fuse_copy_ioctl_iovec(struct iovec *dst, void *src, | ||
1638 | size_t transferred, unsigned count, | ||
1639 | bool is_compat) | ||
1640 | { | ||
1641 | #ifdef CONFIG_COMPAT | ||
1642 | if (count * sizeof(struct compat_iovec) == transferred) { | ||
1643 | struct compat_iovec *ciov = src; | ||
1644 | unsigned i; | ||
1645 | |||
1646 | /* | ||
1647 | * With this interface a 32bit server cannot support | ||
1648 | * non-compat (i.e. ones coming from 64bit apps) ioctl | ||
1649 | * requests | ||
1650 | */ | ||
1651 | if (!is_compat) | ||
1652 | return -EINVAL; | ||
1653 | |||
1654 | for (i = 0; i < count; i++) { | ||
1655 | dst[i].iov_base = compat_ptr(ciov[i].iov_base); | ||
1656 | dst[i].iov_len = ciov[i].iov_len; | ||
1657 | } | ||
1658 | return 0; | ||
1659 | } | ||
1660 | #endif | ||
1661 | |||
1662 | if (count * sizeof(struct iovec) != transferred) | ||
1663 | return -EIO; | ||
1664 | |||
1665 | memcpy(dst, src, transferred); | ||
1666 | return 0; | ||
1667 | } | ||
1668 | |||
1669 | /* Make sure iov_length() won't overflow */ | ||
1670 | static int fuse_verify_ioctl_iov(struct iovec *iov, size_t count) | ||
1671 | { | ||
1672 | size_t n; | ||
1673 | u32 max = FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT; | ||
1674 | |||
1675 | for (n = 0; n < count; n++) { | ||
1676 | if (iov->iov_len > (size_t) max) | ||
1677 | return -ENOMEM; | ||
1678 | max -= iov->iov_len; | ||
1679 | } | ||
1680 | return 0; | ||
1681 | } | ||
1682 | |||
1683 | /* | ||
1631 | * For ioctls, there is no generic way to determine how much memory | 1684 | * For ioctls, there is no generic way to determine how much memory |
1632 | * needs to be read and/or written. Furthermore, ioctls are allowed | 1685 | * needs to be read and/or written. Furthermore, ioctls are allowed |
1633 | * to dereference the passed pointer, so the parameter requires deep | 1686 | * to dereference the passed pointer, so the parameter requires deep |
@@ -1808,18 +1861,25 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg, | |||
1808 | in_iovs + out_iovs > FUSE_IOCTL_MAX_IOV) | 1861 | in_iovs + out_iovs > FUSE_IOCTL_MAX_IOV) |
1809 | goto out; | 1862 | goto out; |
1810 | 1863 | ||
1811 | err = -EIO; | ||
1812 | if ((in_iovs + out_iovs) * sizeof(struct iovec) != transferred) | ||
1813 | goto out; | ||
1814 | |||
1815 | /* okay, copy in iovs and retry */ | ||
1816 | vaddr = kmap_atomic(pages[0], KM_USER0); | 1864 | vaddr = kmap_atomic(pages[0], KM_USER0); |
1817 | memcpy(page_address(iov_page), vaddr, transferred); | 1865 | err = fuse_copy_ioctl_iovec(page_address(iov_page), vaddr, |
1866 | transferred, in_iovs + out_iovs, | ||
1867 | (flags & FUSE_IOCTL_COMPAT) != 0); | ||
1818 | kunmap_atomic(vaddr, KM_USER0); | 1868 | kunmap_atomic(vaddr, KM_USER0); |
1869 | if (err) | ||
1870 | goto out; | ||
1819 | 1871 | ||
1820 | in_iov = page_address(iov_page); | 1872 | in_iov = page_address(iov_page); |
1821 | out_iov = in_iov + in_iovs; | 1873 | out_iov = in_iov + in_iovs; |
1822 | 1874 | ||
1875 | err = fuse_verify_ioctl_iov(in_iov, in_iovs); | ||
1876 | if (err) | ||
1877 | goto out; | ||
1878 | |||
1879 | err = fuse_verify_ioctl_iov(out_iov, out_iovs); | ||
1880 | if (err) | ||
1881 | goto out; | ||
1882 | |||
1823 | goto retry; | 1883 | goto retry; |
1824 | } | 1884 | } |
1825 | 1885 | ||
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 8ea4a4180a87..996dd8989a91 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -57,7 +57,7 @@ static int nfs_rename(struct inode *, struct dentry *, | |||
57 | struct inode *, struct dentry *); | 57 | struct inode *, struct dentry *); |
58 | static int nfs_fsync_dir(struct file *, int); | 58 | static int nfs_fsync_dir(struct file *, int); |
59 | static loff_t nfs_llseek_dir(struct file *, loff_t, int); | 59 | static loff_t nfs_llseek_dir(struct file *, loff_t, int); |
60 | static int nfs_readdir_clear_array(struct page*, gfp_t); | 60 | static void nfs_readdir_clear_array(struct page*); |
61 | 61 | ||
62 | const struct file_operations nfs_dir_operations = { | 62 | const struct file_operations nfs_dir_operations = { |
63 | .llseek = nfs_llseek_dir, | 63 | .llseek = nfs_llseek_dir, |
@@ -83,8 +83,8 @@ const struct inode_operations nfs_dir_inode_operations = { | |||
83 | .setattr = nfs_setattr, | 83 | .setattr = nfs_setattr, |
84 | }; | 84 | }; |
85 | 85 | ||
86 | const struct address_space_operations nfs_dir_addr_space_ops = { | 86 | const struct address_space_operations nfs_dir_aops = { |
87 | .releasepage = nfs_readdir_clear_array, | 87 | .freepage = nfs_readdir_clear_array, |
88 | }; | 88 | }; |
89 | 89 | ||
90 | #ifdef CONFIG_NFS_V3 | 90 | #ifdef CONFIG_NFS_V3 |
@@ -178,6 +178,7 @@ typedef struct { | |||
178 | struct page *page; | 178 | struct page *page; |
179 | unsigned long page_index; | 179 | unsigned long page_index; |
180 | u64 *dir_cookie; | 180 | u64 *dir_cookie; |
181 | u64 last_cookie; | ||
181 | loff_t current_index; | 182 | loff_t current_index; |
182 | decode_dirent_t decode; | 183 | decode_dirent_t decode; |
183 | 184 | ||
@@ -213,17 +214,15 @@ void nfs_readdir_release_array(struct page *page) | |||
213 | * we are freeing strings created by nfs_add_to_readdir_array() | 214 | * we are freeing strings created by nfs_add_to_readdir_array() |
214 | */ | 215 | */ |
215 | static | 216 | static |
216 | int nfs_readdir_clear_array(struct page *page, gfp_t mask) | 217 | void nfs_readdir_clear_array(struct page *page) |
217 | { | 218 | { |
218 | struct nfs_cache_array *array = nfs_readdir_get_array(page); | 219 | struct nfs_cache_array *array; |
219 | int i; | 220 | int i; |
220 | 221 | ||
221 | if (IS_ERR(array)) | 222 | array = kmap_atomic(page, KM_USER0); |
222 | return PTR_ERR(array); | ||
223 | for (i = 0; i < array->size; i++) | 223 | for (i = 0; i < array->size; i++) |
224 | kfree(array->array[i].string.name); | 224 | kfree(array->array[i].string.name); |
225 | nfs_readdir_release_array(page); | 225 | kunmap_atomic(array, KM_USER0); |
226 | return 0; | ||
227 | } | 226 | } |
228 | 227 | ||
229 | /* | 228 | /* |
@@ -272,7 +271,7 @@ int nfs_readdir_add_to_array(struct nfs_entry *entry, struct page *page) | |||
272 | goto out; | 271 | goto out; |
273 | array->last_cookie = entry->cookie; | 272 | array->last_cookie = entry->cookie; |
274 | array->size++; | 273 | array->size++; |
275 | if (entry->eof == 1) | 274 | if (entry->eof != 0) |
276 | array->eof_index = array->size; | 275 | array->eof_index = array->size; |
277 | out: | 276 | out: |
278 | nfs_readdir_release_array(page); | 277 | nfs_readdir_release_array(page); |
@@ -312,15 +311,14 @@ int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_des | |||
312 | for (i = 0; i < array->size; i++) { | 311 | for (i = 0; i < array->size; i++) { |
313 | if (array->array[i].cookie == *desc->dir_cookie) { | 312 | if (array->array[i].cookie == *desc->dir_cookie) { |
314 | desc->cache_entry_index = i; | 313 | desc->cache_entry_index = i; |
315 | status = 0; | 314 | return 0; |
316 | goto out; | ||
317 | } | 315 | } |
318 | } | 316 | } |
319 | if (i == array->eof_index) { | 317 | if (array->eof_index >= 0) { |
320 | desc->eof = 1; | ||
321 | status = -EBADCOOKIE; | 318 | status = -EBADCOOKIE; |
319 | if (*desc->dir_cookie == array->last_cookie) | ||
320 | desc->eof = 1; | ||
322 | } | 321 | } |
323 | out: | ||
324 | return status; | 322 | return status; |
325 | } | 323 | } |
326 | 324 | ||
@@ -328,10 +326,7 @@ static | |||
328 | int nfs_readdir_search_array(nfs_readdir_descriptor_t *desc) | 326 | int nfs_readdir_search_array(nfs_readdir_descriptor_t *desc) |
329 | { | 327 | { |
330 | struct nfs_cache_array *array; | 328 | struct nfs_cache_array *array; |
331 | int status = -EBADCOOKIE; | 329 | int status; |
332 | |||
333 | if (desc->dir_cookie == NULL) | ||
334 | goto out; | ||
335 | 330 | ||
336 | array = nfs_readdir_get_array(desc->page); | 331 | array = nfs_readdir_get_array(desc->page); |
337 | if (IS_ERR(array)) { | 332 | if (IS_ERR(array)) { |
@@ -344,6 +339,10 @@ int nfs_readdir_search_array(nfs_readdir_descriptor_t *desc) | |||
344 | else | 339 | else |
345 | status = nfs_readdir_search_for_cookie(array, desc); | 340 | status = nfs_readdir_search_for_cookie(array, desc); |
346 | 341 | ||
342 | if (status == -EAGAIN) { | ||
343 | desc->last_cookie = array->last_cookie; | ||
344 | desc->page_index++; | ||
345 | } | ||
347 | nfs_readdir_release_array(desc->page); | 346 | nfs_readdir_release_array(desc->page); |
348 | out: | 347 | out: |
349 | return status; | 348 | return status; |
@@ -395,13 +394,9 @@ int xdr_decode(nfs_readdir_descriptor_t *desc, struct nfs_entry *entry, struct x | |||
395 | static | 394 | static |
396 | int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry) | 395 | int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry) |
397 | { | 396 | { |
398 | struct nfs_inode *node; | ||
399 | if (dentry->d_inode == NULL) | 397 | if (dentry->d_inode == NULL) |
400 | goto different; | 398 | goto different; |
401 | node = NFS_I(dentry->d_inode); | 399 | if (nfs_compare_fh(entry->fh, NFS_FH(dentry->d_inode)) != 0) |
402 | if (node->fh.size != entry->fh->size) | ||
403 | goto different; | ||
404 | if (strncmp(node->fh.data, entry->fh->data, node->fh.size) != 0) | ||
405 | goto different; | 400 | goto different; |
406 | return 1; | 401 | return 1; |
407 | different: | 402 | different: |
@@ -494,7 +489,7 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en | |||
494 | 489 | ||
495 | count++; | 490 | count++; |
496 | 491 | ||
497 | if (desc->plus == 1) | 492 | if (desc->plus != 0) |
498 | nfs_prime_dcache(desc->file->f_path.dentry, entry); | 493 | nfs_prime_dcache(desc->file->f_path.dentry, entry); |
499 | 494 | ||
500 | status = nfs_readdir_add_to_array(entry, page); | 495 | status = nfs_readdir_add_to_array(entry, page); |
@@ -502,7 +497,7 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en | |||
502 | break; | 497 | break; |
503 | } while (!entry->eof); | 498 | } while (!entry->eof); |
504 | 499 | ||
505 | if (count == 0 || (status == -EBADCOOKIE && entry->eof == 1)) { | 500 | if (count == 0 || (status == -EBADCOOKIE && entry->eof != 0)) { |
506 | array = nfs_readdir_get_array(page); | 501 | array = nfs_readdir_get_array(page); |
507 | if (!IS_ERR(array)) { | 502 | if (!IS_ERR(array)) { |
508 | array->eof_index = array->size; | 503 | array->eof_index = array->size; |
@@ -567,7 +562,7 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, | |||
567 | unsigned int array_size = ARRAY_SIZE(pages); | 562 | unsigned int array_size = ARRAY_SIZE(pages); |
568 | 563 | ||
569 | entry.prev_cookie = 0; | 564 | entry.prev_cookie = 0; |
570 | entry.cookie = *desc->dir_cookie; | 565 | entry.cookie = desc->last_cookie; |
571 | entry.eof = 0; | 566 | entry.eof = 0; |
572 | entry.fh = nfs_alloc_fhandle(); | 567 | entry.fh = nfs_alloc_fhandle(); |
573 | entry.fattr = nfs_alloc_fattr(); | 568 | entry.fattr = nfs_alloc_fattr(); |
@@ -640,6 +635,8 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page* page) | |||
640 | static | 635 | static |
641 | void cache_page_release(nfs_readdir_descriptor_t *desc) | 636 | void cache_page_release(nfs_readdir_descriptor_t *desc) |
642 | { | 637 | { |
638 | if (!desc->page->mapping) | ||
639 | nfs_readdir_clear_array(desc->page); | ||
643 | page_cache_release(desc->page); | 640 | page_cache_release(desc->page); |
644 | desc->page = NULL; | 641 | desc->page = NULL; |
645 | } | 642 | } |
@@ -664,9 +661,8 @@ int find_cache_page(nfs_readdir_descriptor_t *desc) | |||
664 | return PTR_ERR(desc->page); | 661 | return PTR_ERR(desc->page); |
665 | 662 | ||
666 | res = nfs_readdir_search_array(desc); | 663 | res = nfs_readdir_search_array(desc); |
667 | if (res == 0) | 664 | if (res != 0) |
668 | return 0; | 665 | cache_page_release(desc); |
669 | cache_page_release(desc); | ||
670 | return res; | 666 | return res; |
671 | } | 667 | } |
672 | 668 | ||
@@ -676,22 +672,16 @@ int readdir_search_pagecache(nfs_readdir_descriptor_t *desc) | |||
676 | { | 672 | { |
677 | int res; | 673 | int res; |
678 | 674 | ||
679 | if (desc->page_index == 0) | 675 | if (desc->page_index == 0) { |
680 | desc->current_index = 0; | 676 | desc->current_index = 0; |
681 | while (1) { | 677 | desc->last_cookie = 0; |
682 | res = find_cache_page(desc); | ||
683 | if (res != -EAGAIN) | ||
684 | break; | ||
685 | desc->page_index++; | ||
686 | } | 678 | } |
679 | do { | ||
680 | res = find_cache_page(desc); | ||
681 | } while (res == -EAGAIN); | ||
687 | return res; | 682 | return res; |
688 | } | 683 | } |
689 | 684 | ||
690 | static inline unsigned int dt_type(struct inode *inode) | ||
691 | { | ||
692 | return (inode->i_mode >> 12) & 15; | ||
693 | } | ||
694 | |||
695 | /* | 685 | /* |
696 | * Once we've found the start of the dirent within a page: fill 'er up... | 686 | * Once we've found the start of the dirent within a page: fill 'er up... |
697 | */ | 687 | */ |
@@ -721,13 +711,12 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent, | |||
721 | break; | 711 | break; |
722 | } | 712 | } |
723 | file->f_pos++; | 713 | file->f_pos++; |
724 | desc->cache_entry_index = i; | ||
725 | if (i < (array->size-1)) | 714 | if (i < (array->size-1)) |
726 | *desc->dir_cookie = array->array[i+1].cookie; | 715 | *desc->dir_cookie = array->array[i+1].cookie; |
727 | else | 716 | else |
728 | *desc->dir_cookie = array->last_cookie; | 717 | *desc->dir_cookie = array->last_cookie; |
729 | } | 718 | } |
730 | if (i == array->eof_index) | 719 | if (array->eof_index >= 0) |
731 | desc->eof = 1; | 720 | desc->eof = 1; |
732 | 721 | ||
733 | nfs_readdir_release_array(desc->page); | 722 | nfs_readdir_release_array(desc->page); |
@@ -768,6 +757,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent, | |||
768 | } | 757 | } |
769 | 758 | ||
770 | desc->page_index = 0; | 759 | desc->page_index = 0; |
760 | desc->last_cookie = *desc->dir_cookie; | ||
771 | desc->page = page; | 761 | desc->page = page; |
772 | 762 | ||
773 | status = nfs_readdir_xdr_to_array(desc, page, inode); | 763 | status = nfs_readdir_xdr_to_array(desc, page, inode); |
@@ -795,7 +785,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
795 | struct inode *inode = dentry->d_inode; | 785 | struct inode *inode = dentry->d_inode; |
796 | nfs_readdir_descriptor_t my_desc, | 786 | nfs_readdir_descriptor_t my_desc, |
797 | *desc = &my_desc; | 787 | *desc = &my_desc; |
798 | int res = -ENOMEM; | 788 | int res; |
799 | 789 | ||
800 | dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n", | 790 | dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n", |
801 | dentry->d_parent->d_name.name, dentry->d_name.name, | 791 | dentry->d_parent->d_name.name, dentry->d_name.name, |
@@ -820,7 +810,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
820 | if (res < 0) | 810 | if (res < 0) |
821 | goto out; | 811 | goto out; |
822 | 812 | ||
823 | while (desc->eof != 1) { | 813 | do { |
824 | res = readdir_search_pagecache(desc); | 814 | res = readdir_search_pagecache(desc); |
825 | 815 | ||
826 | if (res == -EBADCOOKIE) { | 816 | if (res == -EBADCOOKIE) { |
@@ -848,7 +838,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
848 | res = nfs_do_filldir(desc, dirent, filldir); | 838 | res = nfs_do_filldir(desc, dirent, filldir); |
849 | if (res < 0) | 839 | if (res < 0) |
850 | break; | 840 | break; |
851 | } | 841 | } while (!desc->eof); |
852 | out: | 842 | out: |
853 | nfs_unblock_sillyrename(dentry); | 843 | nfs_unblock_sillyrename(dentry); |
854 | if (res > 0) | 844 | if (res > 0) |
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 60677f9f1311..7bf029ef4084 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -693,6 +693,7 @@ do_getlk(struct file *filp, int cmd, struct file_lock *fl, int is_local) | |||
693 | { | 693 | { |
694 | struct inode *inode = filp->f_mapping->host; | 694 | struct inode *inode = filp->f_mapping->host; |
695 | int status = 0; | 695 | int status = 0; |
696 | unsigned int saved_type = fl->fl_type; | ||
696 | 697 | ||
697 | /* Try local locking first */ | 698 | /* Try local locking first */ |
698 | posix_test_lock(filp, fl); | 699 | posix_test_lock(filp, fl); |
@@ -700,6 +701,7 @@ do_getlk(struct file *filp, int cmd, struct file_lock *fl, int is_local) | |||
700 | /* found a conflict */ | 701 | /* found a conflict */ |
701 | goto out; | 702 | goto out; |
702 | } | 703 | } |
704 | fl->fl_type = saved_type; | ||
703 | 705 | ||
704 | if (nfs_have_delegation(inode, FMODE_READ)) | 706 | if (nfs_have_delegation(inode, FMODE_READ)) |
705 | goto out_noconflict; | 707 | goto out_noconflict; |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 314f57164602..e67e31c73416 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -289,6 +289,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | |||
289 | } else if (S_ISDIR(inode->i_mode)) { | 289 | } else if (S_ISDIR(inode->i_mode)) { |
290 | inode->i_op = NFS_SB(sb)->nfs_client->rpc_ops->dir_inode_ops; | 290 | inode->i_op = NFS_SB(sb)->nfs_client->rpc_ops->dir_inode_ops; |
291 | inode->i_fop = &nfs_dir_operations; | 291 | inode->i_fop = &nfs_dir_operations; |
292 | inode->i_data.a_ops = &nfs_dir_aops; | ||
292 | if (nfs_server_capable(inode, NFS_CAP_READDIRPLUS)) | 293 | if (nfs_server_capable(inode, NFS_CAP_READDIRPLUS)) |
293 | set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags); | 294 | set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags); |
294 | /* Deal with crossing mountpoints */ | 295 | /* Deal with crossing mountpoints */ |
diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c index eceafe74f473..4f981f1f6689 100644 --- a/fs/nfs/mount_clnt.c +++ b/fs/nfs/mount_clnt.c | |||
@@ -505,13 +505,13 @@ static struct rpc_procinfo mnt3_procedures[] = { | |||
505 | 505 | ||
506 | static struct rpc_version mnt_version1 = { | 506 | static struct rpc_version mnt_version1 = { |
507 | .number = 1, | 507 | .number = 1, |
508 | .nrprocs = 2, | 508 | .nrprocs = ARRAY_SIZE(mnt_procedures), |
509 | .procs = mnt_procedures, | 509 | .procs = mnt_procedures, |
510 | }; | 510 | }; |
511 | 511 | ||
512 | static struct rpc_version mnt_version3 = { | 512 | static struct rpc_version mnt_version3 = { |
513 | .number = 3, | 513 | .number = 3, |
514 | .nrprocs = 2, | 514 | .nrprocs = ARRAY_SIZE(mnt3_procedures), |
515 | .procs = mnt3_procedures, | 515 | .procs = mnt3_procedures, |
516 | }; | 516 | }; |
517 | 517 | ||
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 6a653ffd8e4e..4435e5e1f904 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -3361,6 +3361,8 @@ static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen) | |||
3361 | ret = nfs_revalidate_inode(server, inode); | 3361 | ret = nfs_revalidate_inode(server, inode); |
3362 | if (ret < 0) | 3362 | if (ret < 0) |
3363 | return ret; | 3363 | return ret; |
3364 | if (NFS_I(inode)->cache_validity & NFS_INO_INVALID_ACL) | ||
3365 | nfs_zap_acl_cache(inode); | ||
3364 | ret = nfs4_read_cached_acl(inode, buf, buflen); | 3366 | ret = nfs4_read_cached_acl(inode, buf, buflen); |
3365 | if (ret != -ENOENT) | 3367 | if (ret != -ENOENT) |
3366 | return ret; | 3368 | return ret; |
@@ -3389,6 +3391,13 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl | |||
3389 | nfs_inode_return_delegation(inode); | 3391 | nfs_inode_return_delegation(inode); |
3390 | buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase); | 3392 | buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase); |
3391 | ret = nfs4_call_sync(server, &msg, &arg, &res, 1); | 3393 | ret = nfs4_call_sync(server, &msg, &arg, &res, 1); |
3394 | /* | ||
3395 | * Acl update can result in inode attribute update. | ||
3396 | * so mark the attribute cache invalid. | ||
3397 | */ | ||
3398 | spin_lock(&inode->i_lock); | ||
3399 | NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATTR; | ||
3400 | spin_unlock(&inode->i_lock); | ||
3392 | nfs_access_zap_cache(inode); | 3401 | nfs_access_zap_cache(inode); |
3393 | nfs_zap_acl_cache(inode); | 3402 | nfs_zap_acl_cache(inode); |
3394 | return ret; | 3403 | return ret; |
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index 137b549e63db..b68536cc9046 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c | |||
@@ -115,7 +115,7 @@ int nfs_set_page_tag_locked(struct nfs_page *req) | |||
115 | { | 115 | { |
116 | if (!nfs_lock_request_dontget(req)) | 116 | if (!nfs_lock_request_dontget(req)) |
117 | return 0; | 117 | return 0; |
118 | if (req->wb_page != NULL) | 118 | if (test_bit(PG_MAPPED, &req->wb_flags)) |
119 | radix_tree_tag_set(&NFS_I(req->wb_context->path.dentry->d_inode)->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED); | 119 | radix_tree_tag_set(&NFS_I(req->wb_context->path.dentry->d_inode)->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED); |
120 | return 1; | 120 | return 1; |
121 | } | 121 | } |
@@ -125,7 +125,7 @@ int nfs_set_page_tag_locked(struct nfs_page *req) | |||
125 | */ | 125 | */ |
126 | void nfs_clear_page_tag_locked(struct nfs_page *req) | 126 | void nfs_clear_page_tag_locked(struct nfs_page *req) |
127 | { | 127 | { |
128 | if (req->wb_page != NULL) { | 128 | if (test_bit(PG_MAPPED, &req->wb_flags)) { |
129 | struct inode *inode = req->wb_context->path.dentry->d_inode; | 129 | struct inode *inode = req->wb_context->path.dentry->d_inode; |
130 | struct nfs_inode *nfsi = NFS_I(inode); | 130 | struct nfs_inode *nfsi = NFS_I(inode); |
131 | 131 | ||
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index e4b62c6f5a6e..aedcaa7f291f 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
@@ -152,7 +152,6 @@ static void nfs_readpage_release(struct nfs_page *req) | |||
152 | (long long)NFS_FILEID(req->wb_context->path.dentry->d_inode), | 152 | (long long)NFS_FILEID(req->wb_context->path.dentry->d_inode), |
153 | req->wb_bytes, | 153 | req->wb_bytes, |
154 | (long long)req_offset(req)); | 154 | (long long)req_offset(req)); |
155 | nfs_clear_request(req); | ||
156 | nfs_release_request(req); | 155 | nfs_release_request(req); |
157 | } | 156 | } |
158 | 157 | ||
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 3c045044fca2..4100630c9a5b 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -1069,12 +1069,10 @@ static int nfs_parse_mount_options(char *raw, | |||
1069 | mnt->flags |= NFS_MOUNT_VER3; | 1069 | mnt->flags |= NFS_MOUNT_VER3; |
1070 | mnt->version = 3; | 1070 | mnt->version = 3; |
1071 | break; | 1071 | break; |
1072 | #ifdef CONFIG_NFS_V4 | ||
1073 | case Opt_v4: | 1072 | case Opt_v4: |
1074 | mnt->flags &= ~NFS_MOUNT_VER3; | 1073 | mnt->flags &= ~NFS_MOUNT_VER3; |
1075 | mnt->version = 4; | 1074 | mnt->version = 4; |
1076 | break; | 1075 | break; |
1077 | #endif | ||
1078 | case Opt_udp: | 1076 | case Opt_udp: |
1079 | mnt->flags &= ~NFS_MOUNT_TCP; | 1077 | mnt->flags &= ~NFS_MOUNT_TCP; |
1080 | mnt->nfs_server.protocol = XPRT_TRANSPORT_UDP; | 1078 | mnt->nfs_server.protocol = XPRT_TRANSPORT_UDP; |
@@ -1286,12 +1284,10 @@ static int nfs_parse_mount_options(char *raw, | |||
1286 | mnt->flags |= NFS_MOUNT_VER3; | 1284 | mnt->flags |= NFS_MOUNT_VER3; |
1287 | mnt->version = 3; | 1285 | mnt->version = 3; |
1288 | break; | 1286 | break; |
1289 | #ifdef CONFIG_NFS_V4 | ||
1290 | case NFS4_VERSION: | 1287 | case NFS4_VERSION: |
1291 | mnt->flags &= ~NFS_MOUNT_VER3; | 1288 | mnt->flags &= ~NFS_MOUNT_VER3; |
1292 | mnt->version = 4; | 1289 | mnt->version = 4; |
1293 | break; | 1290 | break; |
1294 | #endif | ||
1295 | default: | 1291 | default: |
1296 | goto out_invalid_value; | 1292 | goto out_invalid_value; |
1297 | } | 1293 | } |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 4c14c17a5276..10d648ea128b 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -390,6 +390,7 @@ static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req) | |||
390 | if (nfs_have_delegation(inode, FMODE_WRITE)) | 390 | if (nfs_have_delegation(inode, FMODE_WRITE)) |
391 | nfsi->change_attr++; | 391 | nfsi->change_attr++; |
392 | } | 392 | } |
393 | set_bit(PG_MAPPED, &req->wb_flags); | ||
393 | SetPagePrivate(req->wb_page); | 394 | SetPagePrivate(req->wb_page); |
394 | set_page_private(req->wb_page, (unsigned long)req); | 395 | set_page_private(req->wb_page, (unsigned long)req); |
395 | nfsi->npages++; | 396 | nfsi->npages++; |
@@ -415,6 +416,7 @@ static void nfs_inode_remove_request(struct nfs_page *req) | |||
415 | spin_lock(&inode->i_lock); | 416 | spin_lock(&inode->i_lock); |
416 | set_page_private(req->wb_page, 0); | 417 | set_page_private(req->wb_page, 0); |
417 | ClearPagePrivate(req->wb_page); | 418 | ClearPagePrivate(req->wb_page); |
419 | clear_bit(PG_MAPPED, &req->wb_flags); | ||
418 | radix_tree_delete(&nfsi->nfs_page_tree, req->wb_index); | 420 | radix_tree_delete(&nfsi->nfs_page_tree, req->wb_index); |
419 | nfsi->npages--; | 421 | nfsi->npages--; |
420 | if (!nfsi->npages) { | 422 | if (!nfsi->npages) { |
@@ -422,7 +424,6 @@ static void nfs_inode_remove_request(struct nfs_page *req) | |||
422 | iput(inode); | 424 | iput(inode); |
423 | } else | 425 | } else |
424 | spin_unlock(&inode->i_lock); | 426 | spin_unlock(&inode->i_lock); |
425 | nfs_clear_request(req); | ||
426 | nfs_release_request(req); | 427 | nfs_release_request(req); |
427 | } | 428 | } |
428 | 429 | ||
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c index 2a533a0af2a9..7e84a852cdae 100644 --- a/fs/nfsd/nfs3xdr.c +++ b/fs/nfsd/nfs3xdr.c | |||
@@ -260,9 +260,11 @@ void fill_post_wcc(struct svc_fh *fhp) | |||
260 | err = vfs_getattr(fhp->fh_export->ex_path.mnt, fhp->fh_dentry, | 260 | err = vfs_getattr(fhp->fh_export->ex_path.mnt, fhp->fh_dentry, |
261 | &fhp->fh_post_attr); | 261 | &fhp->fh_post_attr); |
262 | fhp->fh_post_change = fhp->fh_dentry->d_inode->i_version; | 262 | fhp->fh_post_change = fhp->fh_dentry->d_inode->i_version; |
263 | if (err) | 263 | if (err) { |
264 | fhp->fh_post_saved = 0; | 264 | fhp->fh_post_saved = 0; |
265 | else | 265 | /* Grab the ctime anyway - set_change_info might use it */ |
266 | fhp->fh_post_attr.ctime = fhp->fh_dentry->d_inode->i_ctime; | ||
267 | } else | ||
266 | fhp->fh_post_saved = 1; | 268 | fhp->fh_post_saved = 1; |
267 | } | 269 | } |
268 | 270 | ||
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h index 4d476ff08ae6..60fce3dc5cb5 100644 --- a/fs/nfsd/xdr4.h +++ b/fs/nfsd/xdr4.h | |||
@@ -484,18 +484,17 @@ static inline bool nfsd4_not_cached(struct nfsd4_compoundres *resp) | |||
484 | static inline void | 484 | static inline void |
485 | set_change_info(struct nfsd4_change_info *cinfo, struct svc_fh *fhp) | 485 | set_change_info(struct nfsd4_change_info *cinfo, struct svc_fh *fhp) |
486 | { | 486 | { |
487 | BUG_ON(!fhp->fh_pre_saved || !fhp->fh_post_saved); | 487 | BUG_ON(!fhp->fh_pre_saved); |
488 | cinfo->atomic = 1; | 488 | cinfo->atomic = fhp->fh_post_saved; |
489 | cinfo->change_supported = IS_I_VERSION(fhp->fh_dentry->d_inode); | 489 | cinfo->change_supported = IS_I_VERSION(fhp->fh_dentry->d_inode); |
490 | if (cinfo->change_supported) { | 490 | |
491 | cinfo->before_change = fhp->fh_pre_change; | 491 | cinfo->before_change = fhp->fh_pre_change; |
492 | cinfo->after_change = fhp->fh_post_change; | 492 | cinfo->after_change = fhp->fh_post_change; |
493 | } else { | 493 | cinfo->before_ctime_sec = fhp->fh_pre_ctime.tv_sec; |
494 | cinfo->before_ctime_sec = fhp->fh_pre_ctime.tv_sec; | 494 | cinfo->before_ctime_nsec = fhp->fh_pre_ctime.tv_nsec; |
495 | cinfo->before_ctime_nsec = fhp->fh_pre_ctime.tv_nsec; | 495 | cinfo->after_ctime_sec = fhp->fh_post_attr.ctime.tv_sec; |
496 | cinfo->after_ctime_sec = fhp->fh_post_attr.ctime.tv_sec; | 496 | cinfo->after_ctime_nsec = fhp->fh_post_attr.ctime.tv_nsec; |
497 | cinfo->after_ctime_nsec = fhp->fh_post_attr.ctime.tv_nsec; | 497 | |
498 | } | ||
499 | } | 498 | } |
500 | 499 | ||
501 | int nfs4svc_encode_voidres(struct svc_rqst *, __be32 *, void *); | 500 | int nfs4svc_encode_voidres(struct svc_rqst *, __be32 *, void *); |
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c index 52c7557f3e25..9f26ac9be2a4 100644 --- a/fs/ocfs2/cluster/heartbeat.c +++ b/fs/ocfs2/cluster/heartbeat.c | |||
@@ -1964,8 +1964,10 @@ static struct config_item *o2hb_heartbeat_group_make_item(struct config_group *g | |||
1964 | if (reg == NULL) | 1964 | if (reg == NULL) |
1965 | return ERR_PTR(-ENOMEM); | 1965 | return ERR_PTR(-ENOMEM); |
1966 | 1966 | ||
1967 | if (strlen(name) > O2HB_MAX_REGION_NAME_LEN) | 1967 | if (strlen(name) > O2HB_MAX_REGION_NAME_LEN) { |
1968 | return ERR_PTR(-ENAMETOOLONG); | 1968 | ret = -ENAMETOOLONG; |
1969 | goto free; | ||
1970 | } | ||
1969 | 1971 | ||
1970 | spin_lock(&o2hb_live_lock); | 1972 | spin_lock(&o2hb_live_lock); |
1971 | reg->hr_region_num = 0; | 1973 | reg->hr_region_num = 0; |
@@ -1974,7 +1976,8 @@ static struct config_item *o2hb_heartbeat_group_make_item(struct config_group *g | |||
1974 | O2NM_MAX_REGIONS); | 1976 | O2NM_MAX_REGIONS); |
1975 | if (reg->hr_region_num >= O2NM_MAX_REGIONS) { | 1977 | if (reg->hr_region_num >= O2NM_MAX_REGIONS) { |
1976 | spin_unlock(&o2hb_live_lock); | 1978 | spin_unlock(&o2hb_live_lock); |
1977 | return ERR_PTR(-EFBIG); | 1979 | ret = -EFBIG; |
1980 | goto free; | ||
1978 | } | 1981 | } |
1979 | set_bit(reg->hr_region_num, o2hb_region_bitmap); | 1982 | set_bit(reg->hr_region_num, o2hb_region_bitmap); |
1980 | } | 1983 | } |
@@ -1986,10 +1989,13 @@ static struct config_item *o2hb_heartbeat_group_make_item(struct config_group *g | |||
1986 | ret = o2hb_debug_region_init(reg, o2hb_debug_dir); | 1989 | ret = o2hb_debug_region_init(reg, o2hb_debug_dir); |
1987 | if (ret) { | 1990 | if (ret) { |
1988 | config_item_put(®->hr_item); | 1991 | config_item_put(®->hr_item); |
1989 | return ERR_PTR(ret); | 1992 | goto free; |
1990 | } | 1993 | } |
1991 | 1994 | ||
1992 | return ®->hr_item; | 1995 | return ®->hr_item; |
1996 | free: | ||
1997 | kfree(reg); | ||
1998 | return ERR_PTR(ret); | ||
1993 | } | 1999 | } |
1994 | 2000 | ||
1995 | static void o2hb_heartbeat_group_drop_item(struct config_group *group, | 2001 | static void o2hb_heartbeat_group_drop_item(struct config_group *group, |
diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c index edaded48e7e9..895532ac4d98 100644 --- a/fs/ocfs2/dcache.c +++ b/fs/ocfs2/dcache.c | |||
@@ -476,7 +476,6 @@ static void ocfs2_dentry_iput(struct dentry *dentry, struct inode *inode) | |||
476 | 476 | ||
477 | out: | 477 | out: |
478 | iput(inode); | 478 | iput(inode); |
479 | ocfs2_dentry_attach_gen(dentry); | ||
480 | } | 479 | } |
481 | 480 | ||
482 | /* | 481 | /* |
diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c index 58a93b953735..cc2aaa96cfe5 100644 --- a/fs/ocfs2/dlm/dlmdomain.c +++ b/fs/ocfs2/dlm/dlmdomain.c | |||
@@ -959,7 +959,7 @@ static int dlm_match_regions(struct dlm_ctxt *dlm, | |||
959 | r += O2HB_MAX_REGION_NAME_LEN; | 959 | r += O2HB_MAX_REGION_NAME_LEN; |
960 | } | 960 | } |
961 | 961 | ||
962 | local = kmalloc(sizeof(qr->qr_regions), GFP_KERNEL); | 962 | local = kmalloc(sizeof(qr->qr_regions), GFP_ATOMIC); |
963 | if (!local) { | 963 | if (!local) { |
964 | status = -ENOMEM; | 964 | status = -ENOMEM; |
965 | goto bail; | 965 | goto bail; |
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index 1efea3615589..70dd3b1798f1 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h | |||
@@ -159,9 +159,9 @@ struct ocfs2_lock_res { | |||
159 | char l_name[OCFS2_LOCK_ID_MAX_LEN]; | 159 | char l_name[OCFS2_LOCK_ID_MAX_LEN]; |
160 | unsigned int l_ro_holders; | 160 | unsigned int l_ro_holders; |
161 | unsigned int l_ex_holders; | 161 | unsigned int l_ex_holders; |
162 | char l_level; | 162 | signed char l_level; |
163 | char l_requested; | 163 | signed char l_requested; |
164 | char l_blocking; | 164 | signed char l_blocking; |
165 | 165 | ||
166 | /* Data packed - type enum ocfs2_lock_type */ | 166 | /* Data packed - type enum ocfs2_lock_type */ |
167 | unsigned char l_type; | 167 | unsigned char l_type; |
diff --git a/fs/ocfs2/stack_user.c b/fs/ocfs2/stack_user.c index 252e7c82f929..a5ebe421195f 100644 --- a/fs/ocfs2/stack_user.c +++ b/fs/ocfs2/stack_user.c | |||
@@ -190,7 +190,7 @@ static struct ocfs2_live_connection *ocfs2_connection_find(const char *name) | |||
190 | return c; | 190 | return c; |
191 | } | 191 | } |
192 | 192 | ||
193 | return c; | 193 | return NULL; |
194 | } | 194 | } |
195 | 195 | ||
196 | /* | 196 | /* |
diff --git a/fs/proc/base.c b/fs/proc/base.c index f3d02ca461ec..182845147fe4 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -1574,7 +1574,7 @@ static int do_proc_readlink(struct path *path, char __user *buffer, int buflen) | |||
1574 | if (!tmp) | 1574 | if (!tmp) |
1575 | return -ENOMEM; | 1575 | return -ENOMEM; |
1576 | 1576 | ||
1577 | pathname = d_path_with_unreachable(path, tmp, PAGE_SIZE); | 1577 | pathname = d_path(path, tmp, PAGE_SIZE); |
1578 | len = PTR_ERR(pathname); | 1578 | len = PTR_ERR(pathname); |
1579 | if (IS_ERR(pathname)) | 1579 | if (IS_ERR(pathname)) |
1580 | goto out; | 1580 | goto out; |
diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c index 536d697a8a28..90d2fcb67a31 100644 --- a/fs/reiserfs/xattr_acl.c +++ b/fs/reiserfs/xattr_acl.c | |||
@@ -472,7 +472,9 @@ int reiserfs_acl_chmod(struct inode *inode) | |||
472 | struct reiserfs_transaction_handle th; | 472 | struct reiserfs_transaction_handle th; |
473 | size_t size = reiserfs_xattr_nblocks(inode, | 473 | size_t size = reiserfs_xattr_nblocks(inode, |
474 | reiserfs_acl_size(clone->a_count)); | 474 | reiserfs_acl_size(clone->a_count)); |
475 | reiserfs_write_lock(inode->i_sb); | 475 | int depth; |
476 | |||
477 | depth = reiserfs_write_lock_once(inode->i_sb); | ||
476 | error = journal_begin(&th, inode->i_sb, size * 2); | 478 | error = journal_begin(&th, inode->i_sb, size * 2); |
477 | if (!error) { | 479 | if (!error) { |
478 | int error2; | 480 | int error2; |
@@ -482,7 +484,7 @@ int reiserfs_acl_chmod(struct inode *inode) | |||
482 | if (error2) | 484 | if (error2) |
483 | error = error2; | 485 | error = error2; |
484 | } | 486 | } |
485 | reiserfs_write_unlock(inode->i_sb); | 487 | reiserfs_write_unlock_once(inode->i_sb, depth); |
486 | } | 488 | } |
487 | posix_acl_release(clone); | 489 | posix_acl_release(clone); |
488 | return error; | 490 | return error; |
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index 7d287afccde5..691f61223ed6 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c | |||
@@ -934,7 +934,6 @@ xfs_aops_discard_page( | |||
934 | struct xfs_inode *ip = XFS_I(inode); | 934 | struct xfs_inode *ip = XFS_I(inode); |
935 | struct buffer_head *bh, *head; | 935 | struct buffer_head *bh, *head; |
936 | loff_t offset = page_offset(page); | 936 | loff_t offset = page_offset(page); |
937 | ssize_t len = 1 << inode->i_blkbits; | ||
938 | 937 | ||
939 | if (!xfs_is_delayed_page(page, IO_DELAY)) | 938 | if (!xfs_is_delayed_page(page, IO_DELAY)) |
940 | goto out_invalidate; | 939 | goto out_invalidate; |
@@ -949,58 +948,14 @@ xfs_aops_discard_page( | |||
949 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 948 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
950 | bh = head = page_buffers(page); | 949 | bh = head = page_buffers(page); |
951 | do { | 950 | do { |
952 | int done; | ||
953 | xfs_fileoff_t offset_fsb; | ||
954 | xfs_bmbt_irec_t imap; | ||
955 | int nimaps = 1; | ||
956 | int error; | 951 | int error; |
957 | xfs_fsblock_t firstblock; | 952 | xfs_fileoff_t start_fsb; |
958 | xfs_bmap_free_t flist; | ||
959 | 953 | ||
960 | if (!buffer_delay(bh)) | 954 | if (!buffer_delay(bh)) |
961 | goto next_buffer; | 955 | goto next_buffer; |
962 | 956 | ||
963 | offset_fsb = XFS_B_TO_FSBT(ip->i_mount, offset); | 957 | start_fsb = XFS_B_TO_FSBT(ip->i_mount, offset); |
964 | 958 | error = xfs_bmap_punch_delalloc_range(ip, start_fsb, 1); | |
965 | /* | ||
966 | * Map the range first and check that it is a delalloc extent | ||
967 | * before trying to unmap the range. Otherwise we will be | ||
968 | * trying to remove a real extent (which requires a | ||
969 | * transaction) or a hole, which is probably a bad idea... | ||
970 | */ | ||
971 | error = xfs_bmapi(NULL, ip, offset_fsb, 1, | ||
972 | XFS_BMAPI_ENTIRE, NULL, 0, &imap, | ||
973 | &nimaps, NULL); | ||
974 | |||
975 | if (error) { | ||
976 | /* something screwed, just bail */ | ||
977 | if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) { | ||
978 | xfs_fs_cmn_err(CE_ALERT, ip->i_mount, | ||
979 | "page discard failed delalloc mapping lookup."); | ||
980 | } | ||
981 | break; | ||
982 | } | ||
983 | if (!nimaps) { | ||
984 | /* nothing there */ | ||
985 | goto next_buffer; | ||
986 | } | ||
987 | if (imap.br_startblock != DELAYSTARTBLOCK) { | ||
988 | /* been converted, ignore */ | ||
989 | goto next_buffer; | ||
990 | } | ||
991 | WARN_ON(imap.br_blockcount == 0); | ||
992 | |||
993 | /* | ||
994 | * Note: while we initialise the firstblock/flist pair, they | ||
995 | * should never be used because blocks should never be | ||
996 | * allocated or freed for a delalloc extent and hence we need | ||
997 | * don't cancel or finish them after the xfs_bunmapi() call. | ||
998 | */ | ||
999 | xfs_bmap_init(&flist, &firstblock); | ||
1000 | error = xfs_bunmapi(NULL, ip, offset_fsb, 1, 0, 1, &firstblock, | ||
1001 | &flist, &done); | ||
1002 | |||
1003 | ASSERT(!flist.xbf_count && !flist.xbf_first); | ||
1004 | if (error) { | 959 | if (error) { |
1005 | /* something screwed, just bail */ | 960 | /* something screwed, just bail */ |
1006 | if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) { | 961 | if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) { |
@@ -1010,7 +965,7 @@ xfs_aops_discard_page( | |||
1010 | break; | 965 | break; |
1011 | } | 966 | } |
1012 | next_buffer: | 967 | next_buffer: |
1013 | offset += len; | 968 | offset += 1 << inode->i_blkbits; |
1014 | 969 | ||
1015 | } while ((bh = bh->b_this_page) != head); | 970 | } while ((bh = bh->b_this_page) != head); |
1016 | 971 | ||
@@ -1505,11 +1460,42 @@ xfs_vm_write_failed( | |||
1505 | struct inode *inode = mapping->host; | 1460 | struct inode *inode = mapping->host; |
1506 | 1461 | ||
1507 | if (to > inode->i_size) { | 1462 | if (to > inode->i_size) { |
1508 | struct iattr ia = { | 1463 | /* |
1509 | .ia_valid = ATTR_SIZE | ATTR_FORCE, | 1464 | * punch out the delalloc blocks we have already allocated. We |
1510 | .ia_size = inode->i_size, | 1465 | * don't call xfs_setattr() to do this as we may be in the |
1511 | }; | 1466 | * middle of a multi-iovec write and so the vfs inode->i_size |
1512 | xfs_setattr(XFS_I(inode), &ia, XFS_ATTR_NOLOCK); | 1467 | * will not match the xfs ip->i_size and so it will zero too |
1468 | * much. Hence we jus truncate the page cache to zero what is | ||
1469 | * necessary and punch the delalloc blocks directly. | ||
1470 | */ | ||
1471 | struct xfs_inode *ip = XFS_I(inode); | ||
1472 | xfs_fileoff_t start_fsb; | ||
1473 | xfs_fileoff_t end_fsb; | ||
1474 | int error; | ||
1475 | |||
1476 | truncate_pagecache(inode, to, inode->i_size); | ||
1477 | |||
1478 | /* | ||
1479 | * Check if there are any blocks that are outside of i_size | ||
1480 | * that need to be trimmed back. | ||
1481 | */ | ||
1482 | start_fsb = XFS_B_TO_FSB(ip->i_mount, inode->i_size) + 1; | ||
1483 | end_fsb = XFS_B_TO_FSB(ip->i_mount, to); | ||
1484 | if (end_fsb <= start_fsb) | ||
1485 | return; | ||
1486 | |||
1487 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
1488 | error = xfs_bmap_punch_delalloc_range(ip, start_fsb, | ||
1489 | end_fsb - start_fsb); | ||
1490 | if (error) { | ||
1491 | /* something screwed, just bail */ | ||
1492 | if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) { | ||
1493 | xfs_fs_cmn_err(CE_ALERT, ip->i_mount, | ||
1494 | "xfs_vm_write_failed: unable to clean up ino %lld", | ||
1495 | ip->i_ino); | ||
1496 | } | ||
1497 | } | ||
1498 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
1513 | } | 1499 | } |
1514 | } | 1500 | } |
1515 | 1501 | ||
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index aa1d353def29..4c5deb6e9e31 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c | |||
@@ -488,29 +488,16 @@ found: | |||
488 | spin_unlock(&pag->pag_buf_lock); | 488 | spin_unlock(&pag->pag_buf_lock); |
489 | xfs_perag_put(pag); | 489 | xfs_perag_put(pag); |
490 | 490 | ||
491 | /* Attempt to get the semaphore without sleeping, | 491 | if (xfs_buf_cond_lock(bp)) { |
492 | * if this does not work then we need to drop the | 492 | /* failed, so wait for the lock if requested. */ |
493 | * spinlock and do a hard attempt on the semaphore. | ||
494 | */ | ||
495 | if (down_trylock(&bp->b_sema)) { | ||
496 | if (!(flags & XBF_TRYLOCK)) { | 493 | if (!(flags & XBF_TRYLOCK)) { |
497 | /* wait for buffer ownership */ | ||
498 | xfs_buf_lock(bp); | 494 | xfs_buf_lock(bp); |
499 | XFS_STATS_INC(xb_get_locked_waited); | 495 | XFS_STATS_INC(xb_get_locked_waited); |
500 | } else { | 496 | } else { |
501 | /* We asked for a trylock and failed, no need | ||
502 | * to look at file offset and length here, we | ||
503 | * know that this buffer at least overlaps our | ||
504 | * buffer and is locked, therefore our buffer | ||
505 | * either does not exist, or is this buffer. | ||
506 | */ | ||
507 | xfs_buf_rele(bp); | 497 | xfs_buf_rele(bp); |
508 | XFS_STATS_INC(xb_busy_locked); | 498 | XFS_STATS_INC(xb_busy_locked); |
509 | return NULL; | 499 | return NULL; |
510 | } | 500 | } |
511 | } else { | ||
512 | /* trylock worked */ | ||
513 | XB_SET_OWNER(bp); | ||
514 | } | 501 | } |
515 | 502 | ||
516 | if (bp->b_flags & XBF_STALE) { | 503 | if (bp->b_flags & XBF_STALE) { |
@@ -876,10 +863,18 @@ xfs_buf_rele( | |||
876 | */ | 863 | */ |
877 | 864 | ||
878 | /* | 865 | /* |
879 | * Locks a buffer object, if it is not already locked. | 866 | * Locks a buffer object, if it is not already locked. Note that this in |
880 | * Note that this in no way locks the underlying pages, so it is only | 867 | * no way locks the underlying pages, so it is only useful for |
881 | * useful for synchronizing concurrent use of buffer objects, not for | 868 | * synchronizing concurrent use of buffer objects, not for synchronizing |
882 | * synchronizing independent access to the underlying pages. | 869 | * independent access to the underlying pages. |
870 | * | ||
871 | * If we come across a stale, pinned, locked buffer, we know that we are | ||
872 | * being asked to lock a buffer that has been reallocated. Because it is | ||
873 | * pinned, we know that the log has not been pushed to disk and hence it | ||
874 | * will still be locked. Rather than continuing to have trylock attempts | ||
875 | * fail until someone else pushes the log, push it ourselves before | ||
876 | * returning. This means that the xfsaild will not get stuck trying | ||
877 | * to push on stale inode buffers. | ||
883 | */ | 878 | */ |
884 | int | 879 | int |
885 | xfs_buf_cond_lock( | 880 | xfs_buf_cond_lock( |
@@ -890,6 +885,8 @@ xfs_buf_cond_lock( | |||
890 | locked = down_trylock(&bp->b_sema) == 0; | 885 | locked = down_trylock(&bp->b_sema) == 0; |
891 | if (locked) | 886 | if (locked) |
892 | XB_SET_OWNER(bp); | 887 | XB_SET_OWNER(bp); |
888 | else if (atomic_read(&bp->b_pin_count) && (bp->b_flags & XBF_STALE)) | ||
889 | xfs_log_force(bp->b_target->bt_mount, 0); | ||
893 | 890 | ||
894 | trace_xfs_buf_cond_lock(bp, _RET_IP_); | 891 | trace_xfs_buf_cond_lock(bp, _RET_IP_); |
895 | return locked ? 0 : -EBUSY; | 892 | return locked ? 0 : -EBUSY; |
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 8abd12e32e13..4111cd3966c7 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c | |||
@@ -5471,8 +5471,13 @@ xfs_getbmap( | |||
5471 | if (error) | 5471 | if (error) |
5472 | goto out_unlock_iolock; | 5472 | goto out_unlock_iolock; |
5473 | } | 5473 | } |
5474 | 5474 | /* | |
5475 | ASSERT(ip->i_delayed_blks == 0); | 5475 | * even after flushing the inode, there can still be delalloc |
5476 | * blocks on the inode beyond EOF due to speculative | ||
5477 | * preallocation. These are not removed until the release | ||
5478 | * function is called or the inode is inactivated. Hence we | ||
5479 | * cannot assert here that ip->i_delayed_blks == 0. | ||
5480 | */ | ||
5476 | } | 5481 | } |
5477 | 5482 | ||
5478 | lock = xfs_ilock_map_shared(ip); | 5483 | lock = xfs_ilock_map_shared(ip); |
@@ -6070,3 +6075,79 @@ xfs_bmap_disk_count_leaves( | |||
6070 | *count += xfs_bmbt_disk_get_blockcount(frp); | 6075 | *count += xfs_bmbt_disk_get_blockcount(frp); |
6071 | } | 6076 | } |
6072 | } | 6077 | } |
6078 | |||
6079 | /* | ||
6080 | * dead simple method of punching delalyed allocation blocks from a range in | ||
6081 | * the inode. Walks a block at a time so will be slow, but is only executed in | ||
6082 | * rare error cases so the overhead is not critical. This will alays punch out | ||
6083 | * both the start and end blocks, even if the ranges only partially overlap | ||
6084 | * them, so it is up to the caller to ensure that partial blocks are not | ||
6085 | * passed in. | ||
6086 | */ | ||
6087 | int | ||
6088 | xfs_bmap_punch_delalloc_range( | ||
6089 | struct xfs_inode *ip, | ||
6090 | xfs_fileoff_t start_fsb, | ||
6091 | xfs_fileoff_t length) | ||
6092 | { | ||
6093 | xfs_fileoff_t remaining = length; | ||
6094 | int error = 0; | ||
6095 | |||
6096 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); | ||
6097 | |||
6098 | do { | ||
6099 | int done; | ||
6100 | xfs_bmbt_irec_t imap; | ||
6101 | int nimaps = 1; | ||
6102 | xfs_fsblock_t firstblock; | ||
6103 | xfs_bmap_free_t flist; | ||
6104 | |||
6105 | /* | ||
6106 | * Map the range first and check that it is a delalloc extent | ||
6107 | * before trying to unmap the range. Otherwise we will be | ||
6108 | * trying to remove a real extent (which requires a | ||
6109 | * transaction) or a hole, which is probably a bad idea... | ||
6110 | */ | ||
6111 | error = xfs_bmapi(NULL, ip, start_fsb, 1, | ||
6112 | XFS_BMAPI_ENTIRE, NULL, 0, &imap, | ||
6113 | &nimaps, NULL); | ||
6114 | |||
6115 | if (error) { | ||
6116 | /* something screwed, just bail */ | ||
6117 | if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) { | ||
6118 | xfs_fs_cmn_err(CE_ALERT, ip->i_mount, | ||
6119 | "Failed delalloc mapping lookup ino %lld fsb %lld.", | ||
6120 | ip->i_ino, start_fsb); | ||
6121 | } | ||
6122 | break; | ||
6123 | } | ||
6124 | if (!nimaps) { | ||
6125 | /* nothing there */ | ||
6126 | goto next_block; | ||
6127 | } | ||
6128 | if (imap.br_startblock != DELAYSTARTBLOCK) { | ||
6129 | /* been converted, ignore */ | ||
6130 | goto next_block; | ||
6131 | } | ||
6132 | WARN_ON(imap.br_blockcount == 0); | ||
6133 | |||
6134 | /* | ||
6135 | * Note: while we initialise the firstblock/flist pair, they | ||
6136 | * should never be used because blocks should never be | ||
6137 | * allocated or freed for a delalloc extent and hence we need | ||
6138 | * don't cancel or finish them after the xfs_bunmapi() call. | ||
6139 | */ | ||
6140 | xfs_bmap_init(&flist, &firstblock); | ||
6141 | error = xfs_bunmapi(NULL, ip, start_fsb, 1, 0, 1, &firstblock, | ||
6142 | &flist, &done); | ||
6143 | if (error) | ||
6144 | break; | ||
6145 | |||
6146 | ASSERT(!flist.xbf_count && !flist.xbf_first); | ||
6147 | next_block: | ||
6148 | start_fsb++; | ||
6149 | remaining--; | ||
6150 | } while(remaining > 0); | ||
6151 | |||
6152 | return error; | ||
6153 | } | ||
diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h index 71ec9b6ecdfc..3651191daea1 100644 --- a/fs/xfs/xfs_bmap.h +++ b/fs/xfs/xfs_bmap.h | |||
@@ -394,6 +394,11 @@ xfs_bmap_count_blocks( | |||
394 | int whichfork, | 394 | int whichfork, |
395 | int *count); | 395 | int *count); |
396 | 396 | ||
397 | int | ||
398 | xfs_bmap_punch_delalloc_range( | ||
399 | struct xfs_inode *ip, | ||
400 | xfs_fileoff_t start_fsb, | ||
401 | xfs_fileoff_t length); | ||
397 | #endif /* __KERNEL__ */ | 402 | #endif /* __KERNEL__ */ |
398 | 403 | ||
399 | #endif /* __XFS_BMAP_H__ */ | 404 | #endif /* __XFS_BMAP_H__ */ |
diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c index 3b9582c60a22..e60490bc00a6 100644 --- a/fs/xfs/xfs_dfrag.c +++ b/fs/xfs/xfs_dfrag.c | |||
@@ -377,6 +377,19 @@ xfs_swap_extents( | |||
377 | ip->i_d.di_format = tip->i_d.di_format; | 377 | ip->i_d.di_format = tip->i_d.di_format; |
378 | tip->i_d.di_format = tmp; | 378 | tip->i_d.di_format = tmp; |
379 | 379 | ||
380 | /* | ||
381 | * The extents in the source inode could still contain speculative | ||
382 | * preallocation beyond EOF (e.g. the file is open but not modified | ||
383 | * while defrag is in progress). In that case, we need to copy over the | ||
384 | * number of delalloc blocks the data fork in the source inode is | ||
385 | * tracking beyond EOF so that when the fork is truncated away when the | ||
386 | * temporary inode is unlinked we don't underrun the i_delayed_blks | ||
387 | * counter on that inode. | ||
388 | */ | ||
389 | ASSERT(tip->i_delayed_blks == 0); | ||
390 | tip->i_delayed_blks = ip->i_delayed_blks; | ||
391 | ip->i_delayed_blks = 0; | ||
392 | |||
380 | ilf_fields = XFS_ILOG_CORE; | 393 | ilf_fields = XFS_ILOG_CORE; |
381 | 394 | ||
382 | switch(ip->i_d.di_format) { | 395 | switch(ip->i_d.di_format) { |
diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c index ed9990267661..c78cc6a3d87c 100644 --- a/fs/xfs/xfs_error.c +++ b/fs/xfs/xfs_error.c | |||
@@ -58,6 +58,7 @@ xfs_error_trap(int e) | |||
58 | int xfs_etest[XFS_NUM_INJECT_ERROR]; | 58 | int xfs_etest[XFS_NUM_INJECT_ERROR]; |
59 | int64_t xfs_etest_fsid[XFS_NUM_INJECT_ERROR]; | 59 | int64_t xfs_etest_fsid[XFS_NUM_INJECT_ERROR]; |
60 | char * xfs_etest_fsname[XFS_NUM_INJECT_ERROR]; | 60 | char * xfs_etest_fsname[XFS_NUM_INJECT_ERROR]; |
61 | int xfs_error_test_active; | ||
61 | 62 | ||
62 | int | 63 | int |
63 | xfs_error_test(int error_tag, int *fsidp, char *expression, | 64 | xfs_error_test(int error_tag, int *fsidp, char *expression, |
@@ -108,6 +109,7 @@ xfs_errortag_add(int error_tag, xfs_mount_t *mp) | |||
108 | len = strlen(mp->m_fsname); | 109 | len = strlen(mp->m_fsname); |
109 | xfs_etest_fsname[i] = kmem_alloc(len + 1, KM_SLEEP); | 110 | xfs_etest_fsname[i] = kmem_alloc(len + 1, KM_SLEEP); |
110 | strcpy(xfs_etest_fsname[i], mp->m_fsname); | 111 | strcpy(xfs_etest_fsname[i], mp->m_fsname); |
112 | xfs_error_test_active++; | ||
111 | return 0; | 113 | return 0; |
112 | } | 114 | } |
113 | } | 115 | } |
@@ -137,6 +139,7 @@ xfs_errortag_clearall(xfs_mount_t *mp, int loud) | |||
137 | xfs_etest_fsid[i] = 0LL; | 139 | xfs_etest_fsid[i] = 0LL; |
138 | kmem_free(xfs_etest_fsname[i]); | 140 | kmem_free(xfs_etest_fsname[i]); |
139 | xfs_etest_fsname[i] = NULL; | 141 | xfs_etest_fsname[i] = NULL; |
142 | xfs_error_test_active--; | ||
140 | } | 143 | } |
141 | } | 144 | } |
142 | 145 | ||
diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h index c2c1a072bb82..f338847f80b8 100644 --- a/fs/xfs/xfs_error.h +++ b/fs/xfs/xfs_error.h | |||
@@ -127,13 +127,14 @@ extern void xfs_corruption_error(const char *tag, int level, | |||
127 | #define XFS_RANDOM_BMAPIFORMAT XFS_RANDOM_DEFAULT | 127 | #define XFS_RANDOM_BMAPIFORMAT XFS_RANDOM_DEFAULT |
128 | 128 | ||
129 | #ifdef DEBUG | 129 | #ifdef DEBUG |
130 | extern int xfs_error_test_active; | ||
130 | extern int xfs_error_test(int, int *, char *, int, char *, unsigned long); | 131 | extern int xfs_error_test(int, int *, char *, int, char *, unsigned long); |
131 | 132 | ||
132 | #define XFS_NUM_INJECT_ERROR 10 | 133 | #define XFS_NUM_INJECT_ERROR 10 |
133 | #define XFS_TEST_ERROR(expr, mp, tag, rf) \ | 134 | #define XFS_TEST_ERROR(expr, mp, tag, rf) \ |
134 | ((expr) || \ | 135 | ((expr) || (xfs_error_test_active && \ |
135 | xfs_error_test((tag), (mp)->m_fixedfsid, "expr", __LINE__, __FILE__, \ | 136 | xfs_error_test((tag), (mp)->m_fixedfsid, "expr", __LINE__, __FILE__, \ |
136 | (rf))) | 137 | (rf)))) |
137 | 138 | ||
138 | extern int xfs_errortag_add(int error_tag, xfs_mount_t *mp); | 139 | extern int xfs_errortag_add(int error_tag, xfs_mount_t *mp); |
139 | extern int xfs_errortag_clearall(xfs_mount_t *mp, int loud); | 140 | extern int xfs_errortag_clearall(xfs_mount_t *mp, int loud); |
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index c7ac020705df..7c8d30c453c3 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c | |||
@@ -657,18 +657,37 @@ xfs_inode_item_unlock( | |||
657 | } | 657 | } |
658 | 658 | ||
659 | /* | 659 | /* |
660 | * This is called to find out where the oldest active copy of the | 660 | * This is called to find out where the oldest active copy of the inode log |
661 | * inode log item in the on disk log resides now that the last log | 661 | * item in the on disk log resides now that the last log write of it completed |
662 | * write of it completed at the given lsn. Since we always re-log | 662 | * at the given lsn. Since we always re-log all dirty data in an inode, the |
663 | * all dirty data in an inode, the latest copy in the on disk log | 663 | * latest copy in the on disk log is the only one that matters. Therefore, |
664 | * is the only one that matters. Therefore, simply return the | 664 | * simply return the given lsn. |
665 | * given lsn. | 665 | * |
666 | * If the inode has been marked stale because the cluster is being freed, we | ||
667 | * don't want to (re-)insert this inode into the AIL. There is a race condition | ||
668 | * where the cluster buffer may be unpinned before the inode is inserted into | ||
669 | * the AIL during transaction committed processing. If the buffer is unpinned | ||
670 | * before the inode item has been committed and inserted, then it is possible | ||
671 | * for the buffer to be written and IO completions before the inode is inserted | ||
672 | * into the AIL. In that case, we'd be inserting a clean, stale inode into the | ||
673 | * AIL which will never get removed. It will, however, get reclaimed which | ||
674 | * triggers an assert in xfs_inode_free() complaining about freein an inode | ||
675 | * still in the AIL. | ||
676 | * | ||
677 | * To avoid this, return a lower LSN than the one passed in so that the | ||
678 | * transaction committed code will not move the inode forward in the AIL but | ||
679 | * will still unpin it properly. | ||
666 | */ | 680 | */ |
667 | STATIC xfs_lsn_t | 681 | STATIC xfs_lsn_t |
668 | xfs_inode_item_committed( | 682 | xfs_inode_item_committed( |
669 | struct xfs_log_item *lip, | 683 | struct xfs_log_item *lip, |
670 | xfs_lsn_t lsn) | 684 | xfs_lsn_t lsn) |
671 | { | 685 | { |
686 | struct xfs_inode_log_item *iip = INODE_ITEM(lip); | ||
687 | struct xfs_inode *ip = iip->ili_inode; | ||
688 | |||
689 | if (xfs_iflags_test(ip, XFS_ISTALE)) | ||
690 | return lsn - 1; | ||
672 | return lsn; | 691 | return lsn; |
673 | } | 692 | } |
674 | 693 | ||
diff --git a/fs/xfs/xfs_rename.c b/fs/xfs/xfs_rename.c index d2af0a8381a6..77a59891734e 100644 --- a/fs/xfs/xfs_rename.c +++ b/fs/xfs/xfs_rename.c | |||
@@ -297,6 +297,7 @@ xfs_rename( | |||
297 | * it and some incremental backup programs won't work without it. | 297 | * it and some incremental backup programs won't work without it. |
298 | */ | 298 | */ |
299 | xfs_trans_ichgtime(tp, src_ip, XFS_ICHGTIME_CHG); | 299 | xfs_trans_ichgtime(tp, src_ip, XFS_ICHGTIME_CHG); |
300 | xfs_trans_log_inode(tp, src_ip, XFS_ILOG_CORE); | ||
300 | 301 | ||
301 | /* | 302 | /* |
302 | * Adjust the link count on src_dp. This is necessary when | 303 | * Adjust the link count on src_dp. This is necessary when |