diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/btrfs/disk-io.c | 8 | ||||
| -rw-r--r-- | fs/btrfs/extent-tree.c | 2 | ||||
| -rw-r--r-- | fs/btrfs/extent_io.c | 48 | ||||
| -rw-r--r-- | fs/btrfs/extent_map.c | 4 | ||||
| -rw-r--r-- | fs/btrfs/file.c | 1 | ||||
| -rw-r--r-- | fs/btrfs/inode.c | 3 | ||||
| -rw-r--r-- | fs/btrfs/ioctl.c | 10 | ||||
| -rw-r--r-- | fs/btrfs/relocation.c | 1 | ||||
| -rw-r--r-- | fs/btrfs/volumes.c | 2 | ||||
| -rw-r--r-- | fs/cifs/cifsglob.h | 4 | ||||
| -rw-r--r-- | fs/cifs/connect.c | 37 | ||||
| -rw-r--r-- | fs/cifs/transport.c | 3 | ||||
| -rw-r--r-- | fs/dlm/lowcomms.c | 6 | ||||
| -rw-r--r-- | fs/ext4/ext4.h | 10 | ||||
| -rw-r--r-- | fs/ext4/extents.c | 10 | ||||
| -rw-r--r-- | fs/ext4/file.c | 60 | ||||
| -rw-r--r-- | fs/ext4/mballoc.c | 100 | ||||
| -rw-r--r-- | fs/ext4/page-io.c | 36 | ||||
| -rw-r--r-- | fs/ext4/super.c | 66 | ||||
| -rw-r--r-- | fs/jbd2/journal.c | 9 | ||||
| -rw-r--r-- | fs/jbd2/transaction.c | 21 | ||||
| -rw-r--r-- | fs/namei.c | 142 | ||||
| -rw-r--r-- | fs/nfsd/nfs4callback.c | 6 | ||||
| -rw-r--r-- | fs/nfsd/nfs4state.c | 186 | ||||
| -rw-r--r-- | fs/nfsd/state.h | 5 | ||||
| -rw-r--r-- | fs/nfsd/vfs.c | 21 | ||||
| -rw-r--r-- | fs/open.c | 2 | ||||
| -rw-r--r-- | fs/proc/array.c | 3 | ||||
| -rw-r--r-- | fs/super.c | 5 |
29 files changed, 524 insertions, 287 deletions
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/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/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/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/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..9e701e28a329 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 | ||
| @@ -807,6 +799,11 @@ static inline int do_follow_link(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 | |||
| 810 | if (current->link_count >= MAX_NESTED_LINKS) | 807 | if (current->link_count >= MAX_NESTED_LINKS) |
| 811 | goto loop; | 808 | goto loop; |
| 812 | if (current->total_link_count >= 40) | 809 | if (current->total_link_count >= 40) |
| @@ -1251,9 +1248,15 @@ static int do_lookup(struct nameidata *nd, struct qstr *name, | |||
| 1251 | return -ECHILD; | 1248 | return -ECHILD; |
| 1252 | 1249 | ||
| 1253 | nd->seq = seq; | 1250 | nd->seq = seq; |
| 1254 | if (dentry->d_flags & DCACHE_OP_REVALIDATE) | 1251 | if (unlikely(dentry->d_flags & DCACHE_OP_REVALIDATE)) { |
| 1255 | goto need_revalidate; | 1252 | dentry = do_revalidate_rcu(dentry, nd); |
| 1256 | done2: | 1253 | if (!dentry) |
| 1254 | goto need_lookup; | ||
| 1255 | if (IS_ERR(dentry)) | ||
| 1256 | goto fail; | ||
| 1257 | if (!(nd->flags & LOOKUP_RCU)) | ||
| 1258 | goto done; | ||
| 1259 | } | ||
| 1257 | path->mnt = mnt; | 1260 | path->mnt = mnt; |
| 1258 | path->dentry = dentry; | 1261 | path->dentry = dentry; |
| 1259 | if (likely(__follow_mount_rcu(nd, path, inode, false))) | 1262 | if (likely(__follow_mount_rcu(nd, path, inode, false))) |
| @@ -1266,8 +1269,13 @@ done2: | |||
| 1266 | if (!dentry) | 1269 | if (!dentry) |
| 1267 | goto need_lookup; | 1270 | goto need_lookup; |
| 1268 | found: | 1271 | found: |
| 1269 | if (dentry->d_flags & DCACHE_OP_REVALIDATE) | 1272 | if (unlikely(dentry->d_flags & DCACHE_OP_REVALIDATE)) { |
| 1270 | goto need_revalidate; | 1273 | dentry = do_revalidate(dentry, nd); |
| 1274 | if (!dentry) | ||
| 1275 | goto need_lookup; | ||
| 1276 | if (IS_ERR(dentry)) | ||
| 1277 | goto fail; | ||
| 1278 | } | ||
| 1271 | done: | 1279 | done: |
| 1272 | path->mnt = mnt; | 1280 | path->mnt = mnt; |
| 1273 | path->dentry = dentry; | 1281 | path->dentry = dentry; |
| @@ -1309,16 +1317,6 @@ need_lookup: | |||
| 1309 | mutex_unlock(&dir->i_mutex); | 1317 | mutex_unlock(&dir->i_mutex); |
| 1310 | goto found; | 1318 | goto found; |
| 1311 | 1319 | ||
| 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: | 1320 | fail: |
| 1323 | return PTR_ERR(dentry); | 1321 | return PTR_ERR(dentry); |
| 1324 | } | 1322 | } |
| @@ -1415,9 +1413,6 @@ exec_again: | |||
| 1415 | goto out_dput; | 1413 | goto out_dput; |
| 1416 | 1414 | ||
| 1417 | if (inode->i_op->follow_link) { | 1415 | if (inode->i_op->follow_link) { |
| 1418 | /* We commonly drop rcu-walk here */ | ||
| 1419 | if (nameidata_dentry_drop_rcu_maybe(nd, next.dentry)) | ||
| 1420 | return -ECHILD; | ||
| 1421 | BUG_ON(inode != next.dentry->d_inode); | 1416 | BUG_ON(inode != next.dentry->d_inode); |
| 1422 | err = do_follow_link(&next, nd); | 1417 | err = do_follow_link(&next, nd); |
| 1423 | if (err) | 1418 | if (err) |
| @@ -1463,8 +1458,6 @@ 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)) | ||
| 1467 | return -ECHILD; | ||
| 1468 | BUG_ON(inode != next.dentry->d_inode); | 1461 | BUG_ON(inode != next.dentry->d_inode); |
| 1469 | err = do_follow_link(&next, nd); | 1462 | err = do_follow_link(&next, nd); |
| 1470 | if (err) | 1463 | if (err) |
| @@ -1500,12 +1493,15 @@ return_reval: | |||
| 1500 | * We may need to check the cached dentry for staleness. | 1493 | * We may need to check the cached dentry for staleness. |
| 1501 | */ | 1494 | */ |
| 1502 | if (need_reval_dot(nd->path.dentry)) { | 1495 | if (need_reval_dot(nd->path.dentry)) { |
| 1496 | if (nameidata_drop_rcu_last_maybe(nd)) | ||
| 1497 | return -ECHILD; | ||
| 1503 | /* Note: we do not d_invalidate() */ | 1498 | /* Note: we do not d_invalidate() */ |
| 1504 | err = d_revalidate(nd->path.dentry, nd); | 1499 | err = d_revalidate(nd->path.dentry, nd); |
| 1505 | if (!err) | 1500 | if (!err) |
| 1506 | err = -ESTALE; | 1501 | err = -ESTALE; |
| 1507 | if (err < 0) | 1502 | if (err < 0) |
| 1508 | break; | 1503 | break; |
| 1504 | return 0; | ||
| 1509 | } | 1505 | } |
| 1510 | return_base: | 1506 | return_base: |
| 1511 | if (nameidata_drop_rcu_last_maybe(nd)) | 1507 | if (nameidata_drop_rcu_last_maybe(nd)) |
| @@ -2265,8 +2261,6 @@ static struct file *finish_open(struct nameidata *nd, | |||
| 2265 | return filp; | 2261 | return filp; |
| 2266 | 2262 | ||
| 2267 | exit: | 2263 | exit: |
| 2268 | if (!IS_ERR(nd->intent.open.file)) | ||
| 2269 | release_open_intent(nd); | ||
| 2270 | path_put(&nd->path); | 2264 | path_put(&nd->path); |
| 2271 | return ERR_PTR(error); | 2265 | return ERR_PTR(error); |
| 2272 | } | 2266 | } |
| @@ -2389,8 +2383,6 @@ exit_mutex_unlock: | |||
| 2389 | exit_dput: | 2383 | exit_dput: |
| 2390 | path_put_conditional(path, nd); | 2384 | path_put_conditional(path, nd); |
| 2391 | exit: | 2385 | exit: |
| 2392 | if (!IS_ERR(nd->intent.open.file)) | ||
| 2393 | release_open_intent(nd); | ||
| 2394 | path_put(&nd->path); | 2386 | path_put(&nd->path); |
| 2395 | return ERR_PTR(error); | 2387 | return ERR_PTR(error); |
| 2396 | } | 2388 | } |
| @@ -2477,6 +2469,7 @@ struct file *do_filp_open(int dfd, const char *pathname, | |||
| 2477 | } | 2469 | } |
| 2478 | audit_inode(pathname, nd.path.dentry); | 2470 | audit_inode(pathname, nd.path.dentry); |
| 2479 | filp = finish_open(&nd, open_flag, acc_mode); | 2471 | filp = finish_open(&nd, open_flag, acc_mode); |
| 2472 | release_open_intent(&nd); | ||
| 2480 | return filp; | 2473 | return filp; |
| 2481 | 2474 | ||
| 2482 | creat: | 2475 | creat: |
| @@ -2553,6 +2546,7 @@ out: | |||
| 2553 | path_put(&nd.root); | 2546 | path_put(&nd.root); |
| 2554 | if (filp == ERR_PTR(-ESTALE) && !(flags & LOOKUP_REVAL)) | 2547 | if (filp == ERR_PTR(-ESTALE) && !(flags & LOOKUP_REVAL)) |
| 2555 | goto reval; | 2548 | goto reval; |
| 2549 | release_open_intent(&nd); | ||
| 2556 | return filp; | 2550 | return filp; |
| 2557 | 2551 | ||
| 2558 | exit_dput: | 2552 | exit_dput: |
| @@ -2560,8 +2554,6 @@ exit_dput: | |||
| 2560 | out_path: | 2554 | out_path: |
| 2561 | path_put(&nd.path); | 2555 | path_put(&nd.path); |
| 2562 | out_filp: | 2556 | out_filp: |
| 2563 | if (!IS_ERR(nd.intent.open.file)) | ||
| 2564 | release_open_intent(&nd); | ||
| 2565 | filp = ERR_PTR(error); | 2557 | filp = ERR_PTR(error); |
| 2566 | goto out; | 2558 | goto out; |
| 2567 | } | 2559 | } |
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/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/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 { |
