diff options
author | Colin Cross <ccross@android.com> | 2011-03-03 17:17:49 -0500 |
---|---|---|
committer | Colin Cross <ccross@android.com> | 2011-03-03 17:17:49 -0500 |
commit | c871fe663a6368fd0e98f5a3bfd81b0b9c591266 (patch) | |
tree | d09c244e94c09f985caf259c434c7eda8ff53229 /fs | |
parent | d5fdafd38ca0c28c4648909ce0afd0a5420309ca (diff) | |
parent | db811ca0f48578f9940f49f284ac81e336b264ad (diff) |
Merge branch 'for-2639/i2c/i2c-tegra' of git://git.fluff.org/bjdooks/linux into for-next-i2c
Diffstat (limited to 'fs')
45 files changed, 623 insertions, 453 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c index 333a7bb4cb9c..4fb8a3431531 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
@@ -1215,12 +1215,6 @@ int blkdev_get(struct block_device *bdev, fmode_t mode, void *holder) | |||
1215 | 1215 | ||
1216 | res = __blkdev_get(bdev, mode, 0); | 1216 | res = __blkdev_get(bdev, mode, 0); |
1217 | 1217 | ||
1218 | /* __blkdev_get() may alter read only status, check it afterwards */ | ||
1219 | if (!res && (mode & FMODE_WRITE) && bdev_read_only(bdev)) { | ||
1220 | __blkdev_put(bdev, mode, 0); | ||
1221 | res = -EACCES; | ||
1222 | } | ||
1223 | |||
1224 | if (whole) { | 1218 | if (whole) { |
1225 | /* finish claiming */ | 1219 | /* finish claiming */ |
1226 | mutex_lock(&bdev->bd_mutex); | 1220 | mutex_lock(&bdev->bd_mutex); |
@@ -1298,6 +1292,11 @@ struct block_device *blkdev_get_by_path(const char *path, fmode_t mode, | |||
1298 | if (err) | 1292 | if (err) |
1299 | return ERR_PTR(err); | 1293 | return ERR_PTR(err); |
1300 | 1294 | ||
1295 | if ((mode & FMODE_WRITE) && bdev_read_only(bdev)) { | ||
1296 | blkdev_put(bdev, mode); | ||
1297 | return ERR_PTR(-EACCES); | ||
1298 | } | ||
1299 | |||
1301 | return bdev; | 1300 | return bdev; |
1302 | } | 1301 | } |
1303 | EXPORT_SYMBOL(blkdev_get_by_path); | 1302 | EXPORT_SYMBOL(blkdev_get_by_path); |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index fdce8799b98d..e1aa8d607bc7 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -359,10 +359,14 @@ static int csum_dirty_buffer(struct btrfs_root *root, struct page *page) | |||
359 | 359 | ||
360 | tree = &BTRFS_I(page->mapping->host)->io_tree; | 360 | tree = &BTRFS_I(page->mapping->host)->io_tree; |
361 | 361 | ||
362 | if (page->private == EXTENT_PAGE_PRIVATE) | 362 | if (page->private == EXTENT_PAGE_PRIVATE) { |
363 | WARN_ON(1); | ||
363 | goto out; | 364 | goto out; |
364 | if (!page->private) | 365 | } |
366 | if (!page->private) { | ||
367 | WARN_ON(1); | ||
365 | goto out; | 368 | goto out; |
369 | } | ||
366 | len = page->private >> 2; | 370 | len = page->private >> 2; |
367 | WARN_ON(len == 0); | 371 | WARN_ON(len == 0); |
368 | 372 | ||
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 4e7e012ad667..f3c96fc01439 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -6583,7 +6583,7 @@ static noinline int relocate_data_extent(struct inode *reloc_inode, | |||
6583 | u64 end = start + extent_key->offset - 1; | 6583 | u64 end = start + extent_key->offset - 1; |
6584 | 6584 | ||
6585 | em = alloc_extent_map(GFP_NOFS); | 6585 | em = alloc_extent_map(GFP_NOFS); |
6586 | BUG_ON(!em || IS_ERR(em)); | 6586 | BUG_ON(!em); |
6587 | 6587 | ||
6588 | em->start = start; | 6588 | em->start = start; |
6589 | em->len = extent_key->offset; | 6589 | em->len = extent_key->offset; |
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 5e76a474cb7e..92ac5192c518 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
@@ -1946,6 +1946,7 @@ void set_page_extent_mapped(struct page *page) | |||
1946 | 1946 | ||
1947 | static void set_page_extent_head(struct page *page, unsigned long len) | 1947 | static void set_page_extent_head(struct page *page, unsigned long len) |
1948 | { | 1948 | { |
1949 | WARN_ON(!PagePrivate(page)); | ||
1949 | set_page_private(page, EXTENT_PAGE_PRIVATE_FIRST_PAGE | len << 2); | 1950 | set_page_private(page, EXTENT_PAGE_PRIVATE_FIRST_PAGE | len << 2); |
1950 | } | 1951 | } |
1951 | 1952 | ||
@@ -2821,9 +2822,17 @@ int try_release_extent_state(struct extent_map_tree *map, | |||
2821 | * at this point we can safely clear everything except the | 2822 | * at this point we can safely clear everything except the |
2822 | * locked bit and the nodatasum bit | 2823 | * locked bit and the nodatasum bit |
2823 | */ | 2824 | */ |
2824 | clear_extent_bit(tree, start, end, | 2825 | ret = clear_extent_bit(tree, start, end, |
2825 | ~(EXTENT_LOCKED | EXTENT_NODATASUM), | 2826 | ~(EXTENT_LOCKED | EXTENT_NODATASUM), |
2826 | 0, 0, NULL, mask); | 2827 | 0, 0, NULL, mask); |
2828 | |||
2829 | /* if clear_extent_bit failed for enomem reasons, | ||
2830 | * we can't allow the release to continue. | ||
2831 | */ | ||
2832 | if (ret < 0) | ||
2833 | ret = 0; | ||
2834 | else | ||
2835 | ret = 1; | ||
2827 | } | 2836 | } |
2828 | return ret; | 2837 | return ret; |
2829 | } | 2838 | } |
@@ -3194,7 +3203,13 @@ struct extent_buffer *alloc_extent_buffer(struct extent_io_tree *tree, | |||
3194 | } | 3203 | } |
3195 | if (!PageUptodate(p)) | 3204 | if (!PageUptodate(p)) |
3196 | uptodate = 0; | 3205 | uptodate = 0; |
3197 | unlock_page(p); | 3206 | |
3207 | /* | ||
3208 | * see below about how we avoid a nasty race with release page | ||
3209 | * and why we unlock later | ||
3210 | */ | ||
3211 | if (i != 0) | ||
3212 | unlock_page(p); | ||
3198 | } | 3213 | } |
3199 | if (uptodate) | 3214 | if (uptodate) |
3200 | set_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags); | 3215 | set_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags); |
@@ -3218,9 +3233,26 @@ struct extent_buffer *alloc_extent_buffer(struct extent_io_tree *tree, | |||
3218 | atomic_inc(&eb->refs); | 3233 | atomic_inc(&eb->refs); |
3219 | spin_unlock(&tree->buffer_lock); | 3234 | spin_unlock(&tree->buffer_lock); |
3220 | radix_tree_preload_end(); | 3235 | radix_tree_preload_end(); |
3236 | |||
3237 | /* | ||
3238 | * there is a race where release page may have | ||
3239 | * tried to find this extent buffer in the radix | ||
3240 | * but failed. It will tell the VM it is safe to | ||
3241 | * reclaim the, and it will clear the page private bit. | ||
3242 | * We must make sure to set the page private bit properly | ||
3243 | * after the extent buffer is in the radix tree so | ||
3244 | * it doesn't get lost | ||
3245 | */ | ||
3246 | set_page_extent_mapped(eb->first_page); | ||
3247 | set_page_extent_head(eb->first_page, eb->len); | ||
3248 | if (!page0) | ||
3249 | unlock_page(eb->first_page); | ||
3221 | return eb; | 3250 | return eb; |
3222 | 3251 | ||
3223 | free_eb: | 3252 | free_eb: |
3253 | if (eb->first_page && !page0) | ||
3254 | unlock_page(eb->first_page); | ||
3255 | |||
3224 | if (!atomic_dec_and_test(&eb->refs)) | 3256 | if (!atomic_dec_and_test(&eb->refs)) |
3225 | return exists; | 3257 | return exists; |
3226 | btrfs_release_extent_buffer(eb); | 3258 | btrfs_release_extent_buffer(eb); |
@@ -3271,10 +3303,11 @@ int clear_extent_buffer_dirty(struct extent_io_tree *tree, | |||
3271 | continue; | 3303 | continue; |
3272 | 3304 | ||
3273 | lock_page(page); | 3305 | lock_page(page); |
3306 | WARN_ON(!PagePrivate(page)); | ||
3307 | |||
3308 | set_page_extent_mapped(page); | ||
3274 | if (i == 0) | 3309 | if (i == 0) |
3275 | set_page_extent_head(page, eb->len); | 3310 | set_page_extent_head(page, eb->len); |
3276 | else | ||
3277 | set_page_private(page, EXTENT_PAGE_PRIVATE); | ||
3278 | 3311 | ||
3279 | clear_page_dirty_for_io(page); | 3312 | clear_page_dirty_for_io(page); |
3280 | spin_lock_irq(&page->mapping->tree_lock); | 3313 | spin_lock_irq(&page->mapping->tree_lock); |
@@ -3464,6 +3497,13 @@ int read_extent_buffer_pages(struct extent_io_tree *tree, | |||
3464 | 3497 | ||
3465 | for (i = start_i; i < num_pages; i++) { | 3498 | for (i = start_i; i < num_pages; i++) { |
3466 | page = extent_buffer_page(eb, i); | 3499 | page = extent_buffer_page(eb, i); |
3500 | |||
3501 | WARN_ON(!PagePrivate(page)); | ||
3502 | |||
3503 | set_page_extent_mapped(page); | ||
3504 | if (i == 0) | ||
3505 | set_page_extent_head(page, eb->len); | ||
3506 | |||
3467 | if (inc_all_pages) | 3507 | if (inc_all_pages) |
3468 | page_cache_get(page); | 3508 | page_cache_get(page); |
3469 | if (!PageUptodate(page)) { | 3509 | if (!PageUptodate(page)) { |
diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c index b0e1fce12530..2b6c12e983b3 100644 --- a/fs/btrfs/extent_map.c +++ b/fs/btrfs/extent_map.c | |||
@@ -51,8 +51,8 @@ struct extent_map *alloc_extent_map(gfp_t mask) | |||
51 | { | 51 | { |
52 | struct extent_map *em; | 52 | struct extent_map *em; |
53 | em = kmem_cache_alloc(extent_map_cache, mask); | 53 | em = kmem_cache_alloc(extent_map_cache, mask); |
54 | if (!em || IS_ERR(em)) | 54 | if (!em) |
55 | return em; | 55 | return NULL; |
56 | em->in_tree = 0; | 56 | em->in_tree = 0; |
57 | em->flags = 0; | 57 | em->flags = 0; |
58 | em->compress_type = BTRFS_COMPRESS_NONE; | 58 | em->compress_type = BTRFS_COMPRESS_NONE; |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index c1d3a818731a..7084140d5940 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -186,6 +186,7 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end, | |||
186 | split = alloc_extent_map(GFP_NOFS); | 186 | split = alloc_extent_map(GFP_NOFS); |
187 | if (!split2) | 187 | if (!split2) |
188 | split2 = alloc_extent_map(GFP_NOFS); | 188 | split2 = alloc_extent_map(GFP_NOFS); |
189 | BUG_ON(!split || !split2); | ||
189 | 190 | ||
190 | write_lock(&em_tree->lock); | 191 | write_lock(&em_tree->lock); |
191 | em = lookup_extent_mapping(em_tree, start, len); | 192 | em = lookup_extent_mapping(em_tree, start, len); |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index bcc461a9695f..fb9bd7832b6d 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -644,6 +644,7 @@ retry: | |||
644 | async_extent->ram_size - 1, 0); | 644 | async_extent->ram_size - 1, 0); |
645 | 645 | ||
646 | em = alloc_extent_map(GFP_NOFS); | 646 | em = alloc_extent_map(GFP_NOFS); |
647 | BUG_ON(!em); | ||
647 | em->start = async_extent->start; | 648 | em->start = async_extent->start; |
648 | em->len = async_extent->ram_size; | 649 | em->len = async_extent->ram_size; |
649 | em->orig_start = em->start; | 650 | em->orig_start = em->start; |
@@ -820,6 +821,7 @@ static noinline int cow_file_range(struct inode *inode, | |||
820 | BUG_ON(ret); | 821 | BUG_ON(ret); |
821 | 822 | ||
822 | em = alloc_extent_map(GFP_NOFS); | 823 | em = alloc_extent_map(GFP_NOFS); |
824 | BUG_ON(!em); | ||
823 | em->start = start; | 825 | em->start = start; |
824 | em->orig_start = em->start; | 826 | em->orig_start = em->start; |
825 | ram_size = ins.offset; | 827 | ram_size = ins.offset; |
@@ -1169,6 +1171,7 @@ out_check: | |||
1169 | struct extent_map_tree *em_tree; | 1171 | struct extent_map_tree *em_tree; |
1170 | em_tree = &BTRFS_I(inode)->extent_tree; | 1172 | em_tree = &BTRFS_I(inode)->extent_tree; |
1171 | em = alloc_extent_map(GFP_NOFS); | 1173 | em = alloc_extent_map(GFP_NOFS); |
1174 | BUG_ON(!em); | ||
1172 | em->start = cur_offset; | 1175 | em->start = cur_offset; |
1173 | em->orig_start = em->start; | 1176 | em->orig_start = em->start; |
1174 | em->len = num_bytes; | 1177 | em->len = num_bytes; |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 02d224e8c83f..be2d4f6aaa5e 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -2208,7 +2208,7 @@ long btrfs_ioctl_space_info(struct btrfs_root *root, void __user *arg) | |||
2208 | int num_types = 4; | 2208 | int num_types = 4; |
2209 | int alloc_size; | 2209 | int alloc_size; |
2210 | int ret = 0; | 2210 | int ret = 0; |
2211 | int slot_count = 0; | 2211 | u64 slot_count = 0; |
2212 | int i, c; | 2212 | int i, c; |
2213 | 2213 | ||
2214 | if (copy_from_user(&space_args, | 2214 | if (copy_from_user(&space_args, |
@@ -2247,7 +2247,7 @@ long btrfs_ioctl_space_info(struct btrfs_root *root, void __user *arg) | |||
2247 | goto out; | 2247 | goto out; |
2248 | } | 2248 | } |
2249 | 2249 | ||
2250 | slot_count = min_t(int, space_args.space_slots, slot_count); | 2250 | slot_count = min_t(u64, space_args.space_slots, slot_count); |
2251 | 2251 | ||
2252 | alloc_size = sizeof(*dest) * slot_count; | 2252 | alloc_size = sizeof(*dest) * slot_count; |
2253 | 2253 | ||
@@ -2267,6 +2267,9 @@ long btrfs_ioctl_space_info(struct btrfs_root *root, void __user *arg) | |||
2267 | for (i = 0; i < num_types; i++) { | 2267 | for (i = 0; i < num_types; i++) { |
2268 | struct btrfs_space_info *tmp; | 2268 | struct btrfs_space_info *tmp; |
2269 | 2269 | ||
2270 | if (!slot_count) | ||
2271 | break; | ||
2272 | |||
2270 | info = NULL; | 2273 | info = NULL; |
2271 | rcu_read_lock(); | 2274 | rcu_read_lock(); |
2272 | list_for_each_entry_rcu(tmp, &root->fs_info->space_info, | 2275 | list_for_each_entry_rcu(tmp, &root->fs_info->space_info, |
@@ -2288,7 +2291,10 @@ long btrfs_ioctl_space_info(struct btrfs_root *root, void __user *arg) | |||
2288 | memcpy(dest, &space, sizeof(space)); | 2291 | memcpy(dest, &space, sizeof(space)); |
2289 | dest++; | 2292 | dest++; |
2290 | space_args.total_spaces++; | 2293 | space_args.total_spaces++; |
2294 | slot_count--; | ||
2291 | } | 2295 | } |
2296 | if (!slot_count) | ||
2297 | break; | ||
2292 | } | 2298 | } |
2293 | up_read(&info->groups_sem); | 2299 | up_read(&info->groups_sem); |
2294 | } | 2300 | } |
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 1f5556acb530..0825e4ed9447 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c | |||
@@ -1157,6 +1157,7 @@ static int clone_backref_node(struct btrfs_trans_handle *trans, | |||
1157 | new_node->bytenr = dest->node->start; | 1157 | new_node->bytenr = dest->node->start; |
1158 | new_node->level = node->level; | 1158 | new_node->level = node->level; |
1159 | new_node->lowest = node->lowest; | 1159 | new_node->lowest = node->lowest; |
1160 | new_node->checked = 1; | ||
1160 | new_node->root = dest; | 1161 | new_node->root = dest; |
1161 | 1162 | ||
1162 | if (!node->lowest) { | 1163 | if (!node->lowest) { |
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 2636a051e4b2..af7dbca15276 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -1605,12 +1605,14 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) | |||
1605 | 1605 | ||
1606 | ret = find_next_devid(root, &device->devid); | 1606 | ret = find_next_devid(root, &device->devid); |
1607 | if (ret) { | 1607 | if (ret) { |
1608 | kfree(device->name); | ||
1608 | kfree(device); | 1609 | kfree(device); |
1609 | goto error; | 1610 | goto error; |
1610 | } | 1611 | } |
1611 | 1612 | ||
1612 | trans = btrfs_start_transaction(root, 0); | 1613 | trans = btrfs_start_transaction(root, 0); |
1613 | if (IS_ERR(trans)) { | 1614 | if (IS_ERR(trans)) { |
1615 | kfree(device->name); | ||
1614 | kfree(device); | 1616 | kfree(device); |
1615 | ret = PTR_ERR(trans); | 1617 | ret = PTR_ERR(trans); |
1616 | goto error; | 1618 | goto error; |
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 0bc68de8edd7..f0aef787a102 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c | |||
@@ -60,6 +60,7 @@ int ceph_init_dentry(struct dentry *dentry) | |||
60 | } | 60 | } |
61 | di->dentry = dentry; | 61 | di->dentry = dentry; |
62 | di->lease_session = NULL; | 62 | di->lease_session = NULL; |
63 | di->parent_inode = igrab(dentry->d_parent->d_inode); | ||
63 | dentry->d_fsdata = di; | 64 | dentry->d_fsdata = di; |
64 | dentry->d_time = jiffies; | 65 | dentry->d_time = jiffies; |
65 | ceph_dentry_lru_add(dentry); | 66 | ceph_dentry_lru_add(dentry); |
@@ -1033,7 +1034,7 @@ static void ceph_dentry_release(struct dentry *dentry) | |||
1033 | u64 snapid = CEPH_NOSNAP; | 1034 | u64 snapid = CEPH_NOSNAP; |
1034 | 1035 | ||
1035 | if (!IS_ROOT(dentry)) { | 1036 | if (!IS_ROOT(dentry)) { |
1036 | parent_inode = dentry->d_parent->d_inode; | 1037 | parent_inode = di->parent_inode; |
1037 | if (parent_inode) | 1038 | if (parent_inode) |
1038 | snapid = ceph_snap(parent_inode); | 1039 | snapid = ceph_snap(parent_inode); |
1039 | } | 1040 | } |
@@ -1058,6 +1059,8 @@ static void ceph_dentry_release(struct dentry *dentry) | |||
1058 | kmem_cache_free(ceph_dentry_cachep, di); | 1059 | kmem_cache_free(ceph_dentry_cachep, di); |
1059 | dentry->d_fsdata = NULL; | 1060 | dentry->d_fsdata = NULL; |
1060 | } | 1061 | } |
1062 | if (parent_inode) | ||
1063 | iput(parent_inode); | ||
1061 | } | 1064 | } |
1062 | 1065 | ||
1063 | static int ceph_snapdir_d_revalidate(struct dentry *dentry, | 1066 | static int ceph_snapdir_d_revalidate(struct dentry *dentry, |
diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c index 39c243acd062..f40b9139e437 100644 --- a/fs/ceph/snap.c +++ b/fs/ceph/snap.c | |||
@@ -584,10 +584,14 @@ static void queue_realm_cap_snaps(struct ceph_snap_realm *realm) | |||
584 | if (lastinode) | 584 | if (lastinode) |
585 | iput(lastinode); | 585 | iput(lastinode); |
586 | 586 | ||
587 | dout("queue_realm_cap_snaps %p %llx children\n", realm, realm->ino); | 587 | list_for_each_entry(child, &realm->children, child_item) { |
588 | list_for_each_entry(child, &realm->children, child_item) | 588 | dout("queue_realm_cap_snaps %p %llx queue child %p %llx\n", |
589 | queue_realm_cap_snaps(child); | 589 | realm, realm->ino, child, child->ino); |
590 | list_del_init(&child->dirty_item); | ||
591 | list_add(&child->dirty_item, &realm->dirty_item); | ||
592 | } | ||
590 | 593 | ||
594 | list_del_init(&realm->dirty_item); | ||
591 | dout("queue_realm_cap_snaps %p %llx done\n", realm, realm->ino); | 595 | dout("queue_realm_cap_snaps %p %llx done\n", realm, realm->ino); |
592 | } | 596 | } |
593 | 597 | ||
@@ -683,7 +687,9 @@ more: | |||
683 | * queue cap snaps _after_ we've built the new snap contexts, | 687 | * queue cap snaps _after_ we've built the new snap contexts, |
684 | * so that i_head_snapc can be set appropriately. | 688 | * so that i_head_snapc can be set appropriately. |
685 | */ | 689 | */ |
686 | list_for_each_entry(realm, &dirty_realms, dirty_item) { | 690 | while (!list_empty(&dirty_realms)) { |
691 | realm = list_first_entry(&dirty_realms, struct ceph_snap_realm, | ||
692 | dirty_item); | ||
687 | queue_realm_cap_snaps(realm); | 693 | queue_realm_cap_snaps(realm); |
688 | } | 694 | } |
689 | 695 | ||
diff --git a/fs/ceph/super.h b/fs/ceph/super.h index 20b907d76ae2..88fcaa21b801 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h | |||
@@ -207,6 +207,7 @@ struct ceph_dentry_info { | |||
207 | struct dentry *dentry; | 207 | struct dentry *dentry; |
208 | u64 time; | 208 | u64 time; |
209 | u64 offset; | 209 | u64 offset; |
210 | struct inode *parent_inode; | ||
210 | }; | 211 | }; |
211 | 212 | ||
212 | struct ceph_inode_xattrs_info { | 213 | struct ceph_inode_xattrs_info { |
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 4a3330235d55..a9371b6578c0 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
@@ -127,5 +127,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); | |||
127 | extern const struct export_operations cifs_export_ops; | 127 | extern const struct export_operations cifs_export_ops; |
128 | #endif /* EXPERIMENTAL */ | 128 | #endif /* EXPERIMENTAL */ |
129 | 129 | ||
130 | #define CIFS_VERSION "1.70" | 130 | #define CIFS_VERSION "1.71" |
131 | #endif /* _CIFSFS_H */ | 131 | #endif /* _CIFSFS_H */ |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index edd5b29b53c9..17afb0fbcaed 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -188,6 +188,8 @@ struct TCP_Server_Info { | |||
188 | /* multiplexed reads or writes */ | 188 | /* multiplexed reads or writes */ |
189 | unsigned int maxBuf; /* maxBuf specifies the maximum */ | 189 | unsigned int maxBuf; /* maxBuf specifies the maximum */ |
190 | /* message size the server can send or receive for non-raw SMBs */ | 190 | /* message size the server can send or receive for non-raw SMBs */ |
191 | /* maxBuf is returned by SMB NegotiateProtocol so maxBuf is only 0 */ | ||
192 | /* when socket is setup (and during reconnect) before NegProt sent */ | ||
191 | unsigned int max_rw; /* maxRw specifies the maximum */ | 193 | unsigned int max_rw; /* maxRw specifies the maximum */ |
192 | /* message size the server can send or receive for */ | 194 | /* message size the server can send or receive for */ |
193 | /* SMB_COM_WRITE_RAW or SMB_COM_READ_RAW. */ | 195 | /* SMB_COM_WRITE_RAW or SMB_COM_READ_RAW. */ |
@@ -652,7 +654,7 @@ static inline void free_dfs_info_array(struct dfs_info3_param *param, | |||
652 | #define MID_REQUEST_SUBMITTED 2 | 654 | #define MID_REQUEST_SUBMITTED 2 |
653 | #define MID_RESPONSE_RECEIVED 4 | 655 | #define MID_RESPONSE_RECEIVED 4 |
654 | #define MID_RETRY_NEEDED 8 /* session closed while this request out */ | 656 | #define MID_RETRY_NEEDED 8 /* session closed while this request out */ |
655 | #define MID_NO_RESP_NEEDED 0x10 | 657 | #define MID_RESPONSE_MALFORMED 0x10 |
656 | 658 | ||
657 | /* Types of response buffer returned from SendReceive2 */ | 659 | /* Types of response buffer returned from SendReceive2 */ |
658 | #define CIFS_NO_BUFFER 0 /* Response buffer not returned */ | 660 | #define CIFS_NO_BUFFER 0 /* Response buffer not returned */ |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 257b6d895e20..8d6c17ab593d 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -338,10 +338,11 @@ cifs_echo_request(struct work_struct *work) | |||
338 | struct TCP_Server_Info, echo.work); | 338 | struct TCP_Server_Info, echo.work); |
339 | 339 | ||
340 | /* | 340 | /* |
341 | * We cannot send an echo until the NEGOTIATE_PROTOCOL request is done. | 341 | * We cannot send an echo until the NEGOTIATE_PROTOCOL request is |
342 | * Also, no need to ping if we got a response recently | 342 | * done, which is indicated by maxBuf != 0. Also, no need to ping if |
343 | * we got a response recently | ||
343 | */ | 344 | */ |
344 | if (server->tcpStatus != CifsGood || | 345 | if (server->maxBuf == 0 || |
345 | time_before(jiffies, server->lstrp + SMB_ECHO_INTERVAL - HZ)) | 346 | time_before(jiffies, server->lstrp + SMB_ECHO_INTERVAL - HZ)) |
346 | goto requeue_echo; | 347 | goto requeue_echo; |
347 | 348 | ||
@@ -585,11 +586,20 @@ incomplete_rcv: | |||
585 | total_read += 4; /* account for rfc1002 hdr */ | 586 | total_read += 4; /* account for rfc1002 hdr */ |
586 | 587 | ||
587 | dump_smb(smb_buffer, total_read); | 588 | dump_smb(smb_buffer, total_read); |
588 | if (checkSMB(smb_buffer, smb_buffer->Mid, total_read)) { | 589 | |
590 | /* | ||
591 | * We know that we received enough to get to the MID as we | ||
592 | * checked the pdu_length earlier. Now check to see | ||
593 | * if the rest of the header is OK. We borrow the length | ||
594 | * var for the rest of the loop to avoid a new stack var. | ||
595 | * | ||
596 | * 48 bytes is enough to display the header and a little bit | ||
597 | * into the payload for debugging purposes. | ||
598 | */ | ||
599 | length = checkSMB(smb_buffer, smb_buffer->Mid, total_read); | ||
600 | if (length != 0) | ||
589 | cifs_dump_mem("Bad SMB: ", smb_buffer, | 601 | cifs_dump_mem("Bad SMB: ", smb_buffer, |
590 | total_read < 48 ? total_read : 48); | 602 | min_t(unsigned int, total_read, 48)); |
591 | continue; | ||
592 | } | ||
593 | 603 | ||
594 | mid_entry = NULL; | 604 | mid_entry = NULL; |
595 | server->lstrp = jiffies; | 605 | server->lstrp = jiffies; |
@@ -601,7 +611,8 @@ incomplete_rcv: | |||
601 | if ((mid_entry->mid == smb_buffer->Mid) && | 611 | if ((mid_entry->mid == smb_buffer->Mid) && |
602 | (mid_entry->midState == MID_REQUEST_SUBMITTED) && | 612 | (mid_entry->midState == MID_REQUEST_SUBMITTED) && |
603 | (mid_entry->command == smb_buffer->Command)) { | 613 | (mid_entry->command == smb_buffer->Command)) { |
604 | if (check2ndT2(smb_buffer,server->maxBuf) > 0) { | 614 | if (length == 0 && |
615 | check2ndT2(smb_buffer, server->maxBuf) > 0) { | ||
605 | /* We have a multipart transact2 resp */ | 616 | /* We have a multipart transact2 resp */ |
606 | isMultiRsp = true; | 617 | isMultiRsp = true; |
607 | if (mid_entry->resp_buf) { | 618 | if (mid_entry->resp_buf) { |
@@ -636,7 +647,12 @@ incomplete_rcv: | |||
636 | mid_entry->resp_buf = smb_buffer; | 647 | mid_entry->resp_buf = smb_buffer; |
637 | mid_entry->largeBuf = isLargeBuf; | 648 | mid_entry->largeBuf = isLargeBuf; |
638 | multi_t2_fnd: | 649 | multi_t2_fnd: |
639 | mid_entry->midState = MID_RESPONSE_RECEIVED; | 650 | if (length == 0) |
651 | mid_entry->midState = | ||
652 | MID_RESPONSE_RECEIVED; | ||
653 | else | ||
654 | mid_entry->midState = | ||
655 | MID_RESPONSE_MALFORMED; | ||
640 | #ifdef CONFIG_CIFS_STATS2 | 656 | #ifdef CONFIG_CIFS_STATS2 |
641 | mid_entry->when_received = jiffies; | 657 | mid_entry->when_received = jiffies; |
642 | #endif | 658 | #endif |
@@ -657,6 +673,9 @@ multi_t2_fnd: | |||
657 | else | 673 | else |
658 | smallbuf = NULL; | 674 | smallbuf = NULL; |
659 | } | 675 | } |
676 | } else if (length != 0) { | ||
677 | /* response sanity checks failed */ | ||
678 | continue; | ||
660 | } else if (!is_valid_oplock_break(smb_buffer, server) && | 679 | } else if (!is_valid_oplock_break(smb_buffer, server) && |
661 | !isMultiRsp) { | 680 | !isMultiRsp) { |
662 | cERROR(1, "No task to wake, unknown frame received! " | 681 | cERROR(1, "No task to wake, unknown frame received! " |
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index 8d9189f64477..79f641eeda30 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c | |||
@@ -170,7 +170,7 @@ cifs_convert_address(struct sockaddr *dst, const char *src, int len) | |||
170 | { | 170 | { |
171 | int rc, alen, slen; | 171 | int rc, alen, slen; |
172 | const char *pct; | 172 | const char *pct; |
173 | char *endp, scope_id[13]; | 173 | char scope_id[13]; |
174 | struct sockaddr_in *s4 = (struct sockaddr_in *) dst; | 174 | struct sockaddr_in *s4 = (struct sockaddr_in *) dst; |
175 | struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) dst; | 175 | struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) dst; |
176 | 176 | ||
@@ -197,9 +197,9 @@ cifs_convert_address(struct sockaddr *dst, const char *src, int len) | |||
197 | memcpy(scope_id, pct + 1, slen); | 197 | memcpy(scope_id, pct + 1, slen); |
198 | scope_id[slen] = '\0'; | 198 | scope_id[slen] = '\0'; |
199 | 199 | ||
200 | s6->sin6_scope_id = (u32) simple_strtoul(pct, &endp, 0); | 200 | rc = strict_strtoul(scope_id, 0, |
201 | if (endp != scope_id + slen) | 201 | (unsigned long *)&s6->sin6_scope_id); |
202 | return 0; | 202 | rc = (rc == 0) ? 1 : 0; |
203 | } | 203 | } |
204 | 204 | ||
205 | return rc; | 205 | return rc; |
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 1adc9625a344..16765703131b 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c | |||
@@ -656,13 +656,13 @@ ssetup_ntlmssp_authenticate: | |||
656 | 656 | ||
657 | if (type == LANMAN) { | 657 | if (type == LANMAN) { |
658 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | 658 | #ifdef CONFIG_CIFS_WEAK_PW_HASH |
659 | char lnm_session_key[CIFS_SESS_KEY_SIZE]; | 659 | char lnm_session_key[CIFS_AUTH_RESP_SIZE]; |
660 | 660 | ||
661 | pSMB->req.hdr.Flags2 &= ~SMBFLG2_UNICODE; | 661 | pSMB->req.hdr.Flags2 &= ~SMBFLG2_UNICODE; |
662 | 662 | ||
663 | /* no capabilities flags in old lanman negotiation */ | 663 | /* no capabilities flags in old lanman negotiation */ |
664 | 664 | ||
665 | pSMB->old_req.PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE); | 665 | pSMB->old_req.PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE); |
666 | 666 | ||
667 | /* Calculate hash with password and copy into bcc_ptr. | 667 | /* Calculate hash with password and copy into bcc_ptr. |
668 | * Encryption Key (stored as in cryptkey) gets used if the | 668 | * Encryption Key (stored as in cryptkey) gets used if the |
@@ -675,8 +675,8 @@ ssetup_ntlmssp_authenticate: | |||
675 | true : false, lnm_session_key); | 675 | true : false, lnm_session_key); |
676 | 676 | ||
677 | ses->flags |= CIFS_SES_LANMAN; | 677 | ses->flags |= CIFS_SES_LANMAN; |
678 | memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_SESS_KEY_SIZE); | 678 | memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_AUTH_RESP_SIZE); |
679 | bcc_ptr += CIFS_SESS_KEY_SIZE; | 679 | bcc_ptr += CIFS_AUTH_RESP_SIZE; |
680 | 680 | ||
681 | /* can not sign if LANMAN negotiated so no need | 681 | /* can not sign if LANMAN negotiated so no need |
682 | to calculate signing key? but what if server | 682 | to calculate signing key? but what if server |
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index fbc5aace54b1..46d8756f2b24 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c | |||
@@ -457,6 +457,9 @@ sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server) | |||
457 | case MID_RETRY_NEEDED: | 457 | case MID_RETRY_NEEDED: |
458 | rc = -EAGAIN; | 458 | rc = -EAGAIN; |
459 | break; | 459 | break; |
460 | case MID_RESPONSE_MALFORMED: | ||
461 | rc = -EIO; | ||
462 | break; | ||
460 | default: | 463 | default: |
461 | cERROR(1, "%s: invalid mid state mid=%d state=%d", __func__, | 464 | cERROR(1, "%s: invalid mid state mid=%d state=%d", __func__, |
462 | mid->mid, mid->midState); | 465 | mid->mid, mid->midState); |
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c index 9c64ae9e4c1a..2d8c87b951c2 100644 --- a/fs/dlm/lowcomms.c +++ b/fs/dlm/lowcomms.c | |||
@@ -1468,15 +1468,13 @@ static void work_stop(void) | |||
1468 | 1468 | ||
1469 | static int work_start(void) | 1469 | static int work_start(void) |
1470 | { | 1470 | { |
1471 | recv_workqueue = alloc_workqueue("dlm_recv", WQ_MEM_RECLAIM | | 1471 | recv_workqueue = create_singlethread_workqueue("dlm_recv"); |
1472 | WQ_HIGHPRI | WQ_FREEZEABLE, 0); | ||
1473 | if (!recv_workqueue) { | 1472 | if (!recv_workqueue) { |
1474 | log_print("can't start dlm_recv"); | 1473 | log_print("can't start dlm_recv"); |
1475 | return -ENOMEM; | 1474 | return -ENOMEM; |
1476 | } | 1475 | } |
1477 | 1476 | ||
1478 | send_workqueue = alloc_workqueue("dlm_send", WQ_MEM_RECLAIM | | 1477 | send_workqueue = create_singlethread_workqueue("dlm_send"); |
1479 | WQ_HIGHPRI | WQ_FREEZEABLE, 0); | ||
1480 | if (!send_workqueue) { | 1478 | if (!send_workqueue) { |
1481 | log_print("can't start dlm_send"); | 1479 | log_print("can't start dlm_send"); |
1482 | destroy_workqueue(recv_workqueue); | 1480 | destroy_workqueue(recv_workqueue); |
diff --git a/fs/ecryptfs/dentry.c b/fs/ecryptfs/dentry.c index 6fc4f319b550..534c1d46e69e 100644 --- a/fs/ecryptfs/dentry.c +++ b/fs/ecryptfs/dentry.c | |||
@@ -46,24 +46,28 @@ static int ecryptfs_d_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
46 | { | 46 | { |
47 | struct dentry *lower_dentry; | 47 | struct dentry *lower_dentry; |
48 | struct vfsmount *lower_mnt; | 48 | struct vfsmount *lower_mnt; |
49 | struct dentry *dentry_save; | 49 | struct dentry *dentry_save = NULL; |
50 | struct vfsmount *vfsmount_save; | 50 | struct vfsmount *vfsmount_save = NULL; |
51 | int rc = 1; | 51 | int rc = 1; |
52 | 52 | ||
53 | if (nd->flags & LOOKUP_RCU) | 53 | if (nd && nd->flags & LOOKUP_RCU) |
54 | return -ECHILD; | 54 | return -ECHILD; |
55 | 55 | ||
56 | lower_dentry = ecryptfs_dentry_to_lower(dentry); | 56 | lower_dentry = ecryptfs_dentry_to_lower(dentry); |
57 | lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry); | 57 | lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry); |
58 | if (!lower_dentry->d_op || !lower_dentry->d_op->d_revalidate) | 58 | if (!lower_dentry->d_op || !lower_dentry->d_op->d_revalidate) |
59 | goto out; | 59 | goto out; |
60 | dentry_save = nd->path.dentry; | 60 | if (nd) { |
61 | vfsmount_save = nd->path.mnt; | 61 | dentry_save = nd->path.dentry; |
62 | nd->path.dentry = lower_dentry; | 62 | vfsmount_save = nd->path.mnt; |
63 | nd->path.mnt = lower_mnt; | 63 | nd->path.dentry = lower_dentry; |
64 | nd->path.mnt = lower_mnt; | ||
65 | } | ||
64 | rc = lower_dentry->d_op->d_revalidate(lower_dentry, nd); | 66 | rc = lower_dentry->d_op->d_revalidate(lower_dentry, nd); |
65 | nd->path.dentry = dentry_save; | 67 | if (nd) { |
66 | nd->path.mnt = vfsmount_save; | 68 | nd->path.dentry = dentry_save; |
69 | nd->path.mnt = vfsmount_save; | ||
70 | } | ||
67 | if (dentry->d_inode) { | 71 | if (dentry->d_inode) { |
68 | struct inode *lower_inode = | 72 | struct inode *lower_inode = |
69 | ecryptfs_inode_to_lower(dentry->d_inode); | 73 | ecryptfs_inode_to_lower(dentry->d_inode); |
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index dbc84ed96336..e00753496e3e 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h | |||
@@ -632,8 +632,7 @@ int ecryptfs_interpose(struct dentry *hidden_dentry, | |||
632 | u32 flags); | 632 | u32 flags); |
633 | int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, | 633 | int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, |
634 | struct dentry *lower_dentry, | 634 | struct dentry *lower_dentry, |
635 | struct inode *ecryptfs_dir_inode, | 635 | struct inode *ecryptfs_dir_inode); |
636 | struct nameidata *ecryptfs_nd); | ||
637 | int ecryptfs_decode_and_decrypt_filename(char **decrypted_name, | 636 | int ecryptfs_decode_and_decrypt_filename(char **decrypted_name, |
638 | size_t *decrypted_name_size, | 637 | size_t *decrypted_name_size, |
639 | struct dentry *ecryptfs_dentry, | 638 | struct dentry *ecryptfs_dentry, |
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c index 81e10e6a9443..7d1050e254f9 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c | |||
@@ -317,6 +317,7 @@ ecryptfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
317 | 317 | ||
318 | const struct file_operations ecryptfs_dir_fops = { | 318 | const struct file_operations ecryptfs_dir_fops = { |
319 | .readdir = ecryptfs_readdir, | 319 | .readdir = ecryptfs_readdir, |
320 | .read = generic_read_dir, | ||
320 | .unlocked_ioctl = ecryptfs_unlocked_ioctl, | 321 | .unlocked_ioctl = ecryptfs_unlocked_ioctl, |
321 | #ifdef CONFIG_COMPAT | 322 | #ifdef CONFIG_COMPAT |
322 | .compat_ioctl = ecryptfs_compat_ioctl, | 323 | .compat_ioctl = ecryptfs_compat_ioctl, |
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index bd33f87a1907..b592938a84bc 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c | |||
@@ -74,16 +74,20 @@ ecryptfs_create_underlying_file(struct inode *lower_dir_inode, | |||
74 | unsigned int flags_save; | 74 | unsigned int flags_save; |
75 | int rc; | 75 | int rc; |
76 | 76 | ||
77 | dentry_save = nd->path.dentry; | 77 | if (nd) { |
78 | vfsmount_save = nd->path.mnt; | 78 | dentry_save = nd->path.dentry; |
79 | flags_save = nd->flags; | 79 | vfsmount_save = nd->path.mnt; |
80 | nd->path.dentry = lower_dentry; | 80 | flags_save = nd->flags; |
81 | nd->path.mnt = lower_mnt; | 81 | nd->path.dentry = lower_dentry; |
82 | nd->flags &= ~LOOKUP_OPEN; | 82 | nd->path.mnt = lower_mnt; |
83 | nd->flags &= ~LOOKUP_OPEN; | ||
84 | } | ||
83 | rc = vfs_create(lower_dir_inode, lower_dentry, mode, nd); | 85 | rc = vfs_create(lower_dir_inode, lower_dentry, mode, nd); |
84 | nd->path.dentry = dentry_save; | 86 | if (nd) { |
85 | nd->path.mnt = vfsmount_save; | 87 | nd->path.dentry = dentry_save; |
86 | nd->flags = flags_save; | 88 | nd->path.mnt = vfsmount_save; |
89 | nd->flags = flags_save; | ||
90 | } | ||
87 | return rc; | 91 | return rc; |
88 | } | 92 | } |
89 | 93 | ||
@@ -241,8 +245,7 @@ out: | |||
241 | */ | 245 | */ |
242 | int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, | 246 | int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, |
243 | struct dentry *lower_dentry, | 247 | struct dentry *lower_dentry, |
244 | struct inode *ecryptfs_dir_inode, | 248 | struct inode *ecryptfs_dir_inode) |
245 | struct nameidata *ecryptfs_nd) | ||
246 | { | 249 | { |
247 | struct dentry *lower_dir_dentry; | 250 | struct dentry *lower_dir_dentry; |
248 | struct vfsmount *lower_mnt; | 251 | struct vfsmount *lower_mnt; |
@@ -290,8 +293,6 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, | |||
290 | goto out; | 293 | goto out; |
291 | if (special_file(lower_inode->i_mode)) | 294 | if (special_file(lower_inode->i_mode)) |
292 | goto out; | 295 | goto out; |
293 | if (!ecryptfs_nd) | ||
294 | goto out; | ||
295 | /* Released in this function */ | 296 | /* Released in this function */ |
296 | page_virt = kmem_cache_zalloc(ecryptfs_header_cache_2, GFP_USER); | 297 | page_virt = kmem_cache_zalloc(ecryptfs_header_cache_2, GFP_USER); |
297 | if (!page_virt) { | 298 | if (!page_virt) { |
@@ -349,75 +350,6 @@ out: | |||
349 | } | 350 | } |
350 | 351 | ||
351 | /** | 352 | /** |
352 | * ecryptfs_new_lower_dentry | ||
353 | * @name: The name of the new dentry. | ||
354 | * @lower_dir_dentry: Parent directory of the new dentry. | ||
355 | * @nd: nameidata from last lookup. | ||
356 | * | ||
357 | * Create a new dentry or get it from lower parent dir. | ||
358 | */ | ||
359 | static struct dentry * | ||
360 | ecryptfs_new_lower_dentry(struct qstr *name, struct dentry *lower_dir_dentry, | ||
361 | struct nameidata *nd) | ||
362 | { | ||
363 | struct dentry *new_dentry; | ||
364 | struct dentry *tmp; | ||
365 | struct inode *lower_dir_inode; | ||
366 | |||
367 | lower_dir_inode = lower_dir_dentry->d_inode; | ||
368 | |||
369 | tmp = d_alloc(lower_dir_dentry, name); | ||
370 | if (!tmp) | ||
371 | return ERR_PTR(-ENOMEM); | ||
372 | |||
373 | mutex_lock(&lower_dir_inode->i_mutex); | ||
374 | new_dentry = lower_dir_inode->i_op->lookup(lower_dir_inode, tmp, nd); | ||
375 | mutex_unlock(&lower_dir_inode->i_mutex); | ||
376 | |||
377 | if (!new_dentry) | ||
378 | new_dentry = tmp; | ||
379 | else | ||
380 | dput(tmp); | ||
381 | |||
382 | return new_dentry; | ||
383 | } | ||
384 | |||
385 | |||
386 | /** | ||
387 | * ecryptfs_lookup_one_lower | ||
388 | * @ecryptfs_dentry: The eCryptfs dentry that we are looking up | ||
389 | * @lower_dir_dentry: lower parent directory | ||
390 | * @name: lower file name | ||
391 | * | ||
392 | * Get the lower dentry from vfs. If lower dentry does not exist yet, | ||
393 | * create it. | ||
394 | */ | ||
395 | static struct dentry * | ||
396 | ecryptfs_lookup_one_lower(struct dentry *ecryptfs_dentry, | ||
397 | struct dentry *lower_dir_dentry, struct qstr *name) | ||
398 | { | ||
399 | struct nameidata nd; | ||
400 | struct vfsmount *lower_mnt; | ||
401 | int err; | ||
402 | |||
403 | lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt( | ||
404 | ecryptfs_dentry->d_parent)); | ||
405 | err = vfs_path_lookup(lower_dir_dentry, lower_mnt, name->name , 0, &nd); | ||
406 | mntput(lower_mnt); | ||
407 | |||
408 | if (!err) { | ||
409 | /* we dont need the mount */ | ||
410 | mntput(nd.path.mnt); | ||
411 | return nd.path.dentry; | ||
412 | } | ||
413 | if (err != -ENOENT) | ||
414 | return ERR_PTR(err); | ||
415 | |||
416 | /* create a new lower dentry */ | ||
417 | return ecryptfs_new_lower_dentry(name, lower_dir_dentry, &nd); | ||
418 | } | ||
419 | |||
420 | /** | ||
421 | * ecryptfs_lookup | 353 | * ecryptfs_lookup |
422 | * @ecryptfs_dir_inode: The eCryptfs directory inode | 354 | * @ecryptfs_dir_inode: The eCryptfs directory inode |
423 | * @ecryptfs_dentry: The eCryptfs dentry that we are looking up | 355 | * @ecryptfs_dentry: The eCryptfs dentry that we are looking up |
@@ -434,7 +366,6 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode, | |||
434 | size_t encrypted_and_encoded_name_size; | 366 | size_t encrypted_and_encoded_name_size; |
435 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat = NULL; | 367 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat = NULL; |
436 | struct dentry *lower_dir_dentry, *lower_dentry; | 368 | struct dentry *lower_dir_dentry, *lower_dentry; |
437 | struct qstr lower_name; | ||
438 | int rc = 0; | 369 | int rc = 0; |
439 | 370 | ||
440 | if ((ecryptfs_dentry->d_name.len == 1 | 371 | if ((ecryptfs_dentry->d_name.len == 1 |
@@ -444,20 +375,14 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode, | |||
444 | goto out_d_drop; | 375 | goto out_d_drop; |
445 | } | 376 | } |
446 | lower_dir_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry->d_parent); | 377 | lower_dir_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry->d_parent); |
447 | lower_name.name = ecryptfs_dentry->d_name.name; | 378 | mutex_lock(&lower_dir_dentry->d_inode->i_mutex); |
448 | lower_name.len = ecryptfs_dentry->d_name.len; | 379 | lower_dentry = lookup_one_len(ecryptfs_dentry->d_name.name, |
449 | lower_name.hash = ecryptfs_dentry->d_name.hash; | 380 | lower_dir_dentry, |
450 | if (lower_dir_dentry->d_op && lower_dir_dentry->d_op->d_hash) { | 381 | ecryptfs_dentry->d_name.len); |
451 | rc = lower_dir_dentry->d_op->d_hash(lower_dir_dentry, | 382 | mutex_unlock(&lower_dir_dentry->d_inode->i_mutex); |
452 | lower_dir_dentry->d_inode, &lower_name); | ||
453 | if (rc < 0) | ||
454 | goto out_d_drop; | ||
455 | } | ||
456 | lower_dentry = ecryptfs_lookup_one_lower(ecryptfs_dentry, | ||
457 | lower_dir_dentry, &lower_name); | ||
458 | if (IS_ERR(lower_dentry)) { | 383 | if (IS_ERR(lower_dentry)) { |
459 | rc = PTR_ERR(lower_dentry); | 384 | rc = PTR_ERR(lower_dentry); |
460 | ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_lower() returned " | 385 | ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_len() returned " |
461 | "[%d] on lower_dentry = [%s]\n", __func__, rc, | 386 | "[%d] on lower_dentry = [%s]\n", __func__, rc, |
462 | encrypted_and_encoded_name); | 387 | encrypted_and_encoded_name); |
463 | goto out_d_drop; | 388 | goto out_d_drop; |
@@ -479,28 +404,21 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode, | |||
479 | "filename; rc = [%d]\n", __func__, rc); | 404 | "filename; rc = [%d]\n", __func__, rc); |
480 | goto out_d_drop; | 405 | goto out_d_drop; |
481 | } | 406 | } |
482 | lower_name.name = encrypted_and_encoded_name; | 407 | mutex_lock(&lower_dir_dentry->d_inode->i_mutex); |
483 | lower_name.len = encrypted_and_encoded_name_size; | 408 | lower_dentry = lookup_one_len(encrypted_and_encoded_name, |
484 | lower_name.hash = full_name_hash(lower_name.name, lower_name.len); | 409 | lower_dir_dentry, |
485 | if (lower_dir_dentry->d_op && lower_dir_dentry->d_op->d_hash) { | 410 | encrypted_and_encoded_name_size); |
486 | rc = lower_dir_dentry->d_op->d_hash(lower_dir_dentry, | 411 | mutex_unlock(&lower_dir_dentry->d_inode->i_mutex); |
487 | lower_dir_dentry->d_inode, &lower_name); | ||
488 | if (rc < 0) | ||
489 | goto out_d_drop; | ||
490 | } | ||
491 | lower_dentry = ecryptfs_lookup_one_lower(ecryptfs_dentry, | ||
492 | lower_dir_dentry, &lower_name); | ||
493 | if (IS_ERR(lower_dentry)) { | 412 | if (IS_ERR(lower_dentry)) { |
494 | rc = PTR_ERR(lower_dentry); | 413 | rc = PTR_ERR(lower_dentry); |
495 | ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_lower() returned " | 414 | ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_len() returned " |
496 | "[%d] on lower_dentry = [%s]\n", __func__, rc, | 415 | "[%d] on lower_dentry = [%s]\n", __func__, rc, |
497 | encrypted_and_encoded_name); | 416 | encrypted_and_encoded_name); |
498 | goto out_d_drop; | 417 | goto out_d_drop; |
499 | } | 418 | } |
500 | lookup_and_interpose: | 419 | lookup_and_interpose: |
501 | rc = ecryptfs_lookup_and_interpose_lower(ecryptfs_dentry, lower_dentry, | 420 | rc = ecryptfs_lookup_and_interpose_lower(ecryptfs_dentry, lower_dentry, |
502 | ecryptfs_dir_inode, | 421 | ecryptfs_dir_inode); |
503 | ecryptfs_nd); | ||
504 | goto out; | 422 | goto out; |
505 | out_d_drop: | 423 | out_d_drop: |
506 | d_drop(ecryptfs_dentry); | 424 | d_drop(ecryptfs_dentry); |
@@ -1092,6 +1010,8 @@ int ecryptfs_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
1092 | rc = vfs_getattr(ecryptfs_dentry_to_lower_mnt(dentry), | 1010 | rc = vfs_getattr(ecryptfs_dentry_to_lower_mnt(dentry), |
1093 | ecryptfs_dentry_to_lower(dentry), &lower_stat); | 1011 | ecryptfs_dentry_to_lower(dentry), &lower_stat); |
1094 | if (!rc) { | 1012 | if (!rc) { |
1013 | fsstack_copy_attr_all(dentry->d_inode, | ||
1014 | ecryptfs_inode_to_lower(dentry->d_inode)); | ||
1095 | generic_fillattr(dentry->d_inode, stat); | 1015 | generic_fillattr(dentry->d_inode, stat); |
1096 | stat->blocks = lower_stat.blocks; | 1016 | stat->blocks = lower_stat.blocks; |
1097 | } | 1017 | } |
diff --git a/fs/eventfd.c b/fs/eventfd.c index e0194b3e14d6..d9a591773919 100644 --- a/fs/eventfd.c +++ b/fs/eventfd.c | |||
@@ -99,7 +99,7 @@ EXPORT_SYMBOL_GPL(eventfd_ctx_get); | |||
99 | * @ctx: [in] Pointer to eventfd context. | 99 | * @ctx: [in] Pointer to eventfd context. |
100 | * | 100 | * |
101 | * The eventfd context reference must have been previously acquired either | 101 | * The eventfd context reference must have been previously acquired either |
102 | * with eventfd_ctx_get() or eventfd_ctx_fdget()). | 102 | * with eventfd_ctx_get() or eventfd_ctx_fdget(). |
103 | */ | 103 | */ |
104 | void eventfd_ctx_put(struct eventfd_ctx *ctx) | 104 | void eventfd_ctx_put(struct eventfd_ctx *ctx) |
105 | { | 105 | { |
@@ -146,9 +146,9 @@ static void eventfd_ctx_do_read(struct eventfd_ctx *ctx, __u64 *cnt) | |||
146 | * eventfd_ctx_remove_wait_queue - Read the current counter and removes wait queue. | 146 | * eventfd_ctx_remove_wait_queue - Read the current counter and removes wait queue. |
147 | * @ctx: [in] Pointer to eventfd context. | 147 | * @ctx: [in] Pointer to eventfd context. |
148 | * @wait: [in] Wait queue to be removed. | 148 | * @wait: [in] Wait queue to be removed. |
149 | * @cnt: [out] Pointer to the 64bit conter value. | 149 | * @cnt: [out] Pointer to the 64-bit counter value. |
150 | * | 150 | * |
151 | * Returns zero if successful, or the following error codes: | 151 | * Returns %0 if successful, or the following error codes: |
152 | * | 152 | * |
153 | * -EAGAIN : The operation would have blocked. | 153 | * -EAGAIN : The operation would have blocked. |
154 | * | 154 | * |
@@ -175,11 +175,11 @@ EXPORT_SYMBOL_GPL(eventfd_ctx_remove_wait_queue); | |||
175 | * eventfd_ctx_read - Reads the eventfd counter or wait if it is zero. | 175 | * eventfd_ctx_read - Reads the eventfd counter or wait if it is zero. |
176 | * @ctx: [in] Pointer to eventfd context. | 176 | * @ctx: [in] Pointer to eventfd context. |
177 | * @no_wait: [in] Different from zero if the operation should not block. | 177 | * @no_wait: [in] Different from zero if the operation should not block. |
178 | * @cnt: [out] Pointer to the 64bit conter value. | 178 | * @cnt: [out] Pointer to the 64-bit counter value. |
179 | * | 179 | * |
180 | * Returns zero if successful, or the following error codes: | 180 | * Returns %0 if successful, or the following error codes: |
181 | * | 181 | * |
182 | * -EAGAIN : The operation would have blocked but @no_wait was nonzero. | 182 | * -EAGAIN : The operation would have blocked but @no_wait was non-zero. |
183 | * -ERESTARTSYS : A signal interrupted the wait operation. | 183 | * -ERESTARTSYS : A signal interrupted the wait operation. |
184 | * | 184 | * |
185 | * If @no_wait is zero, the function might sleep until the eventfd internal | 185 | * If @no_wait is zero, the function might sleep until the eventfd internal |
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 0c8d97b56f34..3aa0b72b3b94 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -848,6 +848,7 @@ struct ext4_inode_info { | |||
848 | atomic_t i_ioend_count; /* Number of outstanding io_end structs */ | 848 | atomic_t i_ioend_count; /* Number of outstanding io_end structs */ |
849 | /* current io_end structure for async DIO write*/ | 849 | /* current io_end structure for async DIO write*/ |
850 | ext4_io_end_t *cur_aio_dio; | 850 | ext4_io_end_t *cur_aio_dio; |
851 | atomic_t i_aiodio_unwritten; /* Nr. of inflight conversions pending */ | ||
851 | 852 | ||
852 | spinlock_t i_block_reservation_lock; | 853 | spinlock_t i_block_reservation_lock; |
853 | 854 | ||
@@ -2119,6 +2120,15 @@ static inline void set_bitmap_uptodate(struct buffer_head *bh) | |||
2119 | 2120 | ||
2120 | #define in_range(b, first, len) ((b) >= (first) && (b) <= (first) + (len) - 1) | 2121 | #define in_range(b, first, len) ((b) >= (first) && (b) <= (first) + (len) - 1) |
2121 | 2122 | ||
2123 | /* For ioend & aio unwritten conversion wait queues */ | ||
2124 | #define EXT4_WQ_HASH_SZ 37 | ||
2125 | #define ext4_ioend_wq(v) (&ext4__ioend_wq[((unsigned long)(v)) %\ | ||
2126 | EXT4_WQ_HASH_SZ]) | ||
2127 | #define ext4_aio_mutex(v) (&ext4__aio_mutex[((unsigned long)(v)) %\ | ||
2128 | EXT4_WQ_HASH_SZ]) | ||
2129 | extern wait_queue_head_t ext4__ioend_wq[EXT4_WQ_HASH_SZ]; | ||
2130 | extern struct mutex ext4__aio_mutex[EXT4_WQ_HASH_SZ]; | ||
2131 | |||
2122 | #endif /* __KERNEL__ */ | 2132 | #endif /* __KERNEL__ */ |
2123 | 2133 | ||
2124 | #endif /* _EXT4_H */ | 2134 | #endif /* _EXT4_H */ |
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 63a75810b7c3..ccce8a7e94ed 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
@@ -3174,9 +3174,10 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode, | |||
3174 | * that this IO needs to convertion to written when IO is | 3174 | * that this IO needs to convertion to written when IO is |
3175 | * completed | 3175 | * completed |
3176 | */ | 3176 | */ |
3177 | if (io) | 3177 | if (io && !(io->flag & EXT4_IO_END_UNWRITTEN)) { |
3178 | io->flag = EXT4_IO_END_UNWRITTEN; | 3178 | io->flag = EXT4_IO_END_UNWRITTEN; |
3179 | else | 3179 | atomic_inc(&EXT4_I(inode)->i_aiodio_unwritten); |
3180 | } else | ||
3180 | ext4_set_inode_state(inode, EXT4_STATE_DIO_UNWRITTEN); | 3181 | ext4_set_inode_state(inode, EXT4_STATE_DIO_UNWRITTEN); |
3181 | if (ext4_should_dioread_nolock(inode)) | 3182 | if (ext4_should_dioread_nolock(inode)) |
3182 | map->m_flags |= EXT4_MAP_UNINIT; | 3183 | map->m_flags |= EXT4_MAP_UNINIT; |
@@ -3463,9 +3464,10 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, | |||
3463 | * that we need to perform convertion when IO is done. | 3464 | * that we need to perform convertion when IO is done. |
3464 | */ | 3465 | */ |
3465 | if ((flags & EXT4_GET_BLOCKS_PRE_IO)) { | 3466 | if ((flags & EXT4_GET_BLOCKS_PRE_IO)) { |
3466 | if (io) | 3467 | if (io && !(io->flag & EXT4_IO_END_UNWRITTEN)) { |
3467 | io->flag = EXT4_IO_END_UNWRITTEN; | 3468 | io->flag = EXT4_IO_END_UNWRITTEN; |
3468 | else | 3469 | atomic_inc(&EXT4_I(inode)->i_aiodio_unwritten); |
3470 | } else | ||
3469 | ext4_set_inode_state(inode, | 3471 | ext4_set_inode_state(inode, |
3470 | EXT4_STATE_DIO_UNWRITTEN); | 3472 | EXT4_STATE_DIO_UNWRITTEN); |
3471 | } | 3473 | } |
diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 2e8322c8aa88..7b80d543b89e 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c | |||
@@ -55,11 +55,47 @@ static int ext4_release_file(struct inode *inode, struct file *filp) | |||
55 | return 0; | 55 | return 0; |
56 | } | 56 | } |
57 | 57 | ||
58 | static void ext4_aiodio_wait(struct inode *inode) | ||
59 | { | ||
60 | wait_queue_head_t *wq = ext4_ioend_wq(inode); | ||
61 | |||
62 | wait_event(*wq, (atomic_read(&EXT4_I(inode)->i_aiodio_unwritten) == 0)); | ||
63 | } | ||
64 | |||
65 | /* | ||
66 | * This tests whether the IO in question is block-aligned or not. | ||
67 | * Ext4 utilizes unwritten extents when hole-filling during direct IO, and they | ||
68 | * are converted to written only after the IO is complete. Until they are | ||
69 | * mapped, these blocks appear as holes, so dio_zero_block() will assume that | ||
70 | * it needs to zero out portions of the start and/or end block. If 2 AIO | ||
71 | * threads are at work on the same unwritten block, they must be synchronized | ||
72 | * or one thread will zero the other's data, causing corruption. | ||
73 | */ | ||
74 | static int | ||
75 | ext4_unaligned_aio(struct inode *inode, const struct iovec *iov, | ||
76 | unsigned long nr_segs, loff_t pos) | ||
77 | { | ||
78 | struct super_block *sb = inode->i_sb; | ||
79 | int blockmask = sb->s_blocksize - 1; | ||
80 | size_t count = iov_length(iov, nr_segs); | ||
81 | loff_t final_size = pos + count; | ||
82 | |||
83 | if (pos >= inode->i_size) | ||
84 | return 0; | ||
85 | |||
86 | if ((pos & blockmask) || (final_size & blockmask)) | ||
87 | return 1; | ||
88 | |||
89 | return 0; | ||
90 | } | ||
91 | |||
58 | static ssize_t | 92 | static ssize_t |
59 | ext4_file_write(struct kiocb *iocb, const struct iovec *iov, | 93 | ext4_file_write(struct kiocb *iocb, const struct iovec *iov, |
60 | unsigned long nr_segs, loff_t pos) | 94 | unsigned long nr_segs, loff_t pos) |
61 | { | 95 | { |
62 | struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode; | 96 | struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode; |
97 | int unaligned_aio = 0; | ||
98 | int ret; | ||
63 | 99 | ||
64 | /* | 100 | /* |
65 | * If we have encountered a bitmap-format file, the size limit | 101 | * If we have encountered a bitmap-format file, the size limit |
@@ -78,9 +114,31 @@ ext4_file_write(struct kiocb *iocb, const struct iovec *iov, | |||
78 | nr_segs = iov_shorten((struct iovec *)iov, nr_segs, | 114 | nr_segs = iov_shorten((struct iovec *)iov, nr_segs, |
79 | sbi->s_bitmap_maxbytes - pos); | 115 | sbi->s_bitmap_maxbytes - pos); |
80 | } | 116 | } |
117 | } else if (unlikely((iocb->ki_filp->f_flags & O_DIRECT) && | ||
118 | !is_sync_kiocb(iocb))) { | ||
119 | unaligned_aio = ext4_unaligned_aio(inode, iov, nr_segs, pos); | ||
81 | } | 120 | } |
82 | 121 | ||
83 | return generic_file_aio_write(iocb, iov, nr_segs, pos); | 122 | /* Unaligned direct AIO must be serialized; see comment above */ |
123 | if (unaligned_aio) { | ||
124 | static unsigned long unaligned_warn_time; | ||
125 | |||
126 | /* Warn about this once per day */ | ||
127 | if (printk_timed_ratelimit(&unaligned_warn_time, 60*60*24*HZ)) | ||
128 | ext4_msg(inode->i_sb, KERN_WARNING, | ||
129 | "Unaligned AIO/DIO on inode %ld by %s; " | ||
130 | "performance will be poor.", | ||
131 | inode->i_ino, current->comm); | ||
132 | mutex_lock(ext4_aio_mutex(inode)); | ||
133 | ext4_aiodio_wait(inode); | ||
134 | } | ||
135 | |||
136 | ret = generic_file_aio_write(iocb, iov, nr_segs, pos); | ||
137 | |||
138 | if (unaligned_aio) | ||
139 | mutex_unlock(ext4_aio_mutex(inode)); | ||
140 | |||
141 | return ret; | ||
84 | } | 142 | } |
85 | 143 | ||
86 | static const struct vm_operations_struct ext4_file_vm_ops = { | 144 | static const struct vm_operations_struct ext4_file_vm_ops = { |
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 851f49b2f9d2..d1fe09aea73d 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c | |||
@@ -342,10 +342,15 @@ static struct kmem_cache *ext4_free_ext_cachep; | |||
342 | /* We create slab caches for groupinfo data structures based on the | 342 | /* We create slab caches for groupinfo data structures based on the |
343 | * superblock block size. There will be one per mounted filesystem for | 343 | * superblock block size. There will be one per mounted filesystem for |
344 | * each unique s_blocksize_bits */ | 344 | * each unique s_blocksize_bits */ |
345 | #define NR_GRPINFO_CACHES \ | 345 | #define NR_GRPINFO_CACHES 8 |
346 | (EXT4_MAX_BLOCK_LOG_SIZE - EXT4_MIN_BLOCK_LOG_SIZE + 1) | ||
347 | static struct kmem_cache *ext4_groupinfo_caches[NR_GRPINFO_CACHES]; | 346 | static struct kmem_cache *ext4_groupinfo_caches[NR_GRPINFO_CACHES]; |
348 | 347 | ||
348 | static const char *ext4_groupinfo_slab_names[NR_GRPINFO_CACHES] = { | ||
349 | "ext4_groupinfo_1k", "ext4_groupinfo_2k", "ext4_groupinfo_4k", | ||
350 | "ext4_groupinfo_8k", "ext4_groupinfo_16k", "ext4_groupinfo_32k", | ||
351 | "ext4_groupinfo_64k", "ext4_groupinfo_128k" | ||
352 | }; | ||
353 | |||
349 | static void ext4_mb_generate_from_pa(struct super_block *sb, void *bitmap, | 354 | static void ext4_mb_generate_from_pa(struct super_block *sb, void *bitmap, |
350 | ext4_group_t group); | 355 | ext4_group_t group); |
351 | static void ext4_mb_generate_from_freelist(struct super_block *sb, void *bitmap, | 356 | static void ext4_mb_generate_from_freelist(struct super_block *sb, void *bitmap, |
@@ -2414,6 +2419,55 @@ err_freesgi: | |||
2414 | return -ENOMEM; | 2419 | return -ENOMEM; |
2415 | } | 2420 | } |
2416 | 2421 | ||
2422 | static void ext4_groupinfo_destroy_slabs(void) | ||
2423 | { | ||
2424 | int i; | ||
2425 | |||
2426 | for (i = 0; i < NR_GRPINFO_CACHES; i++) { | ||
2427 | if (ext4_groupinfo_caches[i]) | ||
2428 | kmem_cache_destroy(ext4_groupinfo_caches[i]); | ||
2429 | ext4_groupinfo_caches[i] = NULL; | ||
2430 | } | ||
2431 | } | ||
2432 | |||
2433 | static int ext4_groupinfo_create_slab(size_t size) | ||
2434 | { | ||
2435 | static DEFINE_MUTEX(ext4_grpinfo_slab_create_mutex); | ||
2436 | int slab_size; | ||
2437 | int blocksize_bits = order_base_2(size); | ||
2438 | int cache_index = blocksize_bits - EXT4_MIN_BLOCK_LOG_SIZE; | ||
2439 | struct kmem_cache *cachep; | ||
2440 | |||
2441 | if (cache_index >= NR_GRPINFO_CACHES) | ||
2442 | return -EINVAL; | ||
2443 | |||
2444 | if (unlikely(cache_index < 0)) | ||
2445 | cache_index = 0; | ||
2446 | |||
2447 | mutex_lock(&ext4_grpinfo_slab_create_mutex); | ||
2448 | if (ext4_groupinfo_caches[cache_index]) { | ||
2449 | mutex_unlock(&ext4_grpinfo_slab_create_mutex); | ||
2450 | return 0; /* Already created */ | ||
2451 | } | ||
2452 | |||
2453 | slab_size = offsetof(struct ext4_group_info, | ||
2454 | bb_counters[blocksize_bits + 2]); | ||
2455 | |||
2456 | cachep = kmem_cache_create(ext4_groupinfo_slab_names[cache_index], | ||
2457 | slab_size, 0, SLAB_RECLAIM_ACCOUNT, | ||
2458 | NULL); | ||
2459 | |||
2460 | mutex_unlock(&ext4_grpinfo_slab_create_mutex); | ||
2461 | if (!cachep) { | ||
2462 | printk(KERN_EMERG "EXT4: no memory for groupinfo slab cache\n"); | ||
2463 | return -ENOMEM; | ||
2464 | } | ||
2465 | |||
2466 | ext4_groupinfo_caches[cache_index] = cachep; | ||
2467 | |||
2468 | return 0; | ||
2469 | } | ||
2470 | |||
2417 | int ext4_mb_init(struct super_block *sb, int needs_recovery) | 2471 | int ext4_mb_init(struct super_block *sb, int needs_recovery) |
2418 | { | 2472 | { |
2419 | struct ext4_sb_info *sbi = EXT4_SB(sb); | 2473 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
@@ -2421,9 +2475,6 @@ int ext4_mb_init(struct super_block *sb, int needs_recovery) | |||
2421 | unsigned offset; | 2475 | unsigned offset; |
2422 | unsigned max; | 2476 | unsigned max; |
2423 | int ret; | 2477 | int ret; |
2424 | int cache_index; | ||
2425 | struct kmem_cache *cachep; | ||
2426 | char *namep = NULL; | ||
2427 | 2478 | ||
2428 | i = (sb->s_blocksize_bits + 2) * sizeof(*sbi->s_mb_offsets); | 2479 | i = (sb->s_blocksize_bits + 2) * sizeof(*sbi->s_mb_offsets); |
2429 | 2480 | ||
@@ -2440,30 +2491,9 @@ int ext4_mb_init(struct super_block *sb, int needs_recovery) | |||
2440 | goto out; | 2491 | goto out; |
2441 | } | 2492 | } |
2442 | 2493 | ||
2443 | cache_index = sb->s_blocksize_bits - EXT4_MIN_BLOCK_LOG_SIZE; | 2494 | ret = ext4_groupinfo_create_slab(sb->s_blocksize); |
2444 | cachep = ext4_groupinfo_caches[cache_index]; | 2495 | if (ret < 0) |
2445 | if (!cachep) { | 2496 | goto out; |
2446 | char name[32]; | ||
2447 | int len = offsetof(struct ext4_group_info, | ||
2448 | bb_counters[sb->s_blocksize_bits + 2]); | ||
2449 | |||
2450 | sprintf(name, "ext4_groupinfo_%d", sb->s_blocksize_bits); | ||
2451 | namep = kstrdup(name, GFP_KERNEL); | ||
2452 | if (!namep) { | ||
2453 | ret = -ENOMEM; | ||
2454 | goto out; | ||
2455 | } | ||
2456 | |||
2457 | /* Need to free the kmem_cache_name() when we | ||
2458 | * destroy the slab */ | ||
2459 | cachep = kmem_cache_create(namep, len, 0, | ||
2460 | SLAB_RECLAIM_ACCOUNT, NULL); | ||
2461 | if (!cachep) { | ||
2462 | ret = -ENOMEM; | ||
2463 | goto out; | ||
2464 | } | ||
2465 | ext4_groupinfo_caches[cache_index] = cachep; | ||
2466 | } | ||
2467 | 2497 | ||
2468 | /* order 0 is regular bitmap */ | 2498 | /* order 0 is regular bitmap */ |
2469 | sbi->s_mb_maxs[0] = sb->s_blocksize << 3; | 2499 | sbi->s_mb_maxs[0] = sb->s_blocksize << 3; |
@@ -2520,7 +2550,6 @@ out: | |||
2520 | if (ret) { | 2550 | if (ret) { |
2521 | kfree(sbi->s_mb_offsets); | 2551 | kfree(sbi->s_mb_offsets); |
2522 | kfree(sbi->s_mb_maxs); | 2552 | kfree(sbi->s_mb_maxs); |
2523 | kfree(namep); | ||
2524 | } | 2553 | } |
2525 | return ret; | 2554 | return ret; |
2526 | } | 2555 | } |
@@ -2734,7 +2763,6 @@ int __init ext4_init_mballoc(void) | |||
2734 | 2763 | ||
2735 | void ext4_exit_mballoc(void) | 2764 | void ext4_exit_mballoc(void) |
2736 | { | 2765 | { |
2737 | int i; | ||
2738 | /* | 2766 | /* |
2739 | * Wait for completion of call_rcu()'s on ext4_pspace_cachep | 2767 | * Wait for completion of call_rcu()'s on ext4_pspace_cachep |
2740 | * before destroying the slab cache. | 2768 | * before destroying the slab cache. |
@@ -2743,15 +2771,7 @@ void ext4_exit_mballoc(void) | |||
2743 | kmem_cache_destroy(ext4_pspace_cachep); | 2771 | kmem_cache_destroy(ext4_pspace_cachep); |
2744 | kmem_cache_destroy(ext4_ac_cachep); | 2772 | kmem_cache_destroy(ext4_ac_cachep); |
2745 | kmem_cache_destroy(ext4_free_ext_cachep); | 2773 | kmem_cache_destroy(ext4_free_ext_cachep); |
2746 | 2774 | ext4_groupinfo_destroy_slabs(); | |
2747 | for (i = 0; i < NR_GRPINFO_CACHES; i++) { | ||
2748 | struct kmem_cache *cachep = ext4_groupinfo_caches[i]; | ||
2749 | if (cachep) { | ||
2750 | char *name = (char *)kmem_cache_name(cachep); | ||
2751 | kmem_cache_destroy(cachep); | ||
2752 | kfree(name); | ||
2753 | } | ||
2754 | } | ||
2755 | ext4_remove_debugfs_entry(); | 2775 | ext4_remove_debugfs_entry(); |
2756 | } | 2776 | } |
2757 | 2777 | ||
diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c index 7270dcfca92a..955cc309142f 100644 --- a/fs/ext4/page-io.c +++ b/fs/ext4/page-io.c | |||
@@ -32,14 +32,8 @@ | |||
32 | 32 | ||
33 | static struct kmem_cache *io_page_cachep, *io_end_cachep; | 33 | static struct kmem_cache *io_page_cachep, *io_end_cachep; |
34 | 34 | ||
35 | #define WQ_HASH_SZ 37 | ||
36 | #define to_ioend_wq(v) (&ioend_wq[((unsigned long)v) % WQ_HASH_SZ]) | ||
37 | static wait_queue_head_t ioend_wq[WQ_HASH_SZ]; | ||
38 | |||
39 | int __init ext4_init_pageio(void) | 35 | int __init ext4_init_pageio(void) |
40 | { | 36 | { |
41 | int i; | ||
42 | |||
43 | io_page_cachep = KMEM_CACHE(ext4_io_page, SLAB_RECLAIM_ACCOUNT); | 37 | io_page_cachep = KMEM_CACHE(ext4_io_page, SLAB_RECLAIM_ACCOUNT); |
44 | if (io_page_cachep == NULL) | 38 | if (io_page_cachep == NULL) |
45 | return -ENOMEM; | 39 | return -ENOMEM; |
@@ -48,9 +42,6 @@ int __init ext4_init_pageio(void) | |||
48 | kmem_cache_destroy(io_page_cachep); | 42 | kmem_cache_destroy(io_page_cachep); |
49 | return -ENOMEM; | 43 | return -ENOMEM; |
50 | } | 44 | } |
51 | for (i = 0; i < WQ_HASH_SZ; i++) | ||
52 | init_waitqueue_head(&ioend_wq[i]); | ||
53 | |||
54 | return 0; | 45 | return 0; |
55 | } | 46 | } |
56 | 47 | ||
@@ -62,7 +53,7 @@ void ext4_exit_pageio(void) | |||
62 | 53 | ||
63 | void ext4_ioend_wait(struct inode *inode) | 54 | void ext4_ioend_wait(struct inode *inode) |
64 | { | 55 | { |
65 | wait_queue_head_t *wq = to_ioend_wq(inode); | 56 | wait_queue_head_t *wq = ext4_ioend_wq(inode); |
66 | 57 | ||
67 | wait_event(*wq, (atomic_read(&EXT4_I(inode)->i_ioend_count) == 0)); | 58 | wait_event(*wq, (atomic_read(&EXT4_I(inode)->i_ioend_count) == 0)); |
68 | } | 59 | } |
@@ -87,7 +78,7 @@ void ext4_free_io_end(ext4_io_end_t *io) | |||
87 | for (i = 0; i < io->num_io_pages; i++) | 78 | for (i = 0; i < io->num_io_pages; i++) |
88 | put_io_page(io->pages[i]); | 79 | put_io_page(io->pages[i]); |
89 | io->num_io_pages = 0; | 80 | io->num_io_pages = 0; |
90 | wq = to_ioend_wq(io->inode); | 81 | wq = ext4_ioend_wq(io->inode); |
91 | if (atomic_dec_and_test(&EXT4_I(io->inode)->i_ioend_count) && | 82 | if (atomic_dec_and_test(&EXT4_I(io->inode)->i_ioend_count) && |
92 | waitqueue_active(wq)) | 83 | waitqueue_active(wq)) |
93 | wake_up_all(wq); | 84 | wake_up_all(wq); |
@@ -102,6 +93,7 @@ int ext4_end_io_nolock(ext4_io_end_t *io) | |||
102 | struct inode *inode = io->inode; | 93 | struct inode *inode = io->inode; |
103 | loff_t offset = io->offset; | 94 | loff_t offset = io->offset; |
104 | ssize_t size = io->size; | 95 | ssize_t size = io->size; |
96 | wait_queue_head_t *wq; | ||
105 | int ret = 0; | 97 | int ret = 0; |
106 | 98 | ||
107 | ext4_debug("ext4_end_io_nolock: io 0x%p from inode %lu,list->next 0x%p," | 99 | ext4_debug("ext4_end_io_nolock: io 0x%p from inode %lu,list->next 0x%p," |
@@ -126,7 +118,16 @@ int ext4_end_io_nolock(ext4_io_end_t *io) | |||
126 | if (io->iocb) | 118 | if (io->iocb) |
127 | aio_complete(io->iocb, io->result, 0); | 119 | aio_complete(io->iocb, io->result, 0); |
128 | /* clear the DIO AIO unwritten flag */ | 120 | /* clear the DIO AIO unwritten flag */ |
129 | io->flag &= ~EXT4_IO_END_UNWRITTEN; | 121 | if (io->flag & EXT4_IO_END_UNWRITTEN) { |
122 | io->flag &= ~EXT4_IO_END_UNWRITTEN; | ||
123 | /* Wake up anyone waiting on unwritten extent conversion */ | ||
124 | wq = ext4_ioend_wq(io->inode); | ||
125 | if (atomic_dec_and_test(&EXT4_I(inode)->i_aiodio_unwritten) && | ||
126 | waitqueue_active(wq)) { | ||
127 | wake_up_all(wq); | ||
128 | } | ||
129 | } | ||
130 | |||
130 | return ret; | 131 | return ret; |
131 | } | 132 | } |
132 | 133 | ||
@@ -190,6 +191,7 @@ static void ext4_end_bio(struct bio *bio, int error) | |||
190 | struct inode *inode; | 191 | struct inode *inode; |
191 | unsigned long flags; | 192 | unsigned long flags; |
192 | int i; | 193 | int i; |
194 | sector_t bi_sector = bio->bi_sector; | ||
193 | 195 | ||
194 | BUG_ON(!io_end); | 196 | BUG_ON(!io_end); |
195 | bio->bi_private = NULL; | 197 | bio->bi_private = NULL; |
@@ -207,9 +209,7 @@ static void ext4_end_bio(struct bio *bio, int error) | |||
207 | if (error) | 209 | if (error) |
208 | SetPageError(page); | 210 | SetPageError(page); |
209 | BUG_ON(!head); | 211 | BUG_ON(!head); |
210 | if (head->b_size == PAGE_CACHE_SIZE) | 212 | if (head->b_size != PAGE_CACHE_SIZE) { |
211 | clear_buffer_dirty(head); | ||
212 | else { | ||
213 | loff_t offset; | 213 | loff_t offset; |
214 | loff_t io_end_offset = io_end->offset + io_end->size; | 214 | loff_t io_end_offset = io_end->offset + io_end->size; |
215 | 215 | ||
@@ -221,7 +221,6 @@ static void ext4_end_bio(struct bio *bio, int error) | |||
221 | if (error) | 221 | if (error) |
222 | buffer_io_error(bh); | 222 | buffer_io_error(bh); |
223 | 223 | ||
224 | clear_buffer_dirty(bh); | ||
225 | } | 224 | } |
226 | if (buffer_delay(bh)) | 225 | if (buffer_delay(bh)) |
227 | partial_write = 1; | 226 | partial_write = 1; |
@@ -257,7 +256,7 @@ static void ext4_end_bio(struct bio *bio, int error) | |||
257 | (unsigned long long) io_end->offset, | 256 | (unsigned long long) io_end->offset, |
258 | (long) io_end->size, | 257 | (long) io_end->size, |
259 | (unsigned long long) | 258 | (unsigned long long) |
260 | bio->bi_sector >> (inode->i_blkbits - 9)); | 259 | bi_sector >> (inode->i_blkbits - 9)); |
261 | } | 260 | } |
262 | 261 | ||
263 | /* Add the io_end to per-inode completed io list*/ | 262 | /* Add the io_end to per-inode completed io list*/ |
@@ -380,6 +379,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io, | |||
380 | 379 | ||
381 | blocksize = 1 << inode->i_blkbits; | 380 | blocksize = 1 << inode->i_blkbits; |
382 | 381 | ||
382 | BUG_ON(!PageLocked(page)); | ||
383 | BUG_ON(PageWriteback(page)); | 383 | BUG_ON(PageWriteback(page)); |
384 | set_page_writeback(page); | 384 | set_page_writeback(page); |
385 | ClearPageError(page); | 385 | ClearPageError(page); |
@@ -397,12 +397,14 @@ int ext4_bio_write_page(struct ext4_io_submit *io, | |||
397 | for (bh = head = page_buffers(page), block_start = 0; | 397 | for (bh = head = page_buffers(page), block_start = 0; |
398 | bh != head || !block_start; | 398 | bh != head || !block_start; |
399 | block_start = block_end, bh = bh->b_this_page) { | 399 | block_start = block_end, bh = bh->b_this_page) { |
400 | |||
400 | block_end = block_start + blocksize; | 401 | block_end = block_start + blocksize; |
401 | if (block_start >= len) { | 402 | if (block_start >= len) { |
402 | clear_buffer_dirty(bh); | 403 | clear_buffer_dirty(bh); |
403 | set_buffer_uptodate(bh); | 404 | set_buffer_uptodate(bh); |
404 | continue; | 405 | continue; |
405 | } | 406 | } |
407 | clear_buffer_dirty(bh); | ||
406 | ret = io_submit_add_bh(io, io_page, inode, wbc, bh); | 408 | ret = io_submit_add_bh(io, io_page, inode, wbc, bh); |
407 | if (ret) { | 409 | if (ret) { |
408 | /* | 410 | /* |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 48ce561fafac..f6a318f836b2 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -77,6 +77,7 @@ static struct dentry *ext4_mount(struct file_system_type *fs_type, int flags, | |||
77 | const char *dev_name, void *data); | 77 | const char *dev_name, void *data); |
78 | static void ext4_destroy_lazyinit_thread(void); | 78 | static void ext4_destroy_lazyinit_thread(void); |
79 | static void ext4_unregister_li_request(struct super_block *sb); | 79 | static void ext4_unregister_li_request(struct super_block *sb); |
80 | static void ext4_clear_request_list(void); | ||
80 | 81 | ||
81 | #if !defined(CONFIG_EXT3_FS) && !defined(CONFIG_EXT3_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23) | 82 | #if !defined(CONFIG_EXT3_FS) && !defined(CONFIG_EXT3_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23) |
82 | static struct file_system_type ext3_fs_type = { | 83 | static struct file_system_type ext3_fs_type = { |
@@ -832,6 +833,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb) | |||
832 | ei->i_sync_tid = 0; | 833 | ei->i_sync_tid = 0; |
833 | ei->i_datasync_tid = 0; | 834 | ei->i_datasync_tid = 0; |
834 | atomic_set(&ei->i_ioend_count, 0); | 835 | atomic_set(&ei->i_ioend_count, 0); |
836 | atomic_set(&ei->i_aiodio_unwritten, 0); | ||
835 | 837 | ||
836 | return &ei->vfs_inode; | 838 | return &ei->vfs_inode; |
837 | } | 839 | } |
@@ -2716,6 +2718,8 @@ static void ext4_unregister_li_request(struct super_block *sb) | |||
2716 | mutex_unlock(&ext4_li_info->li_list_mtx); | 2718 | mutex_unlock(&ext4_li_info->li_list_mtx); |
2717 | } | 2719 | } |
2718 | 2720 | ||
2721 | static struct task_struct *ext4_lazyinit_task; | ||
2722 | |||
2719 | /* | 2723 | /* |
2720 | * This is the function where ext4lazyinit thread lives. It walks | 2724 | * This is the function where ext4lazyinit thread lives. It walks |
2721 | * through the request list searching for next scheduled filesystem. | 2725 | * through the request list searching for next scheduled filesystem. |
@@ -2784,6 +2788,10 @@ cont_thread: | |||
2784 | if (time_before(jiffies, next_wakeup)) | 2788 | if (time_before(jiffies, next_wakeup)) |
2785 | schedule(); | 2789 | schedule(); |
2786 | finish_wait(&eli->li_wait_daemon, &wait); | 2790 | finish_wait(&eli->li_wait_daemon, &wait); |
2791 | if (kthread_should_stop()) { | ||
2792 | ext4_clear_request_list(); | ||
2793 | goto exit_thread; | ||
2794 | } | ||
2787 | } | 2795 | } |
2788 | 2796 | ||
2789 | exit_thread: | 2797 | exit_thread: |
@@ -2808,6 +2816,7 @@ exit_thread: | |||
2808 | wake_up(&eli->li_wait_task); | 2816 | wake_up(&eli->li_wait_task); |
2809 | 2817 | ||
2810 | kfree(ext4_li_info); | 2818 | kfree(ext4_li_info); |
2819 | ext4_lazyinit_task = NULL; | ||
2811 | ext4_li_info = NULL; | 2820 | ext4_li_info = NULL; |
2812 | mutex_unlock(&ext4_li_mtx); | 2821 | mutex_unlock(&ext4_li_mtx); |
2813 | 2822 | ||
@@ -2830,11 +2839,10 @@ static void ext4_clear_request_list(void) | |||
2830 | 2839 | ||
2831 | static int ext4_run_lazyinit_thread(void) | 2840 | static int ext4_run_lazyinit_thread(void) |
2832 | { | 2841 | { |
2833 | struct task_struct *t; | 2842 | ext4_lazyinit_task = kthread_run(ext4_lazyinit_thread, |
2834 | 2843 | ext4_li_info, "ext4lazyinit"); | |
2835 | t = kthread_run(ext4_lazyinit_thread, ext4_li_info, "ext4lazyinit"); | 2844 | if (IS_ERR(ext4_lazyinit_task)) { |
2836 | if (IS_ERR(t)) { | 2845 | int err = PTR_ERR(ext4_lazyinit_task); |
2837 | int err = PTR_ERR(t); | ||
2838 | ext4_clear_request_list(); | 2846 | ext4_clear_request_list(); |
2839 | del_timer_sync(&ext4_li_info->li_timer); | 2847 | del_timer_sync(&ext4_li_info->li_timer); |
2840 | kfree(ext4_li_info); | 2848 | kfree(ext4_li_info); |
@@ -2985,16 +2993,10 @@ static void ext4_destroy_lazyinit_thread(void) | |||
2985 | * If thread exited earlier | 2993 | * If thread exited earlier |
2986 | * there's nothing to be done. | 2994 | * there's nothing to be done. |
2987 | */ | 2995 | */ |
2988 | if (!ext4_li_info) | 2996 | if (!ext4_li_info || !ext4_lazyinit_task) |
2989 | return; | 2997 | return; |
2990 | 2998 | ||
2991 | ext4_clear_request_list(); | 2999 | kthread_stop(ext4_lazyinit_task); |
2992 | |||
2993 | while (ext4_li_info->li_task) { | ||
2994 | wake_up(&ext4_li_info->li_wait_daemon); | ||
2995 | wait_event(ext4_li_info->li_wait_task, | ||
2996 | ext4_li_info->li_task == NULL); | ||
2997 | } | ||
2998 | } | 3000 | } |
2999 | 3001 | ||
3000 | static int ext4_fill_super(struct super_block *sb, void *data, int silent) | 3002 | static int ext4_fill_super(struct super_block *sb, void *data, int silent) |
@@ -4768,7 +4770,7 @@ static struct file_system_type ext4_fs_type = { | |||
4768 | .fs_flags = FS_REQUIRES_DEV, | 4770 | .fs_flags = FS_REQUIRES_DEV, |
4769 | }; | 4771 | }; |
4770 | 4772 | ||
4771 | int __init ext4_init_feat_adverts(void) | 4773 | static int __init ext4_init_feat_adverts(void) |
4772 | { | 4774 | { |
4773 | struct ext4_features *ef; | 4775 | struct ext4_features *ef; |
4774 | int ret = -ENOMEM; | 4776 | int ret = -ENOMEM; |
@@ -4792,23 +4794,44 @@ out: | |||
4792 | return ret; | 4794 | return ret; |
4793 | } | 4795 | } |
4794 | 4796 | ||
4797 | static void ext4_exit_feat_adverts(void) | ||
4798 | { | ||
4799 | kobject_put(&ext4_feat->f_kobj); | ||
4800 | wait_for_completion(&ext4_feat->f_kobj_unregister); | ||
4801 | kfree(ext4_feat); | ||
4802 | } | ||
4803 | |||
4804 | /* Shared across all ext4 file systems */ | ||
4805 | wait_queue_head_t ext4__ioend_wq[EXT4_WQ_HASH_SZ]; | ||
4806 | struct mutex ext4__aio_mutex[EXT4_WQ_HASH_SZ]; | ||
4807 | |||
4795 | static int __init ext4_init_fs(void) | 4808 | static int __init ext4_init_fs(void) |
4796 | { | 4809 | { |
4797 | int err; | 4810 | int i, err; |
4798 | 4811 | ||
4799 | ext4_check_flag_values(); | 4812 | ext4_check_flag_values(); |
4813 | |||
4814 | for (i = 0; i < EXT4_WQ_HASH_SZ; i++) { | ||
4815 | mutex_init(&ext4__aio_mutex[i]); | ||
4816 | init_waitqueue_head(&ext4__ioend_wq[i]); | ||
4817 | } | ||
4818 | |||
4800 | err = ext4_init_pageio(); | 4819 | err = ext4_init_pageio(); |
4801 | if (err) | 4820 | if (err) |
4802 | return err; | 4821 | return err; |
4803 | err = ext4_init_system_zone(); | 4822 | err = ext4_init_system_zone(); |
4804 | if (err) | 4823 | if (err) |
4805 | goto out5; | 4824 | goto out7; |
4806 | ext4_kset = kset_create_and_add("ext4", NULL, fs_kobj); | 4825 | ext4_kset = kset_create_and_add("ext4", NULL, fs_kobj); |
4807 | if (!ext4_kset) | 4826 | if (!ext4_kset) |
4808 | goto out4; | 4827 | goto out6; |
4809 | ext4_proc_root = proc_mkdir("fs/ext4", NULL); | 4828 | ext4_proc_root = proc_mkdir("fs/ext4", NULL); |
4829 | if (!ext4_proc_root) | ||
4830 | goto out5; | ||
4810 | 4831 | ||
4811 | err = ext4_init_feat_adverts(); | 4832 | err = ext4_init_feat_adverts(); |
4833 | if (err) | ||
4834 | goto out4; | ||
4812 | 4835 | ||
4813 | err = ext4_init_mballoc(); | 4836 | err = ext4_init_mballoc(); |
4814 | if (err) | 4837 | if (err) |
@@ -4838,12 +4861,14 @@ out1: | |||
4838 | out2: | 4861 | out2: |
4839 | ext4_exit_mballoc(); | 4862 | ext4_exit_mballoc(); |
4840 | out3: | 4863 | out3: |
4841 | kfree(ext4_feat); | 4864 | ext4_exit_feat_adverts(); |
4865 | out4: | ||
4842 | remove_proc_entry("fs/ext4", NULL); | 4866 | remove_proc_entry("fs/ext4", NULL); |
4867 | out5: | ||
4843 | kset_unregister(ext4_kset); | 4868 | kset_unregister(ext4_kset); |
4844 | out4: | 4869 | out6: |
4845 | ext4_exit_system_zone(); | 4870 | ext4_exit_system_zone(); |
4846 | out5: | 4871 | out7: |
4847 | ext4_exit_pageio(); | 4872 | ext4_exit_pageio(); |
4848 | return err; | 4873 | return err; |
4849 | } | 4874 | } |
@@ -4857,6 +4882,7 @@ static void __exit ext4_exit_fs(void) | |||
4857 | destroy_inodecache(); | 4882 | destroy_inodecache(); |
4858 | ext4_exit_xattr(); | 4883 | ext4_exit_xattr(); |
4859 | ext4_exit_mballoc(); | 4884 | ext4_exit_mballoc(); |
4885 | ext4_exit_feat_adverts(); | ||
4860 | remove_proc_entry("fs/ext4", NULL); | 4886 | remove_proc_entry("fs/ext4", NULL); |
4861 | kset_unregister(ext4_kset); | 4887 | kset_unregister(ext4_kset); |
4862 | ext4_exit_system_zone(); | 4888 | ext4_exit_system_zone(); |
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 08a8beb152e6..7cd9a5a68d59 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c | |||
@@ -1779,11 +1779,11 @@ int __init gfs2_glock_init(void) | |||
1779 | #endif | 1779 | #endif |
1780 | 1780 | ||
1781 | glock_workqueue = alloc_workqueue("glock_workqueue", WQ_MEM_RECLAIM | | 1781 | glock_workqueue = alloc_workqueue("glock_workqueue", WQ_MEM_RECLAIM | |
1782 | WQ_HIGHPRI | WQ_FREEZEABLE, 0); | 1782 | WQ_HIGHPRI | WQ_FREEZABLE, 0); |
1783 | if (IS_ERR(glock_workqueue)) | 1783 | if (IS_ERR(glock_workqueue)) |
1784 | return PTR_ERR(glock_workqueue); | 1784 | return PTR_ERR(glock_workqueue); |
1785 | gfs2_delete_workqueue = alloc_workqueue("delete_workqueue", | 1785 | gfs2_delete_workqueue = alloc_workqueue("delete_workqueue", |
1786 | WQ_MEM_RECLAIM | WQ_FREEZEABLE, | 1786 | WQ_MEM_RECLAIM | WQ_FREEZABLE, |
1787 | 0); | 1787 | 0); |
1788 | if (IS_ERR(gfs2_delete_workqueue)) { | 1788 | if (IS_ERR(gfs2_delete_workqueue)) { |
1789 | destroy_workqueue(glock_workqueue); | 1789 | destroy_workqueue(glock_workqueue); |
diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c index ebef7ab6e17e..85ba027d1c4d 100644 --- a/fs/gfs2/main.c +++ b/fs/gfs2/main.c | |||
@@ -144,7 +144,7 @@ static int __init init_gfs2_fs(void) | |||
144 | 144 | ||
145 | error = -ENOMEM; | 145 | error = -ENOMEM; |
146 | gfs_recovery_wq = alloc_workqueue("gfs_recovery", | 146 | gfs_recovery_wq = alloc_workqueue("gfs_recovery", |
147 | WQ_MEM_RECLAIM | WQ_FREEZEABLE, 0); | 147 | WQ_MEM_RECLAIM | WQ_FREEZABLE, 0); |
148 | if (!gfs_recovery_wq) | 148 | if (!gfs_recovery_wq) |
149 | goto fail_wq; | 149 | goto fail_wq; |
150 | 150 | ||
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 9e4686900f18..97e73469b2c4 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c | |||
@@ -473,7 +473,8 @@ int __jbd2_log_space_left(journal_t *journal) | |||
473 | } | 473 | } |
474 | 474 | ||
475 | /* | 475 | /* |
476 | * Called under j_state_lock. Returns true if a transaction commit was started. | 476 | * Called with j_state_lock locked for writing. |
477 | * Returns true if a transaction commit was started. | ||
477 | */ | 478 | */ |
478 | int __jbd2_log_start_commit(journal_t *journal, tid_t target) | 479 | int __jbd2_log_start_commit(journal_t *journal, tid_t target) |
479 | { | 480 | { |
@@ -520,11 +521,13 @@ int jbd2_journal_force_commit_nested(journal_t *journal) | |||
520 | { | 521 | { |
521 | transaction_t *transaction = NULL; | 522 | transaction_t *transaction = NULL; |
522 | tid_t tid; | 523 | tid_t tid; |
524 | int need_to_start = 0; | ||
523 | 525 | ||
524 | read_lock(&journal->j_state_lock); | 526 | read_lock(&journal->j_state_lock); |
525 | if (journal->j_running_transaction && !current->journal_info) { | 527 | if (journal->j_running_transaction && !current->journal_info) { |
526 | transaction = journal->j_running_transaction; | 528 | transaction = journal->j_running_transaction; |
527 | __jbd2_log_start_commit(journal, transaction->t_tid); | 529 | if (!tid_geq(journal->j_commit_request, transaction->t_tid)) |
530 | need_to_start = 1; | ||
528 | } else if (journal->j_committing_transaction) | 531 | } else if (journal->j_committing_transaction) |
529 | transaction = journal->j_committing_transaction; | 532 | transaction = journal->j_committing_transaction; |
530 | 533 | ||
@@ -535,6 +538,8 @@ int jbd2_journal_force_commit_nested(journal_t *journal) | |||
535 | 538 | ||
536 | tid = transaction->t_tid; | 539 | tid = transaction->t_tid; |
537 | read_unlock(&journal->j_state_lock); | 540 | read_unlock(&journal->j_state_lock); |
541 | if (need_to_start) | ||
542 | jbd2_log_start_commit(journal, tid); | ||
538 | jbd2_log_wait_commit(journal, tid); | 543 | jbd2_log_wait_commit(journal, tid); |
539 | return 1; | 544 | return 1; |
540 | } | 545 | } |
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index faad2bd787c7..1d1191050f99 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c | |||
@@ -117,10 +117,10 @@ static inline void update_t_max_wait(transaction_t *transaction) | |||
117 | static int start_this_handle(journal_t *journal, handle_t *handle, | 117 | static int start_this_handle(journal_t *journal, handle_t *handle, |
118 | int gfp_mask) | 118 | int gfp_mask) |
119 | { | 119 | { |
120 | transaction_t *transaction; | 120 | transaction_t *transaction, *new_transaction = NULL; |
121 | int needed; | 121 | tid_t tid; |
122 | int nblocks = handle->h_buffer_credits; | 122 | int needed, need_to_start; |
123 | transaction_t *new_transaction = NULL; | 123 | int nblocks = handle->h_buffer_credits; |
124 | 124 | ||
125 | if (nblocks > journal->j_max_transaction_buffers) { | 125 | if (nblocks > journal->j_max_transaction_buffers) { |
126 | printk(KERN_ERR "JBD: %s wants too many credits (%d > %d)\n", | 126 | printk(KERN_ERR "JBD: %s wants too many credits (%d > %d)\n", |
@@ -222,8 +222,11 @@ repeat: | |||
222 | atomic_sub(nblocks, &transaction->t_outstanding_credits); | 222 | atomic_sub(nblocks, &transaction->t_outstanding_credits); |
223 | prepare_to_wait(&journal->j_wait_transaction_locked, &wait, | 223 | prepare_to_wait(&journal->j_wait_transaction_locked, &wait, |
224 | TASK_UNINTERRUPTIBLE); | 224 | TASK_UNINTERRUPTIBLE); |
225 | __jbd2_log_start_commit(journal, transaction->t_tid); | 225 | tid = transaction->t_tid; |
226 | need_to_start = !tid_geq(journal->j_commit_request, tid); | ||
226 | read_unlock(&journal->j_state_lock); | 227 | read_unlock(&journal->j_state_lock); |
228 | if (need_to_start) | ||
229 | jbd2_log_start_commit(journal, tid); | ||
227 | schedule(); | 230 | schedule(); |
228 | finish_wait(&journal->j_wait_transaction_locked, &wait); | 231 | finish_wait(&journal->j_wait_transaction_locked, &wait); |
229 | goto repeat; | 232 | goto repeat; |
@@ -442,7 +445,8 @@ int jbd2__journal_restart(handle_t *handle, int nblocks, int gfp_mask) | |||
442 | { | 445 | { |
443 | transaction_t *transaction = handle->h_transaction; | 446 | transaction_t *transaction = handle->h_transaction; |
444 | journal_t *journal = transaction->t_journal; | 447 | journal_t *journal = transaction->t_journal; |
445 | int ret; | 448 | tid_t tid; |
449 | int need_to_start, ret; | ||
446 | 450 | ||
447 | /* If we've had an abort of any type, don't even think about | 451 | /* If we've had an abort of any type, don't even think about |
448 | * actually doing the restart! */ | 452 | * actually doing the restart! */ |
@@ -465,8 +469,11 @@ int jbd2__journal_restart(handle_t *handle, int nblocks, int gfp_mask) | |||
465 | spin_unlock(&transaction->t_handle_lock); | 469 | spin_unlock(&transaction->t_handle_lock); |
466 | 470 | ||
467 | jbd_debug(2, "restarting handle %p\n", handle); | 471 | jbd_debug(2, "restarting handle %p\n", handle); |
468 | __jbd2_log_start_commit(journal, transaction->t_tid); | 472 | tid = transaction->t_tid; |
473 | need_to_start = !tid_geq(journal->j_commit_request, tid); | ||
469 | read_unlock(&journal->j_state_lock); | 474 | read_unlock(&journal->j_state_lock); |
475 | if (need_to_start) | ||
476 | jbd2_log_start_commit(journal, tid); | ||
470 | 477 | ||
471 | lock_map_release(&handle->h_lockdep_map); | 478 | lock_map_release(&handle->h_lockdep_map); |
472 | handle->h_buffer_credits = nblocks; | 479 | handle->h_buffer_credits = nblocks; |
diff --git a/fs/namei.c b/fs/namei.c index 7d77f24d32a9..0087cf9c2c6b 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -455,14 +455,6 @@ static int nameidata_dentry_drop_rcu(struct nameidata *nd, struct dentry *dentry | |||
455 | struct fs_struct *fs = current->fs; | 455 | struct fs_struct *fs = current->fs; |
456 | struct dentry *parent = nd->path.dentry; | 456 | struct dentry *parent = nd->path.dentry; |
457 | 457 | ||
458 | /* | ||
459 | * It can be possible to revalidate the dentry that we started | ||
460 | * the path walk with. force_reval_path may also revalidate the | ||
461 | * dentry already committed to the nameidata. | ||
462 | */ | ||
463 | if (unlikely(parent == dentry)) | ||
464 | return nameidata_drop_rcu(nd); | ||
465 | |||
466 | BUG_ON(!(nd->flags & LOOKUP_RCU)); | 458 | BUG_ON(!(nd->flags & LOOKUP_RCU)); |
467 | if (nd->root.mnt) { | 459 | if (nd->root.mnt) { |
468 | spin_lock(&fs->lock); | 460 | spin_lock(&fs->lock); |
@@ -561,39 +553,25 @@ static inline int nameidata_drop_rcu_last_maybe(struct nameidata *nd) | |||
561 | */ | 553 | */ |
562 | void release_open_intent(struct nameidata *nd) | 554 | void release_open_intent(struct nameidata *nd) |
563 | { | 555 | { |
564 | if (nd->intent.open.file->f_path.dentry == NULL) | 556 | struct file *file = nd->intent.open.file; |
565 | put_filp(nd->intent.open.file); | ||
566 | else | ||
567 | fput(nd->intent.open.file); | ||
568 | } | ||
569 | |||
570 | /* | ||
571 | * Call d_revalidate and handle filesystems that request rcu-walk | ||
572 | * to be dropped. This may be called and return in rcu-walk mode, | ||
573 | * regardless of success or error. If -ECHILD is returned, the caller | ||
574 | * must return -ECHILD back up the path walk stack so path walk may | ||
575 | * be restarted in ref-walk mode. | ||
576 | */ | ||
577 | static int d_revalidate(struct dentry *dentry, struct nameidata *nd) | ||
578 | { | ||
579 | int status; | ||
580 | 557 | ||
581 | status = dentry->d_op->d_revalidate(dentry, nd); | 558 | if (file && !IS_ERR(file)) { |
582 | if (status == -ECHILD) { | 559 | if (file->f_path.dentry == NULL) |
583 | if (nameidata_dentry_drop_rcu(nd, dentry)) | 560 | put_filp(file); |
584 | return status; | 561 | else |
585 | status = dentry->d_op->d_revalidate(dentry, nd); | 562 | fput(file); |
586 | } | 563 | } |
564 | } | ||
587 | 565 | ||
588 | return status; | 566 | static inline int d_revalidate(struct dentry *dentry, struct nameidata *nd) |
567 | { | ||
568 | return dentry->d_op->d_revalidate(dentry, nd); | ||
589 | } | 569 | } |
590 | 570 | ||
591 | static inline struct dentry * | 571 | static struct dentry * |
592 | do_revalidate(struct dentry *dentry, struct nameidata *nd) | 572 | do_revalidate(struct dentry *dentry, struct nameidata *nd) |
593 | { | 573 | { |
594 | int status; | 574 | int status = d_revalidate(dentry, nd); |
595 | |||
596 | status = d_revalidate(dentry, nd); | ||
597 | if (unlikely(status <= 0)) { | 575 | if (unlikely(status <= 0)) { |
598 | /* | 576 | /* |
599 | * The dentry failed validation. | 577 | * The dentry failed validation. |
@@ -602,24 +580,39 @@ do_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
602 | * to return a fail status. | 580 | * to return a fail status. |
603 | */ | 581 | */ |
604 | if (status < 0) { | 582 | if (status < 0) { |
605 | /* If we're in rcu-walk, we don't have a ref */ | 583 | dput(dentry); |
606 | if (!(nd->flags & LOOKUP_RCU)) | ||
607 | dput(dentry); | ||
608 | dentry = ERR_PTR(status); | 584 | dentry = ERR_PTR(status); |
609 | 585 | } else if (!d_invalidate(dentry)) { | |
610 | } else { | 586 | dput(dentry); |
611 | /* Don't d_invalidate in rcu-walk mode */ | 587 | dentry = NULL; |
612 | if (nameidata_dentry_drop_rcu_maybe(nd, dentry)) | ||
613 | return ERR_PTR(-ECHILD); | ||
614 | if (!d_invalidate(dentry)) { | ||
615 | dput(dentry); | ||
616 | dentry = NULL; | ||
617 | } | ||
618 | } | 588 | } |
619 | } | 589 | } |
620 | return dentry; | 590 | return dentry; |
621 | } | 591 | } |
622 | 592 | ||
593 | static inline struct dentry * | ||
594 | do_revalidate_rcu(struct dentry *dentry, struct nameidata *nd) | ||
595 | { | ||
596 | int status = d_revalidate(dentry, nd); | ||
597 | if (likely(status > 0)) | ||
598 | return dentry; | ||
599 | if (status == -ECHILD) { | ||
600 | if (nameidata_dentry_drop_rcu(nd, dentry)) | ||
601 | return ERR_PTR(-ECHILD); | ||
602 | return do_revalidate(dentry, nd); | ||
603 | } | ||
604 | if (status < 0) | ||
605 | return ERR_PTR(status); | ||
606 | /* Don't d_invalidate in rcu-walk mode */ | ||
607 | if (nameidata_dentry_drop_rcu(nd, dentry)) | ||
608 | return ERR_PTR(-ECHILD); | ||
609 | if (!d_invalidate(dentry)) { | ||
610 | dput(dentry); | ||
611 | dentry = NULL; | ||
612 | } | ||
613 | return dentry; | ||
614 | } | ||
615 | |||
623 | static inline int need_reval_dot(struct dentry *dentry) | 616 | static inline int need_reval_dot(struct dentry *dentry) |
624 | { | 617 | { |
625 | if (likely(!(dentry->d_flags & DCACHE_OP_REVALIDATE))) | 618 | if (likely(!(dentry->d_flags & DCACHE_OP_REVALIDATE))) |
@@ -664,9 +657,6 @@ force_reval_path(struct path *path, struct nameidata *nd) | |||
664 | return 0; | 657 | return 0; |
665 | 658 | ||
666 | if (!status) { | 659 | if (!status) { |
667 | /* Don't d_invalidate in rcu-walk mode */ | ||
668 | if (nameidata_drop_rcu(nd)) | ||
669 | return -ECHILD; | ||
670 | d_invalidate(dentry); | 660 | d_invalidate(dentry); |
671 | status = -ESTALE; | 661 | status = -ESTALE; |
672 | } | 662 | } |
@@ -773,6 +763,8 @@ __do_follow_link(const struct path *link, struct nameidata *nd, void **p) | |||
773 | int error; | 763 | int error; |
774 | struct dentry *dentry = link->dentry; | 764 | struct dentry *dentry = link->dentry; |
775 | 765 | ||
766 | BUG_ON(nd->flags & LOOKUP_RCU); | ||
767 | |||
776 | touch_atime(link->mnt, dentry); | 768 | touch_atime(link->mnt, dentry); |
777 | nd_set_link(nd, NULL); | 769 | nd_set_link(nd, NULL); |
778 | 770 | ||
@@ -803,10 +795,16 @@ __do_follow_link(const struct path *link, struct nameidata *nd, void **p) | |||
803 | * Without that kind of total limit, nasty chains of consecutive | 795 | * Without that kind of total limit, nasty chains of consecutive |
804 | * symlinks can cause almost arbitrarily long lookups. | 796 | * symlinks can cause almost arbitrarily long lookups. |
805 | */ | 797 | */ |
806 | static inline int do_follow_link(struct path *path, struct nameidata *nd) | 798 | static inline int do_follow_link(struct inode *inode, struct path *path, struct nameidata *nd) |
807 | { | 799 | { |
808 | void *cookie; | 800 | void *cookie; |
809 | int err = -ELOOP; | 801 | int err = -ELOOP; |
802 | |||
803 | /* We drop rcu-walk here */ | ||
804 | if (nameidata_dentry_drop_rcu_maybe(nd, path->dentry)) | ||
805 | return -ECHILD; | ||
806 | BUG_ON(inode != path->dentry->d_inode); | ||
807 | |||
810 | if (current->link_count >= MAX_NESTED_LINKS) | 808 | if (current->link_count >= MAX_NESTED_LINKS) |
811 | goto loop; | 809 | goto loop; |
812 | if (current->total_link_count >= 40) | 810 | if (current->total_link_count >= 40) |
@@ -1251,9 +1249,15 @@ static int do_lookup(struct nameidata *nd, struct qstr *name, | |||
1251 | return -ECHILD; | 1249 | return -ECHILD; |
1252 | 1250 | ||
1253 | nd->seq = seq; | 1251 | nd->seq = seq; |
1254 | if (dentry->d_flags & DCACHE_OP_REVALIDATE) | 1252 | if (unlikely(dentry->d_flags & DCACHE_OP_REVALIDATE)) { |
1255 | goto need_revalidate; | 1253 | dentry = do_revalidate_rcu(dentry, nd); |
1256 | done2: | 1254 | if (!dentry) |
1255 | goto need_lookup; | ||
1256 | if (IS_ERR(dentry)) | ||
1257 | goto fail; | ||
1258 | if (!(nd->flags & LOOKUP_RCU)) | ||
1259 | goto done; | ||
1260 | } | ||
1257 | path->mnt = mnt; | 1261 | path->mnt = mnt; |
1258 | path->dentry = dentry; | 1262 | path->dentry = dentry; |
1259 | if (likely(__follow_mount_rcu(nd, path, inode, false))) | 1263 | if (likely(__follow_mount_rcu(nd, path, inode, false))) |
@@ -1266,8 +1270,13 @@ done2: | |||
1266 | if (!dentry) | 1270 | if (!dentry) |
1267 | goto need_lookup; | 1271 | goto need_lookup; |
1268 | found: | 1272 | found: |
1269 | if (dentry->d_flags & DCACHE_OP_REVALIDATE) | 1273 | if (unlikely(dentry->d_flags & DCACHE_OP_REVALIDATE)) { |
1270 | goto need_revalidate; | 1274 | dentry = do_revalidate(dentry, nd); |
1275 | if (!dentry) | ||
1276 | goto need_lookup; | ||
1277 | if (IS_ERR(dentry)) | ||
1278 | goto fail; | ||
1279 | } | ||
1271 | done: | 1280 | done: |
1272 | path->mnt = mnt; | 1281 | path->mnt = mnt; |
1273 | path->dentry = dentry; | 1282 | path->dentry = dentry; |
@@ -1309,16 +1318,6 @@ need_lookup: | |||
1309 | mutex_unlock(&dir->i_mutex); | 1318 | mutex_unlock(&dir->i_mutex); |
1310 | goto found; | 1319 | goto found; |
1311 | 1320 | ||
1312 | need_revalidate: | ||
1313 | dentry = do_revalidate(dentry, nd); | ||
1314 | if (!dentry) | ||
1315 | goto need_lookup; | ||
1316 | if (IS_ERR(dentry)) | ||
1317 | goto fail; | ||
1318 | if (nd->flags & LOOKUP_RCU) | ||
1319 | goto done2; | ||
1320 | goto done; | ||
1321 | |||
1322 | fail: | 1321 | fail: |
1323 | return PTR_ERR(dentry); | 1322 | return PTR_ERR(dentry); |
1324 | } | 1323 | } |
@@ -1415,11 +1414,7 @@ exec_again: | |||
1415 | goto out_dput; | 1414 | goto out_dput; |
1416 | 1415 | ||
1417 | if (inode->i_op->follow_link) { | 1416 | if (inode->i_op->follow_link) { |
1418 | /* We commonly drop rcu-walk here */ | 1417 | err = do_follow_link(inode, &next, nd); |
1419 | if (nameidata_dentry_drop_rcu_maybe(nd, next.dentry)) | ||
1420 | return -ECHILD; | ||
1421 | BUG_ON(inode != next.dentry->d_inode); | ||
1422 | err = do_follow_link(&next, nd); | ||
1423 | if (err) | 1418 | if (err) |
1424 | goto return_err; | 1419 | goto return_err; |
1425 | nd->inode = nd->path.dentry->d_inode; | 1420 | nd->inode = nd->path.dentry->d_inode; |
@@ -1463,10 +1458,7 @@ last_component: | |||
1463 | break; | 1458 | break; |
1464 | if (inode && unlikely(inode->i_op->follow_link) && | 1459 | if (inode && unlikely(inode->i_op->follow_link) && |
1465 | (lookup_flags & LOOKUP_FOLLOW)) { | 1460 | (lookup_flags & LOOKUP_FOLLOW)) { |
1466 | if (nameidata_dentry_drop_rcu_maybe(nd, next.dentry)) | 1461 | err = do_follow_link(inode, &next, nd); |
1467 | return -ECHILD; | ||
1468 | BUG_ON(inode != next.dentry->d_inode); | ||
1469 | err = do_follow_link(&next, nd); | ||
1470 | if (err) | 1462 | if (err) |
1471 | goto return_err; | 1463 | goto return_err; |
1472 | nd->inode = nd->path.dentry->d_inode; | 1464 | nd->inode = nd->path.dentry->d_inode; |
@@ -1500,12 +1492,15 @@ return_reval: | |||
1500 | * We may need to check the cached dentry for staleness. | 1492 | * We may need to check the cached dentry for staleness. |
1501 | */ | 1493 | */ |
1502 | if (need_reval_dot(nd->path.dentry)) { | 1494 | if (need_reval_dot(nd->path.dentry)) { |
1495 | if (nameidata_drop_rcu_last_maybe(nd)) | ||
1496 | return -ECHILD; | ||
1503 | /* Note: we do not d_invalidate() */ | 1497 | /* Note: we do not d_invalidate() */ |
1504 | err = d_revalidate(nd->path.dentry, nd); | 1498 | err = d_revalidate(nd->path.dentry, nd); |
1505 | if (!err) | 1499 | if (!err) |
1506 | err = -ESTALE; | 1500 | err = -ESTALE; |
1507 | if (err < 0) | 1501 | if (err < 0) |
1508 | break; | 1502 | break; |
1503 | return 0; | ||
1509 | } | 1504 | } |
1510 | return_base: | 1505 | return_base: |
1511 | if (nameidata_drop_rcu_last_maybe(nd)) | 1506 | if (nameidata_drop_rcu_last_maybe(nd)) |
@@ -2265,8 +2260,6 @@ static struct file *finish_open(struct nameidata *nd, | |||
2265 | return filp; | 2260 | return filp; |
2266 | 2261 | ||
2267 | exit: | 2262 | exit: |
2268 | if (!IS_ERR(nd->intent.open.file)) | ||
2269 | release_open_intent(nd); | ||
2270 | path_put(&nd->path); | 2263 | path_put(&nd->path); |
2271 | return ERR_PTR(error); | 2264 | return ERR_PTR(error); |
2272 | } | 2265 | } |
@@ -2389,8 +2382,6 @@ exit_mutex_unlock: | |||
2389 | exit_dput: | 2382 | exit_dput: |
2390 | path_put_conditional(path, nd); | 2383 | path_put_conditional(path, nd); |
2391 | exit: | 2384 | exit: |
2392 | if (!IS_ERR(nd->intent.open.file)) | ||
2393 | release_open_intent(nd); | ||
2394 | path_put(&nd->path); | 2385 | path_put(&nd->path); |
2395 | return ERR_PTR(error); | 2386 | return ERR_PTR(error); |
2396 | } | 2387 | } |
@@ -2477,6 +2468,7 @@ struct file *do_filp_open(int dfd, const char *pathname, | |||
2477 | } | 2468 | } |
2478 | audit_inode(pathname, nd.path.dentry); | 2469 | audit_inode(pathname, nd.path.dentry); |
2479 | filp = finish_open(&nd, open_flag, acc_mode); | 2470 | filp = finish_open(&nd, open_flag, acc_mode); |
2471 | release_open_intent(&nd); | ||
2480 | return filp; | 2472 | return filp; |
2481 | 2473 | ||
2482 | creat: | 2474 | creat: |
@@ -2553,6 +2545,7 @@ out: | |||
2553 | path_put(&nd.root); | 2545 | path_put(&nd.root); |
2554 | if (filp == ERR_PTR(-ESTALE) && !(flags & LOOKUP_REVAL)) | 2546 | if (filp == ERR_PTR(-ESTALE) && !(flags & LOOKUP_REVAL)) |
2555 | goto reval; | 2547 | goto reval; |
2548 | release_open_intent(&nd); | ||
2556 | return filp; | 2549 | return filp; |
2557 | 2550 | ||
2558 | exit_dput: | 2551 | exit_dput: |
@@ -2560,8 +2553,6 @@ exit_dput: | |||
2560 | out_path: | 2553 | out_path: |
2561 | path_put(&nd.path); | 2554 | path_put(&nd.path); |
2562 | out_filp: | 2555 | out_filp: |
2563 | if (!IS_ERR(nd.intent.open.file)) | ||
2564 | release_open_intent(&nd); | ||
2565 | filp = ERR_PTR(error); | 2556 | filp = ERR_PTR(error); |
2566 | goto out; | 2557 | goto out; |
2567 | } | 2558 | } |
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c index 3be975e18919..cde36cb0f348 100644 --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c | |||
@@ -484,7 +484,7 @@ static int decode_cb_sequence4res(struct xdr_stream *xdr, | |||
484 | out: | 484 | out: |
485 | return status; | 485 | return status; |
486 | out_default: | 486 | out_default: |
487 | return nfs_cb_stat_to_errno(status); | 487 | return nfs_cb_stat_to_errno(nfserr); |
488 | } | 488 | } |
489 | 489 | ||
490 | /* | 490 | /* |
@@ -564,11 +564,9 @@ static int nfs4_xdr_dec_cb_recall(struct rpc_rqst *rqstp, | |||
564 | if (unlikely(status)) | 564 | if (unlikely(status)) |
565 | goto out; | 565 | goto out; |
566 | if (unlikely(nfserr != NFS4_OK)) | 566 | if (unlikely(nfserr != NFS4_OK)) |
567 | goto out_default; | 567 | status = nfs_cb_stat_to_errno(nfserr); |
568 | out: | 568 | out: |
569 | return status; | 569 | return status; |
570 | out_default: | ||
571 | return nfs_cb_stat_to_errno(status); | ||
572 | } | 570 | } |
573 | 571 | ||
574 | /* | 572 | /* |
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index d98d0213285d..54b60bfceb8d 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -230,9 +230,6 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f | |||
230 | dp->dl_client = clp; | 230 | dp->dl_client = clp; |
231 | get_nfs4_file(fp); | 231 | get_nfs4_file(fp); |
232 | dp->dl_file = fp; | 232 | dp->dl_file = fp; |
233 | dp->dl_vfs_file = find_readable_file(fp); | ||
234 | get_file(dp->dl_vfs_file); | ||
235 | dp->dl_flock = NULL; | ||
236 | dp->dl_type = type; | 233 | dp->dl_type = type; |
237 | dp->dl_stateid.si_boot = boot_time; | 234 | dp->dl_stateid.si_boot = boot_time; |
238 | dp->dl_stateid.si_stateownerid = current_delegid++; | 235 | dp->dl_stateid.si_stateownerid = current_delegid++; |
@@ -241,8 +238,6 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f | |||
241 | fh_copy_shallow(&dp->dl_fh, ¤t_fh->fh_handle); | 238 | fh_copy_shallow(&dp->dl_fh, ¤t_fh->fh_handle); |
242 | dp->dl_time = 0; | 239 | dp->dl_time = 0; |
243 | atomic_set(&dp->dl_count, 1); | 240 | atomic_set(&dp->dl_count, 1); |
244 | list_add(&dp->dl_perfile, &fp->fi_delegations); | ||
245 | list_add(&dp->dl_perclnt, &clp->cl_delegations); | ||
246 | INIT_WORK(&dp->dl_recall.cb_work, nfsd4_do_callback_rpc); | 241 | INIT_WORK(&dp->dl_recall.cb_work, nfsd4_do_callback_rpc); |
247 | return dp; | 242 | return dp; |
248 | } | 243 | } |
@@ -253,36 +248,30 @@ nfs4_put_delegation(struct nfs4_delegation *dp) | |||
253 | if (atomic_dec_and_test(&dp->dl_count)) { | 248 | if (atomic_dec_and_test(&dp->dl_count)) { |
254 | dprintk("NFSD: freeing dp %p\n",dp); | 249 | dprintk("NFSD: freeing dp %p\n",dp); |
255 | put_nfs4_file(dp->dl_file); | 250 | put_nfs4_file(dp->dl_file); |
256 | fput(dp->dl_vfs_file); | ||
257 | kmem_cache_free(deleg_slab, dp); | 251 | kmem_cache_free(deleg_slab, dp); |
258 | num_delegations--; | 252 | num_delegations--; |
259 | } | 253 | } |
260 | } | 254 | } |
261 | 255 | ||
262 | /* Remove the associated file_lock first, then remove the delegation. | 256 | static void nfs4_put_deleg_lease(struct nfs4_file *fp) |
263 | * lease_modify() is called to remove the FS_LEASE file_lock from | ||
264 | * the i_flock list, eventually calling nfsd's lock_manager | ||
265 | * fl_release_callback. | ||
266 | */ | ||
267 | static void | ||
268 | nfs4_close_delegation(struct nfs4_delegation *dp) | ||
269 | { | 257 | { |
270 | dprintk("NFSD: close_delegation dp %p\n",dp); | 258 | if (atomic_dec_and_test(&fp->fi_delegees)) { |
271 | /* XXX: do we even need this check?: */ | 259 | vfs_setlease(fp->fi_deleg_file, F_UNLCK, &fp->fi_lease); |
272 | if (dp->dl_flock) | 260 | fp->fi_lease = NULL; |
273 | vfs_setlease(dp->dl_vfs_file, F_UNLCK, &dp->dl_flock); | 261 | fp->fi_deleg_file = NULL; |
262 | } | ||
274 | } | 263 | } |
275 | 264 | ||
276 | /* Called under the state lock. */ | 265 | /* Called under the state lock. */ |
277 | static void | 266 | static void |
278 | unhash_delegation(struct nfs4_delegation *dp) | 267 | unhash_delegation(struct nfs4_delegation *dp) |
279 | { | 268 | { |
280 | list_del_init(&dp->dl_perfile); | ||
281 | list_del_init(&dp->dl_perclnt); | 269 | list_del_init(&dp->dl_perclnt); |
282 | spin_lock(&recall_lock); | 270 | spin_lock(&recall_lock); |
271 | list_del_init(&dp->dl_perfile); | ||
283 | list_del_init(&dp->dl_recall_lru); | 272 | list_del_init(&dp->dl_recall_lru); |
284 | spin_unlock(&recall_lock); | 273 | spin_unlock(&recall_lock); |
285 | nfs4_close_delegation(dp); | 274 | nfs4_put_deleg_lease(dp->dl_file); |
286 | nfs4_put_delegation(dp); | 275 | nfs4_put_delegation(dp); |
287 | } | 276 | } |
288 | 277 | ||
@@ -958,8 +947,6 @@ expire_client(struct nfs4_client *clp) | |||
958 | spin_lock(&recall_lock); | 947 | spin_lock(&recall_lock); |
959 | while (!list_empty(&clp->cl_delegations)) { | 948 | while (!list_empty(&clp->cl_delegations)) { |
960 | dp = list_entry(clp->cl_delegations.next, struct nfs4_delegation, dl_perclnt); | 949 | dp = list_entry(clp->cl_delegations.next, struct nfs4_delegation, dl_perclnt); |
961 | dprintk("NFSD: expire client. dp %p, fp %p\n", dp, | ||
962 | dp->dl_flock); | ||
963 | list_del_init(&dp->dl_perclnt); | 950 | list_del_init(&dp->dl_perclnt); |
964 | list_move(&dp->dl_recall_lru, &reaplist); | 951 | list_move(&dp->dl_recall_lru, &reaplist); |
965 | } | 952 | } |
@@ -2078,6 +2065,7 @@ alloc_init_file(struct inode *ino) | |||
2078 | fp->fi_inode = igrab(ino); | 2065 | fp->fi_inode = igrab(ino); |
2079 | fp->fi_id = current_fileid++; | 2066 | fp->fi_id = current_fileid++; |
2080 | fp->fi_had_conflict = false; | 2067 | fp->fi_had_conflict = false; |
2068 | fp->fi_lease = NULL; | ||
2081 | memset(fp->fi_fds, 0, sizeof(fp->fi_fds)); | 2069 | memset(fp->fi_fds, 0, sizeof(fp->fi_fds)); |
2082 | memset(fp->fi_access, 0, sizeof(fp->fi_access)); | 2070 | memset(fp->fi_access, 0, sizeof(fp->fi_access)); |
2083 | spin_lock(&recall_lock); | 2071 | spin_lock(&recall_lock); |
@@ -2329,23 +2317,8 @@ nfs4_file_downgrade(struct nfs4_file *fp, unsigned int share_access) | |||
2329 | nfs4_file_put_access(fp, O_RDONLY); | 2317 | nfs4_file_put_access(fp, O_RDONLY); |
2330 | } | 2318 | } |
2331 | 2319 | ||
2332 | /* | 2320 | static void nfsd_break_one_deleg(struct nfs4_delegation *dp) |
2333 | * Spawn a thread to perform a recall on the delegation represented | ||
2334 | * by the lease (file_lock) | ||
2335 | * | ||
2336 | * Called from break_lease() with lock_flocks() held. | ||
2337 | * Note: we assume break_lease will only call this *once* for any given | ||
2338 | * lease. | ||
2339 | */ | ||
2340 | static | ||
2341 | void nfsd_break_deleg_cb(struct file_lock *fl) | ||
2342 | { | 2321 | { |
2343 | struct nfs4_delegation *dp = (struct nfs4_delegation *)fl->fl_owner; | ||
2344 | |||
2345 | dprintk("NFSD nfsd_break_deleg_cb: dp %p fl %p\n",dp,fl); | ||
2346 | if (!dp) | ||
2347 | return; | ||
2348 | |||
2349 | /* We're assuming the state code never drops its reference | 2322 | /* We're assuming the state code never drops its reference |
2350 | * without first removing the lease. Since we're in this lease | 2323 | * without first removing the lease. Since we're in this lease |
2351 | * callback (and since the lease code is serialized by the kernel | 2324 | * callback (and since the lease code is serialized by the kernel |
@@ -2353,22 +2326,35 @@ void nfsd_break_deleg_cb(struct file_lock *fl) | |||
2353 | * it's safe to take a reference: */ | 2326 | * it's safe to take a reference: */ |
2354 | atomic_inc(&dp->dl_count); | 2327 | atomic_inc(&dp->dl_count); |
2355 | 2328 | ||
2356 | spin_lock(&recall_lock); | ||
2357 | list_add_tail(&dp->dl_recall_lru, &del_recall_lru); | 2329 | list_add_tail(&dp->dl_recall_lru, &del_recall_lru); |
2358 | spin_unlock(&recall_lock); | ||
2359 | 2330 | ||
2360 | /* only place dl_time is set. protected by lock_flocks*/ | 2331 | /* only place dl_time is set. protected by lock_flocks*/ |
2361 | dp->dl_time = get_seconds(); | 2332 | dp->dl_time = get_seconds(); |
2362 | 2333 | ||
2334 | nfsd4_cb_recall(dp); | ||
2335 | } | ||
2336 | |||
2337 | /* Called from break_lease() with lock_flocks() held. */ | ||
2338 | static void nfsd_break_deleg_cb(struct file_lock *fl) | ||
2339 | { | ||
2340 | struct nfs4_file *fp = (struct nfs4_file *)fl->fl_owner; | ||
2341 | struct nfs4_delegation *dp; | ||
2342 | |||
2343 | BUG_ON(!fp); | ||
2344 | /* We assume break_lease is only called once per lease: */ | ||
2345 | BUG_ON(fp->fi_had_conflict); | ||
2363 | /* | 2346 | /* |
2364 | * We don't want the locks code to timeout the lease for us; | 2347 | * We don't want the locks code to timeout the lease for us; |
2365 | * we'll remove it ourself if the delegation isn't returned | 2348 | * we'll remove it ourself if a delegation isn't returned |
2366 | * in time. | 2349 | * in time: |
2367 | */ | 2350 | */ |
2368 | fl->fl_break_time = 0; | 2351 | fl->fl_break_time = 0; |
2369 | 2352 | ||
2370 | dp->dl_file->fi_had_conflict = true; | 2353 | spin_lock(&recall_lock); |
2371 | nfsd4_cb_recall(dp); | 2354 | fp->fi_had_conflict = true; |
2355 | list_for_each_entry(dp, &fp->fi_delegations, dl_perfile) | ||
2356 | nfsd_break_one_deleg(dp); | ||
2357 | spin_unlock(&recall_lock); | ||
2372 | } | 2358 | } |
2373 | 2359 | ||
2374 | static | 2360 | static |
@@ -2459,13 +2445,15 @@ nfs4_check_delegmode(struct nfs4_delegation *dp, int flags) | |||
2459 | static struct nfs4_delegation * | 2445 | static struct nfs4_delegation * |
2460 | find_delegation_file(struct nfs4_file *fp, stateid_t *stid) | 2446 | find_delegation_file(struct nfs4_file *fp, stateid_t *stid) |
2461 | { | 2447 | { |
2462 | struct nfs4_delegation *dp; | 2448 | struct nfs4_delegation *dp = NULL; |
2463 | 2449 | ||
2450 | spin_lock(&recall_lock); | ||
2464 | list_for_each_entry(dp, &fp->fi_delegations, dl_perfile) { | 2451 | list_for_each_entry(dp, &fp->fi_delegations, dl_perfile) { |
2465 | if (dp->dl_stateid.si_stateownerid == stid->si_stateownerid) | 2452 | if (dp->dl_stateid.si_stateownerid == stid->si_stateownerid) |
2466 | return dp; | 2453 | break; |
2467 | } | 2454 | } |
2468 | return NULL; | 2455 | spin_unlock(&recall_lock); |
2456 | return dp; | ||
2469 | } | 2457 | } |
2470 | 2458 | ||
2471 | int share_access_to_flags(u32 share_access) | 2459 | int share_access_to_flags(u32 share_access) |
@@ -2641,6 +2629,66 @@ static bool nfsd4_cb_channel_good(struct nfs4_client *clp) | |||
2641 | return clp->cl_minorversion && clp->cl_cb_state == NFSD4_CB_UNKNOWN; | 2629 | return clp->cl_minorversion && clp->cl_cb_state == NFSD4_CB_UNKNOWN; |
2642 | } | 2630 | } |
2643 | 2631 | ||
2632 | static struct file_lock *nfs4_alloc_init_lease(struct nfs4_delegation *dp, int flag) | ||
2633 | { | ||
2634 | struct file_lock *fl; | ||
2635 | |||
2636 | fl = locks_alloc_lock(); | ||
2637 | if (!fl) | ||
2638 | return NULL; | ||
2639 | locks_init_lock(fl); | ||
2640 | fl->fl_lmops = &nfsd_lease_mng_ops; | ||
2641 | fl->fl_flags = FL_LEASE; | ||
2642 | fl->fl_type = flag == NFS4_OPEN_DELEGATE_READ? F_RDLCK: F_WRLCK; | ||
2643 | fl->fl_end = OFFSET_MAX; | ||
2644 | fl->fl_owner = (fl_owner_t)(dp->dl_file); | ||
2645 | fl->fl_pid = current->tgid; | ||
2646 | return fl; | ||
2647 | } | ||
2648 | |||
2649 | static int nfs4_setlease(struct nfs4_delegation *dp, int flag) | ||
2650 | { | ||
2651 | struct nfs4_file *fp = dp->dl_file; | ||
2652 | struct file_lock *fl; | ||
2653 | int status; | ||
2654 | |||
2655 | fl = nfs4_alloc_init_lease(dp, flag); | ||
2656 | if (!fl) | ||
2657 | return -ENOMEM; | ||
2658 | fl->fl_file = find_readable_file(fp); | ||
2659 | list_add(&dp->dl_perclnt, &dp->dl_client->cl_delegations); | ||
2660 | status = vfs_setlease(fl->fl_file, fl->fl_type, &fl); | ||
2661 | if (status) { | ||
2662 | list_del_init(&dp->dl_perclnt); | ||
2663 | locks_free_lock(fl); | ||
2664 | return -ENOMEM; | ||
2665 | } | ||
2666 | fp->fi_lease = fl; | ||
2667 | fp->fi_deleg_file = fl->fl_file; | ||
2668 | get_file(fp->fi_deleg_file); | ||
2669 | atomic_set(&fp->fi_delegees, 1); | ||
2670 | list_add(&dp->dl_perfile, &fp->fi_delegations); | ||
2671 | return 0; | ||
2672 | } | ||
2673 | |||
2674 | static int nfs4_set_delegation(struct nfs4_delegation *dp, int flag) | ||
2675 | { | ||
2676 | struct nfs4_file *fp = dp->dl_file; | ||
2677 | |||
2678 | if (!fp->fi_lease) | ||
2679 | return nfs4_setlease(dp, flag); | ||
2680 | spin_lock(&recall_lock); | ||
2681 | if (fp->fi_had_conflict) { | ||
2682 | spin_unlock(&recall_lock); | ||
2683 | return -EAGAIN; | ||
2684 | } | ||
2685 | atomic_inc(&fp->fi_delegees); | ||
2686 | list_add(&dp->dl_perfile, &fp->fi_delegations); | ||
2687 | spin_unlock(&recall_lock); | ||
2688 | list_add(&dp->dl_perclnt, &dp->dl_client->cl_delegations); | ||
2689 | return 0; | ||
2690 | } | ||
2691 | |||
2644 | /* | 2692 | /* |
2645 | * Attempt to hand out a delegation. | 2693 | * Attempt to hand out a delegation. |
2646 | */ | 2694 | */ |
@@ -2650,7 +2698,6 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta | |||
2650 | struct nfs4_delegation *dp; | 2698 | struct nfs4_delegation *dp; |
2651 | struct nfs4_stateowner *sop = stp->st_stateowner; | 2699 | struct nfs4_stateowner *sop = stp->st_stateowner; |
2652 | int cb_up; | 2700 | int cb_up; |
2653 | struct file_lock *fl; | ||
2654 | int status, flag = 0; | 2701 | int status, flag = 0; |
2655 | 2702 | ||
2656 | cb_up = nfsd4_cb_channel_good(sop->so_client); | 2703 | cb_up = nfsd4_cb_channel_good(sop->so_client); |
@@ -2681,36 +2728,11 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta | |||
2681 | } | 2728 | } |
2682 | 2729 | ||
2683 | dp = alloc_init_deleg(sop->so_client, stp, fh, flag); | 2730 | dp = alloc_init_deleg(sop->so_client, stp, fh, flag); |
2684 | if (dp == NULL) { | 2731 | if (dp == NULL) |
2685 | flag = NFS4_OPEN_DELEGATE_NONE; | 2732 | goto out_no_deleg; |
2686 | goto out; | 2733 | status = nfs4_set_delegation(dp, flag); |
2687 | } | 2734 | if (status) |
2688 | status = -ENOMEM; | 2735 | goto out_free; |
2689 | fl = locks_alloc_lock(); | ||
2690 | if (!fl) | ||
2691 | goto out; | ||
2692 | locks_init_lock(fl); | ||
2693 | fl->fl_lmops = &nfsd_lease_mng_ops; | ||
2694 | fl->fl_flags = FL_LEASE; | ||
2695 | fl->fl_type = flag == NFS4_OPEN_DELEGATE_READ? F_RDLCK: F_WRLCK; | ||
2696 | fl->fl_end = OFFSET_MAX; | ||
2697 | fl->fl_owner = (fl_owner_t)dp; | ||
2698 | fl->fl_file = find_readable_file(stp->st_file); | ||
2699 | BUG_ON(!fl->fl_file); | ||
2700 | fl->fl_pid = current->tgid; | ||
2701 | dp->dl_flock = fl; | ||
2702 | |||
2703 | /* vfs_setlease checks to see if delegation should be handed out. | ||
2704 | * the lock_manager callback fl_change is used | ||
2705 | */ | ||
2706 | if ((status = vfs_setlease(fl->fl_file, fl->fl_type, &fl))) { | ||
2707 | dprintk("NFSD: setlease failed [%d], no delegation\n", status); | ||
2708 | dp->dl_flock = NULL; | ||
2709 | locks_free_lock(fl); | ||
2710 | unhash_delegation(dp); | ||
2711 | flag = NFS4_OPEN_DELEGATE_NONE; | ||
2712 | goto out; | ||
2713 | } | ||
2714 | 2736 | ||
2715 | memcpy(&open->op_delegate_stateid, &dp->dl_stateid, sizeof(dp->dl_stateid)); | 2737 | memcpy(&open->op_delegate_stateid, &dp->dl_stateid, sizeof(dp->dl_stateid)); |
2716 | 2738 | ||
@@ -2722,6 +2744,12 @@ out: | |||
2722 | && open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE) | 2744 | && open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE) |
2723 | dprintk("NFSD: WARNING: refusing delegation reclaim\n"); | 2745 | dprintk("NFSD: WARNING: refusing delegation reclaim\n"); |
2724 | open->op_delegate_type = flag; | 2746 | open->op_delegate_type = flag; |
2747 | return; | ||
2748 | out_free: | ||
2749 | nfs4_put_delegation(dp); | ||
2750 | out_no_deleg: | ||
2751 | flag = NFS4_OPEN_DELEGATE_NONE; | ||
2752 | goto out; | ||
2725 | } | 2753 | } |
2726 | 2754 | ||
2727 | /* | 2755 | /* |
@@ -2916,8 +2944,6 @@ nfs4_laundromat(void) | |||
2916 | test_val = u; | 2944 | test_val = u; |
2917 | break; | 2945 | break; |
2918 | } | 2946 | } |
2919 | dprintk("NFSD: purging unused delegation dp %p, fp %p\n", | ||
2920 | dp, dp->dl_flock); | ||
2921 | list_move(&dp->dl_recall_lru, &reaplist); | 2947 | list_move(&dp->dl_recall_lru, &reaplist); |
2922 | } | 2948 | } |
2923 | spin_unlock(&recall_lock); | 2949 | spin_unlock(&recall_lock); |
@@ -3128,7 +3154,7 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate, | |||
3128 | goto out; | 3154 | goto out; |
3129 | renew_client(dp->dl_client); | 3155 | renew_client(dp->dl_client); |
3130 | if (filpp) { | 3156 | if (filpp) { |
3131 | *filpp = find_readable_file(dp->dl_file); | 3157 | *filpp = dp->dl_file->fi_deleg_file; |
3132 | BUG_ON(!*filpp); | 3158 | BUG_ON(!*filpp); |
3133 | } | 3159 | } |
3134 | } else { /* open or lock stateid */ | 3160 | } else { /* open or lock stateid */ |
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 956629b9cdc9..1275b8655070 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
@@ -317,8 +317,8 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, | |||
317 | READ_BUF(dummy32); | 317 | READ_BUF(dummy32); |
318 | len += (XDR_QUADLEN(dummy32) << 2); | 318 | len += (XDR_QUADLEN(dummy32) << 2); |
319 | READMEM(buf, dummy32); | 319 | READMEM(buf, dummy32); |
320 | if ((host_err = nfsd_map_name_to_uid(argp->rqstp, buf, dummy32, &iattr->ia_uid))) | 320 | if ((status = nfsd_map_name_to_uid(argp->rqstp, buf, dummy32, &iattr->ia_uid))) |
321 | goto out_nfserr; | 321 | return status; |
322 | iattr->ia_valid |= ATTR_UID; | 322 | iattr->ia_valid |= ATTR_UID; |
323 | } | 323 | } |
324 | if (bmval[1] & FATTR4_WORD1_OWNER_GROUP) { | 324 | if (bmval[1] & FATTR4_WORD1_OWNER_GROUP) { |
@@ -328,8 +328,8 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, | |||
328 | READ_BUF(dummy32); | 328 | READ_BUF(dummy32); |
329 | len += (XDR_QUADLEN(dummy32) << 2); | 329 | len += (XDR_QUADLEN(dummy32) << 2); |
330 | READMEM(buf, dummy32); | 330 | READMEM(buf, dummy32); |
331 | if ((host_err = nfsd_map_name_to_gid(argp->rqstp, buf, dummy32, &iattr->ia_gid))) | 331 | if ((status = nfsd_map_name_to_gid(argp->rqstp, buf, dummy32, &iattr->ia_gid))) |
332 | goto out_nfserr; | 332 | return status; |
333 | iattr->ia_valid |= ATTR_GID; | 333 | iattr->ia_valid |= ATTR_GID; |
334 | } | 334 | } |
335 | if (bmval[1] & FATTR4_WORD1_TIME_ACCESS_SET) { | 335 | if (bmval[1] & FATTR4_WORD1_TIME_ACCESS_SET) { |
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index 3074656ba7bf..2d31224b07bf 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h | |||
@@ -83,8 +83,6 @@ struct nfs4_delegation { | |||
83 | atomic_t dl_count; /* ref count */ | 83 | atomic_t dl_count; /* ref count */ |
84 | struct nfs4_client *dl_client; | 84 | struct nfs4_client *dl_client; |
85 | struct nfs4_file *dl_file; | 85 | struct nfs4_file *dl_file; |
86 | struct file *dl_vfs_file; | ||
87 | struct file_lock *dl_flock; | ||
88 | u32 dl_type; | 86 | u32 dl_type; |
89 | time_t dl_time; | 87 | time_t dl_time; |
90 | /* For recall: */ | 88 | /* For recall: */ |
@@ -379,6 +377,9 @@ struct nfs4_file { | |||
379 | */ | 377 | */ |
380 | atomic_t fi_readers; | 378 | atomic_t fi_readers; |
381 | atomic_t fi_writers; | 379 | atomic_t fi_writers; |
380 | struct file *fi_deleg_file; | ||
381 | struct file_lock *fi_lease; | ||
382 | atomic_t fi_delegees; | ||
382 | struct inode *fi_inode; | 383 | struct inode *fi_inode; |
383 | u32 fi_id; /* used with stateowner->so_id | 384 | u32 fi_id; /* used with stateowner->so_id |
384 | * for stateid_hashtbl hash */ | 385 | * for stateid_hashtbl hash */ |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 641117f2188d..da1d9701f8e4 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -808,7 +808,7 @@ nfsd_get_raparms(dev_t dev, ino_t ino) | |||
808 | if (ra->p_count == 0) | 808 | if (ra->p_count == 0) |
809 | frap = rap; | 809 | frap = rap; |
810 | } | 810 | } |
811 | depth = nfsdstats.ra_size*11/10; | 811 | depth = nfsdstats.ra_size; |
812 | if (!frap) { | 812 | if (!frap) { |
813 | spin_unlock(&rab->pb_lock); | 813 | spin_unlock(&rab->pb_lock); |
814 | return NULL; | 814 | return NULL; |
@@ -1744,6 +1744,13 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, | |||
1744 | host_err = nfsd_break_lease(odentry->d_inode); | 1744 | host_err = nfsd_break_lease(odentry->d_inode); |
1745 | if (host_err) | 1745 | if (host_err) |
1746 | goto out_drop_write; | 1746 | goto out_drop_write; |
1747 | if (ndentry->d_inode) { | ||
1748 | host_err = nfsd_break_lease(ndentry->d_inode); | ||
1749 | if (host_err) | ||
1750 | goto out_drop_write; | ||
1751 | } | ||
1752 | if (host_err) | ||
1753 | goto out_drop_write; | ||
1747 | host_err = vfs_rename(fdir, odentry, tdir, ndentry); | 1754 | host_err = vfs_rename(fdir, odentry, tdir, ndentry); |
1748 | if (!host_err) { | 1755 | if (!host_err) { |
1749 | host_err = commit_metadata(tfhp); | 1756 | host_err = commit_metadata(tfhp); |
@@ -1812,22 +1819,22 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, | |||
1812 | 1819 | ||
1813 | host_err = mnt_want_write(fhp->fh_export->ex_path.mnt); | 1820 | host_err = mnt_want_write(fhp->fh_export->ex_path.mnt); |
1814 | if (host_err) | 1821 | if (host_err) |
1815 | goto out_nfserr; | 1822 | goto out_put; |
1816 | 1823 | ||
1817 | host_err = nfsd_break_lease(rdentry->d_inode); | 1824 | host_err = nfsd_break_lease(rdentry->d_inode); |
1818 | if (host_err) | 1825 | if (host_err) |
1819 | goto out_put; | 1826 | goto out_drop_write; |
1820 | if (type != S_IFDIR) | 1827 | if (type != S_IFDIR) |
1821 | host_err = vfs_unlink(dirp, rdentry); | 1828 | host_err = vfs_unlink(dirp, rdentry); |
1822 | else | 1829 | else |
1823 | host_err = vfs_rmdir(dirp, rdentry); | 1830 | host_err = vfs_rmdir(dirp, rdentry); |
1824 | out_put: | ||
1825 | dput(rdentry); | ||
1826 | |||
1827 | if (!host_err) | 1831 | if (!host_err) |
1828 | host_err = commit_metadata(fhp); | 1832 | host_err = commit_metadata(fhp); |
1829 | 1833 | out_drop_write: | |
1830 | mnt_drop_write(fhp->fh_export->ex_path.mnt); | 1834 | mnt_drop_write(fhp->fh_export->ex_path.mnt); |
1835 | out_put: | ||
1836 | dput(rdentry); | ||
1837 | |||
1831 | out_nfserr: | 1838 | out_nfserr: |
1832 | err = nfserrno(host_err); | 1839 | err = nfserrno(host_err); |
1833 | out: | 1840 | out: |
@@ -790,6 +790,8 @@ struct file *nameidata_to_filp(struct nameidata *nd) | |||
790 | 790 | ||
791 | /* Pick up the filp from the open intent */ | 791 | /* Pick up the filp from the open intent */ |
792 | filp = nd->intent.open.file; | 792 | filp = nd->intent.open.file; |
793 | nd->intent.open.file = NULL; | ||
794 | |||
793 | /* Has the filesystem initialised the file for us? */ | 795 | /* Has the filesystem initialised the file for us? */ |
794 | if (filp->f_path.dentry == NULL) { | 796 | if (filp->f_path.dentry == NULL) { |
795 | path_get(&nd->path); | 797 | path_get(&nd->path); |
diff --git a/fs/partitions/mac.c b/fs/partitions/mac.c index 68d6a216ee79..11f688bd76c5 100644 --- a/fs/partitions/mac.c +++ b/fs/partitions/mac.c | |||
@@ -29,10 +29,9 @@ static inline void mac_fix_string(char *stg, int len) | |||
29 | 29 | ||
30 | int mac_partition(struct parsed_partitions *state) | 30 | int mac_partition(struct parsed_partitions *state) |
31 | { | 31 | { |
32 | int slot = 1; | ||
33 | Sector sect; | 32 | Sector sect; |
34 | unsigned char *data; | 33 | unsigned char *data; |
35 | int blk, blocks_in_map; | 34 | int slot, blocks_in_map; |
36 | unsigned secsize; | 35 | unsigned secsize; |
37 | #ifdef CONFIG_PPC_PMAC | 36 | #ifdef CONFIG_PPC_PMAC |
38 | int found_root = 0; | 37 | int found_root = 0; |
@@ -59,10 +58,14 @@ int mac_partition(struct parsed_partitions *state) | |||
59 | put_dev_sector(sect); | 58 | put_dev_sector(sect); |
60 | return 0; /* not a MacOS disk */ | 59 | return 0; /* not a MacOS disk */ |
61 | } | 60 | } |
62 | strlcat(state->pp_buf, " [mac]", PAGE_SIZE); | ||
63 | blocks_in_map = be32_to_cpu(part->map_count); | 61 | blocks_in_map = be32_to_cpu(part->map_count); |
64 | for (blk = 1; blk <= blocks_in_map; ++blk) { | 62 | if (blocks_in_map < 0 || blocks_in_map >= DISK_MAX_PARTS) { |
65 | int pos = blk * secsize; | 63 | put_dev_sector(sect); |
64 | return 0; | ||
65 | } | ||
66 | strlcat(state->pp_buf, " [mac]", PAGE_SIZE); | ||
67 | for (slot = 1; slot <= blocks_in_map; ++slot) { | ||
68 | int pos = slot * secsize; | ||
66 | put_dev_sector(sect); | 69 | put_dev_sector(sect); |
67 | data = read_part_sector(state, pos/512, §); | 70 | data = read_part_sector(state, pos/512, §); |
68 | if (!data) | 71 | if (!data) |
@@ -113,13 +116,11 @@ int mac_partition(struct parsed_partitions *state) | |||
113 | } | 116 | } |
114 | 117 | ||
115 | if (goodness > found_root_goodness) { | 118 | if (goodness > found_root_goodness) { |
116 | found_root = blk; | 119 | found_root = slot; |
117 | found_root_goodness = goodness; | 120 | found_root_goodness = goodness; |
118 | } | 121 | } |
119 | } | 122 | } |
120 | #endif /* CONFIG_PPC_PMAC */ | 123 | #endif /* CONFIG_PPC_PMAC */ |
121 | |||
122 | ++slot; | ||
123 | } | 124 | } |
124 | #ifdef CONFIG_PPC_PMAC | 125 | #ifdef CONFIG_PPC_PMAC |
125 | if (found_root_goodness) | 126 | if (found_root_goodness) |
diff --git a/fs/proc/array.c b/fs/proc/array.c index df2b703b9d0f..7c99c1cf7e5c 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c | |||
@@ -353,9 +353,6 @@ int proc_pid_status(struct seq_file *m, struct pid_namespace *ns, | |||
353 | task_cap(m, task); | 353 | task_cap(m, task); |
354 | task_cpus_allowed(m, task); | 354 | task_cpus_allowed(m, task); |
355 | cpuset_task_status_allowed(m, task); | 355 | cpuset_task_status_allowed(m, task); |
356 | #if defined(CONFIG_S390) | ||
357 | task_show_regs(m, task); | ||
358 | #endif | ||
359 | task_context_switch_counts(m, task); | 356 | task_context_switch_counts(m, task); |
360 | return 0; | 357 | return 0; |
361 | } | 358 | } |
diff --git a/fs/super.c b/fs/super.c index 74e149efed81..7e9dd4cc2c01 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -177,6 +177,11 @@ void deactivate_locked_super(struct super_block *s) | |||
177 | struct file_system_type *fs = s->s_type; | 177 | struct file_system_type *fs = s->s_type; |
178 | if (atomic_dec_and_test(&s->s_active)) { | 178 | if (atomic_dec_and_test(&s->s_active)) { |
179 | fs->kill_sb(s); | 179 | fs->kill_sb(s); |
180 | /* | ||
181 | * We need to call rcu_barrier so all the delayed rcu free | ||
182 | * inodes are flushed before we release the fs module. | ||
183 | */ | ||
184 | rcu_barrier(); | ||
180 | put_filesystem(fs); | 185 | put_filesystem(fs); |
181 | put_super(s); | 186 | put_super(s); |
182 | } else { | 187 | } else { |