diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/btrfs/ctree.c | 8 | ||||
| -rw-r--r-- | fs/btrfs/extent-tree.c | 16 | ||||
| -rw-r--r-- | fs/btrfs/file.c | 87 | ||||
| -rw-r--r-- | fs/btrfs/inode.c | 1 | ||||
| -rw-r--r-- | fs/btrfs/ordered-data.c | 7 | ||||
| -rw-r--r-- | fs/btrfs/send.c | 171 | ||||
| -rw-r--r-- | fs/btrfs/transaction.c | 3 | ||||
| -rw-r--r-- | fs/btrfs/tree-log.c | 2 | ||||
| -rw-r--r-- | fs/btrfs/xattr.c | 8 | ||||
| -rw-r--r-- | fs/ecryptfs/ecryptfs_kernel.h | 4 | ||||
| -rw-r--r-- | fs/ecryptfs/file.c | 34 | ||||
| -rw-r--r-- | fs/ecryptfs/keystore.c | 2 | ||||
| -rw-r--r-- | fs/ecryptfs/main.c | 2 | ||||
| -rw-r--r-- | fs/locks.c | 3 | ||||
| -rw-r--r-- | fs/nfs/client.c | 2 | ||||
| -rw-r--r-- | fs/nfs/delegation.c | 45 | ||||
| -rw-r--r-- | fs/nfs/dir.c | 22 | ||||
| -rw-r--r-- | fs/nfs/file.c | 11 | ||||
| -rw-r--r-- | fs/nfs/inode.c | 111 | ||||
| -rw-r--r-- | fs/nfs/internal.h | 1 | ||||
| -rw-r--r-- | fs/nfs/nfs3proc.c | 4 | ||||
| -rw-r--r-- | fs/nfs/nfs3xdr.c | 5 | ||||
| -rw-r--r-- | fs/nfs/nfs4client.c | 9 | ||||
| -rw-r--r-- | fs/nfs/nfs4proc.c | 31 | ||||
| -rw-r--r-- | fs/nfs/nfs4session.h | 1 | ||||
| -rw-r--r-- | fs/nfs/nfs4state.c | 18 | ||||
| -rw-r--r-- | fs/nfs/proc.c | 6 | ||||
| -rw-r--r-- | fs/nfs/write.c | 30 |
28 files changed, 514 insertions, 130 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 993642199326..6d67f32e648d 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
| @@ -1645,14 +1645,14 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, | |||
| 1645 | 1645 | ||
| 1646 | parent_nritems = btrfs_header_nritems(parent); | 1646 | parent_nritems = btrfs_header_nritems(parent); |
| 1647 | blocksize = root->nodesize; | 1647 | blocksize = root->nodesize; |
| 1648 | end_slot = parent_nritems; | 1648 | end_slot = parent_nritems - 1; |
| 1649 | 1649 | ||
| 1650 | if (parent_nritems == 1) | 1650 | if (parent_nritems <= 1) |
| 1651 | return 0; | 1651 | return 0; |
| 1652 | 1652 | ||
| 1653 | btrfs_set_lock_blocking(parent); | 1653 | btrfs_set_lock_blocking(parent); |
| 1654 | 1654 | ||
| 1655 | for (i = start_slot; i < end_slot; i++) { | 1655 | for (i = start_slot; i <= end_slot; i++) { |
| 1656 | int close = 1; | 1656 | int close = 1; |
| 1657 | 1657 | ||
| 1658 | btrfs_node_key(parent, &disk_key, i); | 1658 | btrfs_node_key(parent, &disk_key, i); |
| @@ -1669,7 +1669,7 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, | |||
| 1669 | other = btrfs_node_blockptr(parent, i - 1); | 1669 | other = btrfs_node_blockptr(parent, i - 1); |
| 1670 | close = close_blocks(blocknr, other, blocksize); | 1670 | close = close_blocks(blocknr, other, blocksize); |
| 1671 | } | 1671 | } |
| 1672 | if (!close && i < end_slot - 2) { | 1672 | if (!close && i < end_slot) { |
| 1673 | other = btrfs_node_blockptr(parent, i + 1); | 1673 | other = btrfs_node_blockptr(parent, i + 1); |
| 1674 | close = close_blocks(blocknr, other, blocksize); | 1674 | close = close_blocks(blocknr, other, blocksize); |
| 1675 | } | 1675 | } |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 571f402d3fc4..6f080451fcb1 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
| @@ -3208,6 +3208,8 @@ static int cache_save_setup(struct btrfs_block_group_cache *block_group, | |||
| 3208 | return 0; | 3208 | return 0; |
| 3209 | } | 3209 | } |
| 3210 | 3210 | ||
| 3211 | if (trans->aborted) | ||
| 3212 | return 0; | ||
| 3211 | again: | 3213 | again: |
| 3212 | inode = lookup_free_space_inode(root, block_group, path); | 3214 | inode = lookup_free_space_inode(root, block_group, path); |
| 3213 | if (IS_ERR(inode) && PTR_ERR(inode) != -ENOENT) { | 3215 | if (IS_ERR(inode) && PTR_ERR(inode) != -ENOENT) { |
| @@ -3243,6 +3245,20 @@ again: | |||
| 3243 | */ | 3245 | */ |
| 3244 | BTRFS_I(inode)->generation = 0; | 3246 | BTRFS_I(inode)->generation = 0; |
| 3245 | ret = btrfs_update_inode(trans, root, inode); | 3247 | ret = btrfs_update_inode(trans, root, inode); |
| 3248 | if (ret) { | ||
| 3249 | /* | ||
| 3250 | * So theoretically we could recover from this, simply set the | ||
| 3251 | * super cache generation to 0 so we know to invalidate the | ||
| 3252 | * cache, but then we'd have to keep track of the block groups | ||
| 3253 | * that fail this way so we know we _have_ to reset this cache | ||
| 3254 | * before the next commit or risk reading stale cache. So to | ||
| 3255 | * limit our exposure to horrible edge cases lets just abort the | ||
| 3256 | * transaction, this only happens in really bad situations | ||
| 3257 | * anyway. | ||
| 3258 | */ | ||
| 3259 | btrfs_abort_transaction(trans, root, ret); | ||
| 3260 | goto out_put; | ||
| 3261 | } | ||
| 3246 | WARN_ON(ret); | 3262 | WARN_ON(ret); |
| 3247 | 3263 | ||
| 3248 | if (i_size_read(inode) > 0) { | 3264 | if (i_size_read(inode) > 0) { |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index b78bbbac900d..30982bbd31c3 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
| @@ -1811,22 +1811,10 @@ static ssize_t btrfs_file_write_iter(struct kiocb *iocb, | |||
| 1811 | mutex_unlock(&inode->i_mutex); | 1811 | mutex_unlock(&inode->i_mutex); |
| 1812 | 1812 | ||
| 1813 | /* | 1813 | /* |
| 1814 | * we want to make sure fsync finds this change | ||
| 1815 | * but we haven't joined a transaction running right now. | ||
| 1816 | * | ||
| 1817 | * Later on, someone is sure to update the inode and get the | ||
| 1818 | * real transid recorded. | ||
| 1819 | * | ||
| 1820 | * We set last_trans now to the fs_info generation + 1, | ||
| 1821 | * this will either be one more than the running transaction | ||
| 1822 | * or the generation used for the next transaction if there isn't | ||
| 1823 | * one running right now. | ||
| 1824 | * | ||
| 1825 | * We also have to set last_sub_trans to the current log transid, | 1814 | * We also have to set last_sub_trans to the current log transid, |
| 1826 | * otherwise subsequent syncs to a file that's been synced in this | 1815 | * otherwise subsequent syncs to a file that's been synced in this |
| 1827 | * transaction will appear to have already occured. | 1816 | * transaction will appear to have already occured. |
| 1828 | */ | 1817 | */ |
| 1829 | BTRFS_I(inode)->last_trans = root->fs_info->generation + 1; | ||
| 1830 | BTRFS_I(inode)->last_sub_trans = root->log_transid; | 1818 | BTRFS_I(inode)->last_sub_trans = root->log_transid; |
| 1831 | if (num_written > 0) { | 1819 | if (num_written > 0) { |
| 1832 | err = generic_write_sync(file, pos, num_written); | 1820 | err = generic_write_sync(file, pos, num_written); |
| @@ -1959,25 +1947,37 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) | |||
| 1959 | atomic_inc(&root->log_batch); | 1947 | atomic_inc(&root->log_batch); |
| 1960 | 1948 | ||
| 1961 | /* | 1949 | /* |
| 1962 | * check the transaction that last modified this inode | 1950 | * If the last transaction that changed this file was before the current |
| 1963 | * and see if its already been committed | 1951 | * transaction and we have the full sync flag set in our inode, we can |
| 1964 | */ | 1952 | * bail out now without any syncing. |
| 1965 | if (!BTRFS_I(inode)->last_trans) { | 1953 | * |
| 1966 | mutex_unlock(&inode->i_mutex); | 1954 | * Note that we can't bail out if the full sync flag isn't set. This is |
| 1967 | goto out; | 1955 | * because when the full sync flag is set we start all ordered extents |
| 1968 | } | 1956 | * and wait for them to fully complete - when they complete they update |
| 1969 | 1957 | * the inode's last_trans field through: | |
| 1970 | /* | 1958 | * |
| 1971 | * if the last transaction that changed this file was before | 1959 | * btrfs_finish_ordered_io() -> |
| 1972 | * the current transaction, we can bail out now without any | 1960 | * btrfs_update_inode_fallback() -> |
| 1973 | * syncing | 1961 | * btrfs_update_inode() -> |
| 1962 | * btrfs_set_inode_last_trans() | ||
| 1963 | * | ||
| 1964 | * So we are sure that last_trans is up to date and can do this check to | ||
| 1965 | * bail out safely. For the fast path, when the full sync flag is not | ||
| 1966 | * set in our inode, we can not do it because we start only our ordered | ||
| 1967 | * extents and don't wait for them to complete (that is when | ||
| 1968 | * btrfs_finish_ordered_io runs), so here at this point their last_trans | ||
| 1969 | * value might be less than or equals to fs_info->last_trans_committed, | ||
| 1970 | * and setting a speculative last_trans for an inode when a buffered | ||
| 1971 | * write is made (such as fs_info->generation + 1 for example) would not | ||
| 1972 | * be reliable since after setting the value and before fsync is called | ||
| 1973 | * any number of transactions can start and commit (transaction kthread | ||
| 1974 | * commits the current transaction periodically), and a transaction | ||
| 1975 | * commit does not start nor waits for ordered extents to complete. | ||
| 1974 | */ | 1976 | */ |
| 1975 | smp_mb(); | 1977 | smp_mb(); |
| 1976 | if (btrfs_inode_in_log(inode, root->fs_info->generation) || | 1978 | if (btrfs_inode_in_log(inode, root->fs_info->generation) || |
| 1977 | BTRFS_I(inode)->last_trans <= | 1979 | (full_sync && BTRFS_I(inode)->last_trans <= |
| 1978 | root->fs_info->last_trans_committed) { | 1980 | root->fs_info->last_trans_committed)) { |
| 1979 | BTRFS_I(inode)->last_trans = 0; | ||
| 1980 | |||
| 1981 | /* | 1981 | /* |
| 1982 | * We'v had everything committed since the last time we were | 1982 | * We'v had everything committed since the last time we were |
| 1983 | * modified so clear this flag in case it was set for whatever | 1983 | * modified so clear this flag in case it was set for whatever |
| @@ -2275,6 +2275,8 @@ static int btrfs_punch_hole(struct inode *inode, loff_t offset, loff_t len) | |||
| 2275 | bool same_page; | 2275 | bool same_page; |
| 2276 | bool no_holes = btrfs_fs_incompat(root->fs_info, NO_HOLES); | 2276 | bool no_holes = btrfs_fs_incompat(root->fs_info, NO_HOLES); |
| 2277 | u64 ino_size; | 2277 | u64 ino_size; |
| 2278 | bool truncated_page = false; | ||
| 2279 | bool updated_inode = false; | ||
| 2278 | 2280 | ||
| 2279 | ret = btrfs_wait_ordered_range(inode, offset, len); | 2281 | ret = btrfs_wait_ordered_range(inode, offset, len); |
| 2280 | if (ret) | 2282 | if (ret) |
| @@ -2306,13 +2308,18 @@ static int btrfs_punch_hole(struct inode *inode, loff_t offset, loff_t len) | |||
| 2306 | * entire page. | 2308 | * entire page. |
| 2307 | */ | 2309 | */ |
| 2308 | if (same_page && len < PAGE_CACHE_SIZE) { | 2310 | if (same_page && len < PAGE_CACHE_SIZE) { |
| 2309 | if (offset < ino_size) | 2311 | if (offset < ino_size) { |
| 2312 | truncated_page = true; | ||
| 2310 | ret = btrfs_truncate_page(inode, offset, len, 0); | 2313 | ret = btrfs_truncate_page(inode, offset, len, 0); |
| 2314 | } else { | ||
| 2315 | ret = 0; | ||
| 2316 | } | ||
| 2311 | goto out_only_mutex; | 2317 | goto out_only_mutex; |
| 2312 | } | 2318 | } |
| 2313 | 2319 | ||
| 2314 | /* zero back part of the first page */ | 2320 | /* zero back part of the first page */ |
| 2315 | if (offset < ino_size) { | 2321 | if (offset < ino_size) { |
| 2322 | truncated_page = true; | ||
| 2316 | ret = btrfs_truncate_page(inode, offset, 0, 0); | 2323 | ret = btrfs_truncate_page(inode, offset, 0, 0); |
| 2317 | if (ret) { | 2324 | if (ret) { |
| 2318 | mutex_unlock(&inode->i_mutex); | 2325 | mutex_unlock(&inode->i_mutex); |
| @@ -2348,6 +2355,7 @@ static int btrfs_punch_hole(struct inode *inode, loff_t offset, loff_t len) | |||
| 2348 | if (!ret) { | 2355 | if (!ret) { |
| 2349 | /* zero the front end of the last page */ | 2356 | /* zero the front end of the last page */ |
| 2350 | if (tail_start + tail_len < ino_size) { | 2357 | if (tail_start + tail_len < ino_size) { |
| 2358 | truncated_page = true; | ||
| 2351 | ret = btrfs_truncate_page(inode, | 2359 | ret = btrfs_truncate_page(inode, |
| 2352 | tail_start + tail_len, 0, 1); | 2360 | tail_start + tail_len, 0, 1); |
| 2353 | if (ret) | 2361 | if (ret) |
| @@ -2357,8 +2365,8 @@ static int btrfs_punch_hole(struct inode *inode, loff_t offset, loff_t len) | |||
| 2357 | } | 2365 | } |
| 2358 | 2366 | ||
| 2359 | if (lockend < lockstart) { | 2367 | if (lockend < lockstart) { |
| 2360 | mutex_unlock(&inode->i_mutex); | 2368 | ret = 0; |
| 2361 | return 0; | 2369 | goto out_only_mutex; |
| 2362 | } | 2370 | } |
| 2363 | 2371 | ||
| 2364 | while (1) { | 2372 | while (1) { |
| @@ -2506,6 +2514,7 @@ out_trans: | |||
| 2506 | 2514 | ||
| 2507 | trans->block_rsv = &root->fs_info->trans_block_rsv; | 2515 | trans->block_rsv = &root->fs_info->trans_block_rsv; |
| 2508 | ret = btrfs_update_inode(trans, root, inode); | 2516 | ret = btrfs_update_inode(trans, root, inode); |
| 2517 | updated_inode = true; | ||
| 2509 | btrfs_end_transaction(trans, root); | 2518 | btrfs_end_transaction(trans, root); |
| 2510 | btrfs_btree_balance_dirty(root); | 2519 | btrfs_btree_balance_dirty(root); |
| 2511 | out_free: | 2520 | out_free: |
| @@ -2515,6 +2524,22 @@ out: | |||
| 2515 | unlock_extent_cached(&BTRFS_I(inode)->io_tree, lockstart, lockend, | 2524 | unlock_extent_cached(&BTRFS_I(inode)->io_tree, lockstart, lockend, |
| 2516 | &cached_state, GFP_NOFS); | 2525 | &cached_state, GFP_NOFS); |
| 2517 | out_only_mutex: | 2526 | out_only_mutex: |
| 2527 | if (!updated_inode && truncated_page && !ret && !err) { | ||
| 2528 | /* | ||
| 2529 | * If we only end up zeroing part of a page, we still need to | ||
| 2530 | * update the inode item, so that all the time fields are | ||
| 2531 | * updated as well as the necessary btrfs inode in memory fields | ||
| 2532 | * for detecting, at fsync time, if the inode isn't yet in the | ||
| 2533 | * log tree or it's there but not up to date. | ||
| 2534 | */ | ||
| 2535 | trans = btrfs_start_transaction(root, 1); | ||
| 2536 | if (IS_ERR(trans)) { | ||
| 2537 | err = PTR_ERR(trans); | ||
| 2538 | } else { | ||
| 2539 | err = btrfs_update_inode(trans, root, inode); | ||
| 2540 | ret = btrfs_end_transaction(trans, root); | ||
| 2541 | } | ||
| 2542 | } | ||
| 2518 | mutex_unlock(&inode->i_mutex); | 2543 | mutex_unlock(&inode->i_mutex); |
| 2519 | if (ret && !err) | 2544 | if (ret && !err) |
| 2520 | err = ret; | 2545 | err = ret; |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index a85c23dfcddb..da828cf5e8f8 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
| @@ -7285,7 +7285,6 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock, | |||
| 7285 | ((BTRFS_I(inode)->flags & BTRFS_INODE_NODATACOW) && | 7285 | ((BTRFS_I(inode)->flags & BTRFS_INODE_NODATACOW) && |
| 7286 | em->block_start != EXTENT_MAP_HOLE)) { | 7286 | em->block_start != EXTENT_MAP_HOLE)) { |
| 7287 | int type; | 7287 | int type; |
| 7288 | int ret; | ||
| 7289 | u64 block_start, orig_start, orig_block_len, ram_bytes; | 7288 | u64 block_start, orig_start, orig_block_len, ram_bytes; |
| 7290 | 7289 | ||
| 7291 | if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags)) | 7290 | if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags)) |
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index 534544e08f76..157cc54fc634 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c | |||
| @@ -452,9 +452,7 @@ void btrfs_get_logged_extents(struct inode *inode, | |||
| 452 | continue; | 452 | continue; |
| 453 | if (entry_end(ordered) <= start) | 453 | if (entry_end(ordered) <= start) |
| 454 | break; | 454 | break; |
| 455 | if (!list_empty(&ordered->log_list)) | 455 | if (test_and_set_bit(BTRFS_ORDERED_LOGGED, &ordered->flags)) |
| 456 | continue; | ||
| 457 | if (test_bit(BTRFS_ORDERED_LOGGED, &ordered->flags)) | ||
| 458 | continue; | 456 | continue; |
| 459 | list_add(&ordered->log_list, logged_list); | 457 | list_add(&ordered->log_list, logged_list); |
| 460 | atomic_inc(&ordered->refs); | 458 | atomic_inc(&ordered->refs); |
| @@ -511,8 +509,7 @@ void btrfs_wait_logged_extents(struct btrfs_trans_handle *trans, | |||
| 511 | wait_event(ordered->wait, test_bit(BTRFS_ORDERED_IO_DONE, | 509 | wait_event(ordered->wait, test_bit(BTRFS_ORDERED_IO_DONE, |
| 512 | &ordered->flags)); | 510 | &ordered->flags)); |
| 513 | 511 | ||
| 514 | if (!test_and_set_bit(BTRFS_ORDERED_LOGGED, &ordered->flags)) | 512 | list_add_tail(&ordered->trans_list, &trans->ordered); |
| 515 | list_add_tail(&ordered->trans_list, &trans->ordered); | ||
| 516 | spin_lock_irq(&log->log_extents_lock[index]); | 513 | spin_lock_irq(&log->log_extents_lock[index]); |
| 517 | } | 514 | } |
| 518 | spin_unlock_irq(&log->log_extents_lock[index]); | 515 | spin_unlock_irq(&log->log_extents_lock[index]); |
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index fe5857223515..d6033f540cc7 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c | |||
| @@ -230,6 +230,7 @@ struct pending_dir_move { | |||
| 230 | u64 parent_ino; | 230 | u64 parent_ino; |
| 231 | u64 ino; | 231 | u64 ino; |
| 232 | u64 gen; | 232 | u64 gen; |
| 233 | bool is_orphan; | ||
| 233 | struct list_head update_refs; | 234 | struct list_head update_refs; |
| 234 | }; | 235 | }; |
| 235 | 236 | ||
| @@ -2984,7 +2985,8 @@ static int add_pending_dir_move(struct send_ctx *sctx, | |||
| 2984 | u64 ino_gen, | 2985 | u64 ino_gen, |
| 2985 | u64 parent_ino, | 2986 | u64 parent_ino, |
| 2986 | struct list_head *new_refs, | 2987 | struct list_head *new_refs, |
| 2987 | struct list_head *deleted_refs) | 2988 | struct list_head *deleted_refs, |
| 2989 | const bool is_orphan) | ||
| 2988 | { | 2990 | { |
| 2989 | struct rb_node **p = &sctx->pending_dir_moves.rb_node; | 2991 | struct rb_node **p = &sctx->pending_dir_moves.rb_node; |
| 2990 | struct rb_node *parent = NULL; | 2992 | struct rb_node *parent = NULL; |
| @@ -2999,6 +3001,7 @@ static int add_pending_dir_move(struct send_ctx *sctx, | |||
| 2999 | pm->parent_ino = parent_ino; | 3001 | pm->parent_ino = parent_ino; |
| 3000 | pm->ino = ino; | 3002 | pm->ino = ino; |
| 3001 | pm->gen = ino_gen; | 3003 | pm->gen = ino_gen; |
| 3004 | pm->is_orphan = is_orphan; | ||
| 3002 | INIT_LIST_HEAD(&pm->list); | 3005 | INIT_LIST_HEAD(&pm->list); |
| 3003 | INIT_LIST_HEAD(&pm->update_refs); | 3006 | INIT_LIST_HEAD(&pm->update_refs); |
| 3004 | RB_CLEAR_NODE(&pm->node); | 3007 | RB_CLEAR_NODE(&pm->node); |
| @@ -3131,16 +3134,20 @@ static int apply_dir_move(struct send_ctx *sctx, struct pending_dir_move *pm) | |||
| 3131 | rmdir_ino = dm->rmdir_ino; | 3134 | rmdir_ino = dm->rmdir_ino; |
| 3132 | free_waiting_dir_move(sctx, dm); | 3135 | free_waiting_dir_move(sctx, dm); |
| 3133 | 3136 | ||
| 3134 | ret = get_first_ref(sctx->parent_root, pm->ino, | 3137 | if (pm->is_orphan) { |
| 3135 | &parent_ino, &parent_gen, name); | 3138 | ret = gen_unique_name(sctx, pm->ino, |
| 3136 | if (ret < 0) | 3139 | pm->gen, from_path); |
| 3137 | goto out; | 3140 | } else { |
| 3138 | 3141 | ret = get_first_ref(sctx->parent_root, pm->ino, | |
| 3139 | ret = get_cur_path(sctx, parent_ino, parent_gen, | 3142 | &parent_ino, &parent_gen, name); |
| 3140 | from_path); | 3143 | if (ret < 0) |
| 3141 | if (ret < 0) | 3144 | goto out; |
| 3142 | goto out; | 3145 | ret = get_cur_path(sctx, parent_ino, parent_gen, |
| 3143 | ret = fs_path_add_path(from_path, name); | 3146 | from_path); |
| 3147 | if (ret < 0) | ||
| 3148 | goto out; | ||
| 3149 | ret = fs_path_add_path(from_path, name); | ||
| 3150 | } | ||
| 3144 | if (ret < 0) | 3151 | if (ret < 0) |
| 3145 | goto out; | 3152 | goto out; |
| 3146 | 3153 | ||
| @@ -3150,7 +3157,8 @@ static int apply_dir_move(struct send_ctx *sctx, struct pending_dir_move *pm) | |||
| 3150 | LIST_HEAD(deleted_refs); | 3157 | LIST_HEAD(deleted_refs); |
| 3151 | ASSERT(ancestor > BTRFS_FIRST_FREE_OBJECTID); | 3158 | ASSERT(ancestor > BTRFS_FIRST_FREE_OBJECTID); |
| 3152 | ret = add_pending_dir_move(sctx, pm->ino, pm->gen, ancestor, | 3159 | ret = add_pending_dir_move(sctx, pm->ino, pm->gen, ancestor, |
| 3153 | &pm->update_refs, &deleted_refs); | 3160 | &pm->update_refs, &deleted_refs, |
| 3161 | pm->is_orphan); | ||
| 3154 | if (ret < 0) | 3162 | if (ret < 0) |
| 3155 | goto out; | 3163 | goto out; |
| 3156 | if (rmdir_ino) { | 3164 | if (rmdir_ino) { |
| @@ -3283,6 +3291,127 @@ out: | |||
| 3283 | return ret; | 3291 | return ret; |
| 3284 | } | 3292 | } |
| 3285 | 3293 | ||
| 3294 | /* | ||
| 3295 | * We might need to delay a directory rename even when no ancestor directory | ||
| 3296 | * (in the send root) with a higher inode number than ours (sctx->cur_ino) was | ||
| 3297 | * renamed. This happens when we rename a directory to the old name (the name | ||
| 3298 | * in the parent root) of some other unrelated directory that got its rename | ||
| 3299 | * delayed due to some ancestor with higher number that got renamed. | ||
| 3300 | * | ||
| 3301 | * Example: | ||
| 3302 | * | ||
| 3303 | * Parent snapshot: | ||
| 3304 | * . (ino 256) | ||
| 3305 | * |---- a/ (ino 257) | ||
| 3306 | * | |---- file (ino 260) | ||
| 3307 | * | | ||
| 3308 | * |---- b/ (ino 258) | ||
| 3309 | * |---- c/ (ino 259) | ||
| 3310 | * | ||
| 3311 | * Send snapshot: | ||
| 3312 | * . (ino 256) | ||
| 3313 | * |---- a/ (ino 258) | ||
| 3314 | * |---- x/ (ino 259) | ||
| 3315 | * |---- y/ (ino 257) | ||
| 3316 | * |----- file (ino 260) | ||
| 3317 | * | ||
| 3318 | * Here we can not rename 258 from 'b' to 'a' without the rename of inode 257 | ||
| 3319 | * from 'a' to 'x/y' happening first, which in turn depends on the rename of | ||
| 3320 | * inode 259 from 'c' to 'x'. So the order of rename commands the send stream | ||
| 3321 | * must issue is: | ||
| 3322 | * | ||
| 3323 | * 1 - rename 259 from 'c' to 'x' | ||
| 3324 | * 2 - rename 257 from 'a' to 'x/y' | ||
| 3325 | * 3 - rename 258 from 'b' to 'a' | ||
| 3326 | * | ||
| 3327 | * Returns 1 if the rename of sctx->cur_ino needs to be delayed, 0 if it can | ||
| 3328 | * be done right away and < 0 on error. | ||
| 3329 | */ | ||
| 3330 | static int wait_for_dest_dir_move(struct send_ctx *sctx, | ||
| 3331 | struct recorded_ref *parent_ref, | ||
| 3332 | const bool is_orphan) | ||
| 3333 | { | ||
| 3334 | struct btrfs_path *path; | ||
| 3335 | struct btrfs_key key; | ||
| 3336 | struct btrfs_key di_key; | ||
| 3337 | struct btrfs_dir_item *di; | ||
| 3338 | u64 left_gen; | ||
| 3339 | u64 right_gen; | ||
| 3340 | int ret = 0; | ||
| 3341 | |||
| 3342 | if (RB_EMPTY_ROOT(&sctx->waiting_dir_moves)) | ||
| 3343 | return 0; | ||
| 3344 | |||
| 3345 | path = alloc_path_for_send(); | ||
| 3346 | if (!path) | ||
| 3347 | return -ENOMEM; | ||
| 3348 | |||
| 3349 | key.objectid = parent_ref->dir; | ||
| 3350 | key.type = BTRFS_DIR_ITEM_KEY; | ||
| 3351 | key.offset = btrfs_name_hash(parent_ref->name, parent_ref->name_len); | ||
| 3352 | |||
| 3353 | ret = btrfs_search_slot(NULL, sctx->parent_root, &key, path, 0, 0); | ||
| 3354 | if (ret < 0) { | ||
| 3355 | goto out; | ||
| 3356 | } else if (ret > 0) { | ||
| 3357 | ret = 0; | ||
| 3358 | goto out; | ||
| 3359 | } | ||
| 3360 | |||
| 3361 | di = btrfs_match_dir_item_name(sctx->parent_root, path, | ||
| 3362 | parent_ref->name, parent_ref->name_len); | ||
| 3363 | if (!di) { | ||
| 3364 | ret = 0; | ||
| 3365 | goto out; | ||
| 3366 | } | ||
| 3367 | /* | ||
| 3368 | * di_key.objectid has the number of the inode that has a dentry in the | ||
| 3369 | * parent directory with the same name that sctx->cur_ino is being | ||
| 3370 | * renamed to. We need to check if that inode is in the send root as | ||
| 3371 | * well and if it is currently marked as an inode with a pending rename, | ||
| 3372 | * if it is, we need to delay the rename of sctx->cur_ino as well, so | ||
| 3373 | * that it happens after that other inode is renamed. | ||
| 3374 | */ | ||
| 3375 | btrfs_dir_item_key_to_cpu(path->nodes[0], di, &di_key); | ||
| 3376 | if (di_key.type != BTRFS_INODE_ITEM_KEY) { | ||
| 3377 | ret = 0; | ||
| 3378 | goto out; | ||
| 3379 | } | ||
| 3380 | |||
| 3381 | ret = get_inode_info(sctx->parent_root, di_key.objectid, NULL, | ||
| 3382 | &left_gen, NULL, NULL, NULL, NULL); | ||
| 3383 | if (ret < 0) | ||
| 3384 | goto out; | ||
| 3385 | ret = get_inode_info(sctx->send_root, di_key.objectid, NULL, | ||
| 3386 | &right_gen, NULL, NULL, NULL, NULL); | ||
| 3387 | if (ret < 0) { | ||
| 3388 | if (ret == -ENOENT) | ||
| 3389 | ret = 0; | ||
| 3390 | goto out; | ||
| 3391 | } | ||
| 3392 | |||
| 3393 | /* Different inode, no need to delay the rename of sctx->cur_ino */ | ||
| 3394 | if (right_gen != left_gen) { | ||
| 3395 | ret = 0; | ||
| 3396 | goto out; | ||
| 3397 | } | ||
| 3398 | |||
| 3399 | if (is_waiting_for_move(sctx, di_key.objectid)) { | ||
| 3400 | ret = add_pending_dir_move(sctx, | ||
| 3401 | sctx->cur_ino, | ||
| 3402 | sctx->cur_inode_gen, | ||
| 3403 | di_key.objectid, | ||
| 3404 | &sctx->new_refs, | ||
| 3405 | &sctx->deleted_refs, | ||
| 3406 | is_orphan); | ||
| 3407 | if (!ret) | ||
| 3408 | ret = 1; | ||
| 3409 | } | ||
| 3410 | out: | ||
| 3411 | btrfs_free_path(path); | ||
| 3412 | return ret; | ||
| 3413 | } | ||
| 3414 | |||
| 3286 | static int wait_for_parent_move(struct send_ctx *sctx, | 3415 | static int wait_for_parent_move(struct send_ctx *sctx, |
| 3287 | struct recorded_ref *parent_ref) | 3416 | struct recorded_ref *parent_ref) |
| 3288 | { | 3417 | { |
| @@ -3349,7 +3478,8 @@ out: | |||
| 3349 | sctx->cur_inode_gen, | 3478 | sctx->cur_inode_gen, |
| 3350 | ino, | 3479 | ino, |
| 3351 | &sctx->new_refs, | 3480 | &sctx->new_refs, |
| 3352 | &sctx->deleted_refs); | 3481 | &sctx->deleted_refs, |
| 3482 | false); | ||
| 3353 | if (!ret) | 3483 | if (!ret) |
| 3354 | ret = 1; | 3484 | ret = 1; |
| 3355 | } | 3485 | } |
| @@ -3372,6 +3502,7 @@ static int process_recorded_refs(struct send_ctx *sctx, int *pending_move) | |||
| 3372 | int did_overwrite = 0; | 3502 | int did_overwrite = 0; |
| 3373 | int is_orphan = 0; | 3503 | int is_orphan = 0; |
| 3374 | u64 last_dir_ino_rm = 0; | 3504 | u64 last_dir_ino_rm = 0; |
| 3505 | bool can_rename = true; | ||
| 3375 | 3506 | ||
| 3376 | verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino); | 3507 | verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino); |
| 3377 | 3508 | ||
| @@ -3490,12 +3621,22 @@ verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino); | |||
| 3490 | } | 3621 | } |
| 3491 | } | 3622 | } |
| 3492 | 3623 | ||
| 3624 | if (S_ISDIR(sctx->cur_inode_mode) && sctx->parent_root) { | ||
| 3625 | ret = wait_for_dest_dir_move(sctx, cur, is_orphan); | ||
| 3626 | if (ret < 0) | ||
| 3627 | goto out; | ||
| 3628 | if (ret == 1) { | ||
| 3629 | can_rename = false; | ||
| 3630 | *pending_move = 1; | ||
| 3631 | } | ||
| 3632 | } | ||
| 3633 | |||
| 3493 | /* | 3634 | /* |
| 3494 | * link/move the ref to the new place. If we have an orphan | 3635 | * link/move the ref to the new place. If we have an orphan |
| 3495 | * inode, move it and update valid_path. If not, link or move | 3636 | * inode, move it and update valid_path. If not, link or move |
| 3496 | * it depending on the inode mode. | 3637 | * it depending on the inode mode. |
| 3497 | */ | 3638 | */ |
| 3498 | if (is_orphan) { | 3639 | if (is_orphan && can_rename) { |
| 3499 | ret = send_rename(sctx, valid_path, cur->full_path); | 3640 | ret = send_rename(sctx, valid_path, cur->full_path); |
| 3500 | if (ret < 0) | 3641 | if (ret < 0) |
| 3501 | goto out; | 3642 | goto out; |
| @@ -3503,7 +3644,7 @@ verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino); | |||
| 3503 | ret = fs_path_copy(valid_path, cur->full_path); | 3644 | ret = fs_path_copy(valid_path, cur->full_path); |
| 3504 | if (ret < 0) | 3645 | if (ret < 0) |
| 3505 | goto out; | 3646 | goto out; |
| 3506 | } else { | 3647 | } else if (can_rename) { |
| 3507 | if (S_ISDIR(sctx->cur_inode_mode)) { | 3648 | if (S_ISDIR(sctx->cur_inode_mode)) { |
| 3508 | /* | 3649 | /* |
| 3509 | * Dirs can't be linked, so move it. For moved | 3650 | * Dirs can't be linked, so move it. For moved |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 7e80f32550a6..88e51aded6bd 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
| @@ -1052,9 +1052,6 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans, | |||
| 1052 | ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1); | 1052 | ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1); |
| 1053 | if (ret) | 1053 | if (ret) |
| 1054 | return ret; | 1054 | return ret; |
| 1055 | ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1); | ||
| 1056 | if (ret) | ||
| 1057 | return ret; | ||
| 1058 | } | 1055 | } |
| 1059 | 1056 | ||
| 1060 | return 0; | 1057 | return 0; |
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 9a37f8b39bae..c5b8ba37f88e 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
| @@ -1012,7 +1012,7 @@ again: | |||
| 1012 | base = btrfs_item_ptr_offset(leaf, path->slots[0]); | 1012 | base = btrfs_item_ptr_offset(leaf, path->slots[0]); |
| 1013 | 1013 | ||
| 1014 | while (cur_offset < item_size) { | 1014 | while (cur_offset < item_size) { |
| 1015 | extref = (struct btrfs_inode_extref *)base + cur_offset; | 1015 | extref = (struct btrfs_inode_extref *)(base + cur_offset); |
| 1016 | 1016 | ||
| 1017 | victim_name_len = btrfs_inode_extref_name_len(leaf, extref); | 1017 | victim_name_len = btrfs_inode_extref_name_len(leaf, extref); |
| 1018 | 1018 | ||
diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c index 47b19465f0dc..883b93623bc5 100644 --- a/fs/btrfs/xattr.c +++ b/fs/btrfs/xattr.c | |||
| @@ -111,6 +111,8 @@ static int do_setxattr(struct btrfs_trans_handle *trans, | |||
| 111 | name, name_len, -1); | 111 | name, name_len, -1); |
| 112 | if (!di && (flags & XATTR_REPLACE)) | 112 | if (!di && (flags & XATTR_REPLACE)) |
| 113 | ret = -ENODATA; | 113 | ret = -ENODATA; |
| 114 | else if (IS_ERR(di)) | ||
| 115 | ret = PTR_ERR(di); | ||
| 114 | else if (di) | 116 | else if (di) |
| 115 | ret = btrfs_delete_one_dir_name(trans, root, path, di); | 117 | ret = btrfs_delete_one_dir_name(trans, root, path, di); |
| 116 | goto out; | 118 | goto out; |
| @@ -127,10 +129,12 @@ static int do_setxattr(struct btrfs_trans_handle *trans, | |||
| 127 | ASSERT(mutex_is_locked(&inode->i_mutex)); | 129 | ASSERT(mutex_is_locked(&inode->i_mutex)); |
| 128 | di = btrfs_lookup_xattr(NULL, root, path, btrfs_ino(inode), | 130 | di = btrfs_lookup_xattr(NULL, root, path, btrfs_ino(inode), |
| 129 | name, name_len, 0); | 131 | name, name_len, 0); |
| 130 | if (!di) { | 132 | if (!di) |
| 131 | ret = -ENODATA; | 133 | ret = -ENODATA; |
| 134 | else if (IS_ERR(di)) | ||
| 135 | ret = PTR_ERR(di); | ||
| 136 | if (ret) | ||
| 132 | goto out; | 137 | goto out; |
| 133 | } | ||
| 134 | btrfs_release_path(path); | 138 | btrfs_release_path(path); |
| 135 | di = NULL; | 139 | di = NULL; |
| 136 | } | 140 | } |
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index 90d1882b306f..5ba029e627cc 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h | |||
| @@ -124,7 +124,7 @@ ecryptfs_get_key_payload_data(struct key *key) | |||
| 124 | } | 124 | } |
| 125 | 125 | ||
| 126 | #define ECRYPTFS_MAX_KEYSET_SIZE 1024 | 126 | #define ECRYPTFS_MAX_KEYSET_SIZE 1024 |
| 127 | #define ECRYPTFS_MAX_CIPHER_NAME_SIZE 32 | 127 | #define ECRYPTFS_MAX_CIPHER_NAME_SIZE 31 |
| 128 | #define ECRYPTFS_MAX_NUM_ENC_KEYS 64 | 128 | #define ECRYPTFS_MAX_NUM_ENC_KEYS 64 |
| 129 | #define ECRYPTFS_MAX_IV_BYTES 16 /* 128 bits */ | 129 | #define ECRYPTFS_MAX_IV_BYTES 16 /* 128 bits */ |
| 130 | #define ECRYPTFS_SALT_BYTES 2 | 130 | #define ECRYPTFS_SALT_BYTES 2 |
| @@ -237,7 +237,7 @@ struct ecryptfs_crypt_stat { | |||
| 237 | struct crypto_ablkcipher *tfm; | 237 | struct crypto_ablkcipher *tfm; |
| 238 | struct crypto_hash *hash_tfm; /* Crypto context for generating | 238 | struct crypto_hash *hash_tfm; /* Crypto context for generating |
| 239 | * the initialization vectors */ | 239 | * the initialization vectors */ |
| 240 | unsigned char cipher[ECRYPTFS_MAX_CIPHER_NAME_SIZE]; | 240 | unsigned char cipher[ECRYPTFS_MAX_CIPHER_NAME_SIZE + 1]; |
| 241 | unsigned char key[ECRYPTFS_MAX_KEY_BYTES]; | 241 | unsigned char key[ECRYPTFS_MAX_KEY_BYTES]; |
| 242 | unsigned char root_iv[ECRYPTFS_MAX_IV_BYTES]; | 242 | unsigned char root_iv[ECRYPTFS_MAX_IV_BYTES]; |
| 243 | struct list_head keysig_list; | 243 | struct list_head keysig_list; |
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c index b07731e68c0b..fd39bad6f1bd 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c | |||
| @@ -303,9 +303,22 @@ ecryptfs_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
| 303 | struct file *lower_file = ecryptfs_file_to_lower(file); | 303 | struct file *lower_file = ecryptfs_file_to_lower(file); |
| 304 | long rc = -ENOTTY; | 304 | long rc = -ENOTTY; |
| 305 | 305 | ||
| 306 | if (lower_file->f_op->unlocked_ioctl) | 306 | if (!lower_file->f_op->unlocked_ioctl) |
| 307 | return rc; | ||
| 308 | |||
| 309 | switch (cmd) { | ||
| 310 | case FITRIM: | ||
| 311 | case FS_IOC_GETFLAGS: | ||
| 312 | case FS_IOC_SETFLAGS: | ||
| 313 | case FS_IOC_GETVERSION: | ||
| 314 | case FS_IOC_SETVERSION: | ||
| 307 | rc = lower_file->f_op->unlocked_ioctl(lower_file, cmd, arg); | 315 | rc = lower_file->f_op->unlocked_ioctl(lower_file, cmd, arg); |
| 308 | return rc; | 316 | fsstack_copy_attr_all(file_inode(file), file_inode(lower_file)); |
| 317 | |||
| 318 | return rc; | ||
| 319 | default: | ||
| 320 | return rc; | ||
| 321 | } | ||
| 309 | } | 322 | } |
| 310 | 323 | ||
| 311 | #ifdef CONFIG_COMPAT | 324 | #ifdef CONFIG_COMPAT |
| @@ -315,9 +328,22 @@ ecryptfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
| 315 | struct file *lower_file = ecryptfs_file_to_lower(file); | 328 | struct file *lower_file = ecryptfs_file_to_lower(file); |
| 316 | long rc = -ENOIOCTLCMD; | 329 | long rc = -ENOIOCTLCMD; |
| 317 | 330 | ||
| 318 | if (lower_file->f_op->compat_ioctl) | 331 | if (!lower_file->f_op->compat_ioctl) |
| 332 | return rc; | ||
| 333 | |||
| 334 | switch (cmd) { | ||
| 335 | case FITRIM: | ||
| 336 | case FS_IOC32_GETFLAGS: | ||
| 337 | case FS_IOC32_SETFLAGS: | ||
| 338 | case FS_IOC32_GETVERSION: | ||
| 339 | case FS_IOC32_SETVERSION: | ||
| 319 | rc = lower_file->f_op->compat_ioctl(lower_file, cmd, arg); | 340 | rc = lower_file->f_op->compat_ioctl(lower_file, cmd, arg); |
| 320 | return rc; | 341 | fsstack_copy_attr_all(file_inode(file), file_inode(lower_file)); |
| 342 | |||
| 343 | return rc; | ||
| 344 | default: | ||
| 345 | return rc; | ||
| 346 | } | ||
| 321 | } | 347 | } |
| 322 | #endif | 348 | #endif |
| 323 | 349 | ||
diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index 917bd5c9776a..6bd67e2011f0 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c | |||
| @@ -891,7 +891,7 @@ struct ecryptfs_parse_tag_70_packet_silly_stack { | |||
| 891 | struct blkcipher_desc desc; | 891 | struct blkcipher_desc desc; |
| 892 | char fnek_sig_hex[ECRYPTFS_SIG_SIZE_HEX + 1]; | 892 | char fnek_sig_hex[ECRYPTFS_SIG_SIZE_HEX + 1]; |
| 893 | char iv[ECRYPTFS_MAX_IV_BYTES]; | 893 | char iv[ECRYPTFS_MAX_IV_BYTES]; |
| 894 | char cipher_string[ECRYPTFS_MAX_CIPHER_NAME_SIZE]; | 894 | char cipher_string[ECRYPTFS_MAX_CIPHER_NAME_SIZE + 1]; |
| 895 | }; | 895 | }; |
| 896 | 896 | ||
| 897 | /** | 897 | /** |
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index 1895d60f4122..c095d3264259 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c | |||
| @@ -407,7 +407,7 @@ static int ecryptfs_parse_options(struct ecryptfs_sb_info *sbi, char *options, | |||
| 407 | if (!cipher_name_set) { | 407 | if (!cipher_name_set) { |
| 408 | int cipher_name_len = strlen(ECRYPTFS_DEFAULT_CIPHER); | 408 | int cipher_name_len = strlen(ECRYPTFS_DEFAULT_CIPHER); |
| 409 | 409 | ||
| 410 | BUG_ON(cipher_name_len >= ECRYPTFS_MAX_CIPHER_NAME_SIZE); | 410 | BUG_ON(cipher_name_len > ECRYPTFS_MAX_CIPHER_NAME_SIZE); |
| 411 | strcpy(mount_crypt_stat->global_default_cipher_name, | 411 | strcpy(mount_crypt_stat->global_default_cipher_name, |
| 412 | ECRYPTFS_DEFAULT_CIPHER); | 412 | ECRYPTFS_DEFAULT_CIPHER); |
| 413 | } | 413 | } |
diff --git a/fs/locks.c b/fs/locks.c index 365c82e1b3a9..f1bad681fc1c 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
| @@ -1665,7 +1665,8 @@ generic_add_lease(struct file *filp, long arg, struct file_lock **flp, void **pr | |||
| 1665 | } | 1665 | } |
| 1666 | 1666 | ||
| 1667 | if (my_fl != NULL) { | 1667 | if (my_fl != NULL) { |
| 1668 | error = lease->fl_lmops->lm_change(my_fl, arg, &dispose); | 1668 | lease = my_fl; |
| 1669 | error = lease->fl_lmops->lm_change(lease, arg, &dispose); | ||
| 1669 | if (error) | 1670 | if (error) |
| 1670 | goto out; | 1671 | goto out; |
| 1671 | goto out_setup; | 1672 | goto out_setup; |
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index f9f4845db989..19874151e95c 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
| @@ -433,7 +433,7 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat | |||
| 433 | 433 | ||
| 434 | static bool nfs_client_init_is_complete(const struct nfs_client *clp) | 434 | static bool nfs_client_init_is_complete(const struct nfs_client *clp) |
| 435 | { | 435 | { |
| 436 | return clp->cl_cons_state != NFS_CS_INITING; | 436 | return clp->cl_cons_state <= NFS_CS_READY; |
| 437 | } | 437 | } |
| 438 | 438 | ||
| 439 | int nfs_wait_client_init_complete(const struct nfs_client *clp) | 439 | int nfs_wait_client_init_complete(const struct nfs_client *clp) |
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index a1f0685b42ff..a6ad68865880 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c | |||
| @@ -181,8 +181,8 @@ void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, | |||
| 181 | clear_bit(NFS_DELEGATION_NEED_RECLAIM, | 181 | clear_bit(NFS_DELEGATION_NEED_RECLAIM, |
| 182 | &delegation->flags); | 182 | &delegation->flags); |
| 183 | spin_unlock(&delegation->lock); | 183 | spin_unlock(&delegation->lock); |
| 184 | put_rpccred(oldcred); | ||
| 185 | rcu_read_unlock(); | 184 | rcu_read_unlock(); |
| 185 | put_rpccred(oldcred); | ||
| 186 | trace_nfs4_reclaim_delegation(inode, res->delegation_type); | 186 | trace_nfs4_reclaim_delegation(inode, res->delegation_type); |
| 187 | } else { | 187 | } else { |
| 188 | /* We appear to have raced with a delegation return. */ | 188 | /* We appear to have raced with a delegation return. */ |
| @@ -370,7 +370,10 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct | |||
| 370 | delegation = NULL; | 370 | delegation = NULL; |
| 371 | goto out; | 371 | goto out; |
| 372 | } | 372 | } |
| 373 | freeme = nfs_detach_delegation_locked(nfsi, | 373 | if (test_and_set_bit(NFS_DELEGATION_RETURNING, |
| 374 | &old_delegation->flags)) | ||
| 375 | goto out; | ||
| 376 | freeme = nfs_detach_delegation_locked(nfsi, | ||
| 374 | old_delegation, clp); | 377 | old_delegation, clp); |
| 375 | if (freeme == NULL) | 378 | if (freeme == NULL) |
| 376 | goto out; | 379 | goto out; |
| @@ -433,6 +436,8 @@ static bool nfs_delegation_need_return(struct nfs_delegation *delegation) | |||
| 433 | { | 436 | { |
| 434 | bool ret = false; | 437 | bool ret = false; |
| 435 | 438 | ||
| 439 | if (test_bit(NFS_DELEGATION_RETURNING, &delegation->flags)) | ||
| 440 | goto out; | ||
| 436 | if (test_and_clear_bit(NFS_DELEGATION_RETURN, &delegation->flags)) | 441 | if (test_and_clear_bit(NFS_DELEGATION_RETURN, &delegation->flags)) |
| 437 | ret = true; | 442 | ret = true; |
| 438 | if (test_and_clear_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags) && !ret) { | 443 | if (test_and_clear_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags) && !ret) { |
| @@ -444,6 +449,7 @@ static bool nfs_delegation_need_return(struct nfs_delegation *delegation) | |||
| 444 | ret = true; | 449 | ret = true; |
| 445 | spin_unlock(&delegation->lock); | 450 | spin_unlock(&delegation->lock); |
| 446 | } | 451 | } |
| 452 | out: | ||
| 447 | return ret; | 453 | return ret; |
| 448 | } | 454 | } |
| 449 | 455 | ||
| @@ -471,14 +477,20 @@ restart: | |||
| 471 | super_list) { | 477 | super_list) { |
| 472 | if (!nfs_delegation_need_return(delegation)) | 478 | if (!nfs_delegation_need_return(delegation)) |
| 473 | continue; | 479 | continue; |
| 474 | inode = nfs_delegation_grab_inode(delegation); | 480 | if (!nfs_sb_active(server->super)) |
| 475 | if (inode == NULL) | ||
| 476 | continue; | 481 | continue; |
| 482 | inode = nfs_delegation_grab_inode(delegation); | ||
| 483 | if (inode == NULL) { | ||
| 484 | rcu_read_unlock(); | ||
| 485 | nfs_sb_deactive(server->super); | ||
| 486 | goto restart; | ||
| 487 | } | ||
| 477 | delegation = nfs_start_delegation_return_locked(NFS_I(inode)); | 488 | delegation = nfs_start_delegation_return_locked(NFS_I(inode)); |
| 478 | rcu_read_unlock(); | 489 | rcu_read_unlock(); |
| 479 | 490 | ||
| 480 | err = nfs_end_delegation_return(inode, delegation, 0); | 491 | err = nfs_end_delegation_return(inode, delegation, 0); |
| 481 | iput(inode); | 492 | iput(inode); |
| 493 | nfs_sb_deactive(server->super); | ||
| 482 | if (!err) | 494 | if (!err) |
| 483 | goto restart; | 495 | goto restart; |
| 484 | set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state); | 496 | set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state); |
| @@ -809,19 +821,30 @@ restart: | |||
| 809 | list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) { | 821 | list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) { |
| 810 | list_for_each_entry_rcu(delegation, &server->delegations, | 822 | list_for_each_entry_rcu(delegation, &server->delegations, |
| 811 | super_list) { | 823 | super_list) { |
| 824 | if (test_bit(NFS_DELEGATION_RETURNING, | ||
| 825 | &delegation->flags)) | ||
| 826 | continue; | ||
| 812 | if (test_bit(NFS_DELEGATION_NEED_RECLAIM, | 827 | if (test_bit(NFS_DELEGATION_NEED_RECLAIM, |
| 813 | &delegation->flags) == 0) | 828 | &delegation->flags) == 0) |
| 814 | continue; | 829 | continue; |
| 815 | inode = nfs_delegation_grab_inode(delegation); | 830 | if (!nfs_sb_active(server->super)) |
| 816 | if (inode == NULL) | ||
| 817 | continue; | 831 | continue; |
| 818 | delegation = nfs_detach_delegation(NFS_I(inode), | 832 | inode = nfs_delegation_grab_inode(delegation); |
| 819 | delegation, server); | 833 | if (inode == NULL) { |
| 834 | rcu_read_unlock(); | ||
| 835 | nfs_sb_deactive(server->super); | ||
| 836 | goto restart; | ||
| 837 | } | ||
| 838 | delegation = nfs_start_delegation_return_locked(NFS_I(inode)); | ||
| 820 | rcu_read_unlock(); | 839 | rcu_read_unlock(); |
| 821 | 840 | if (delegation != NULL) { | |
| 822 | if (delegation != NULL) | 841 | delegation = nfs_detach_delegation(NFS_I(inode), |
| 823 | nfs_free_delegation(delegation); | 842 | delegation, server); |
| 843 | if (delegation != NULL) | ||
| 844 | nfs_free_delegation(delegation); | ||
| 845 | } | ||
| 824 | iput(inode); | 846 | iput(inode); |
| 847 | nfs_sb_deactive(server->super); | ||
| 825 | goto restart; | 848 | goto restart; |
| 826 | } | 849 | } |
| 827 | } | 850 | } |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 9b0c55cb2a2e..c19e16f0b2d0 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
| @@ -408,14 +408,22 @@ static int xdr_decode(nfs_readdir_descriptor_t *desc, | |||
| 408 | return 0; | 408 | return 0; |
| 409 | } | 409 | } |
| 410 | 410 | ||
| 411 | /* Match file and dirent using either filehandle or fileid | ||
| 412 | * Note: caller is responsible for checking the fsid | ||
| 413 | */ | ||
| 411 | static | 414 | static |
| 412 | int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry) | 415 | int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry) |
| 413 | { | 416 | { |
| 417 | struct nfs_inode *nfsi; | ||
| 418 | |||
| 414 | if (dentry->d_inode == NULL) | 419 | if (dentry->d_inode == NULL) |
| 415 | goto different; | 420 | goto different; |
| 416 | if (nfs_compare_fh(entry->fh, NFS_FH(dentry->d_inode)) != 0) | 421 | |
| 417 | goto different; | 422 | nfsi = NFS_I(dentry->d_inode); |
| 418 | return 1; | 423 | if (entry->fattr->fileid == nfsi->fileid) |
| 424 | return 1; | ||
| 425 | if (nfs_compare_fh(entry->fh, &nfsi->fh) == 0) | ||
| 426 | return 1; | ||
| 419 | different: | 427 | different: |
| 420 | return 0; | 428 | return 0; |
| 421 | } | 429 | } |
| @@ -469,6 +477,10 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) | |||
| 469 | struct inode *inode; | 477 | struct inode *inode; |
| 470 | int status; | 478 | int status; |
| 471 | 479 | ||
| 480 | if (!(entry->fattr->valid & NFS_ATTR_FATTR_FILEID)) | ||
| 481 | return; | ||
| 482 | if (!(entry->fattr->valid & NFS_ATTR_FATTR_FSID)) | ||
| 483 | return; | ||
| 472 | if (filename.name[0] == '.') { | 484 | if (filename.name[0] == '.') { |
| 473 | if (filename.len == 1) | 485 | if (filename.len == 1) |
| 474 | return; | 486 | return; |
| @@ -479,6 +491,10 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) | |||
| 479 | 491 | ||
| 480 | dentry = d_lookup(parent, &filename); | 492 | dentry = d_lookup(parent, &filename); |
| 481 | if (dentry != NULL) { | 493 | if (dentry != NULL) { |
| 494 | /* Is there a mountpoint here? If so, just exit */ | ||
| 495 | if (!nfs_fsid_equal(&NFS_SB(dentry->d_sb)->fsid, | ||
| 496 | &entry->fattr->fsid)) | ||
| 497 | goto out; | ||
| 482 | if (nfs_same_file(dentry, entry)) { | 498 | if (nfs_same_file(dentry, entry)) { |
| 483 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 499 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
| 484 | status = nfs_refresh_inode(dentry->d_inode, entry->fattr); | 500 | status = nfs_refresh_inode(dentry->d_inode, entry->fattr); |
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 94712fc781fa..e679d24c39d3 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
| @@ -178,7 +178,7 @@ nfs_file_read(struct kiocb *iocb, struct iov_iter *to) | |||
| 178 | iocb->ki_filp, | 178 | iocb->ki_filp, |
| 179 | iov_iter_count(to), (unsigned long) iocb->ki_pos); | 179 | iov_iter_count(to), (unsigned long) iocb->ki_pos); |
| 180 | 180 | ||
| 181 | result = nfs_revalidate_mapping(inode, iocb->ki_filp->f_mapping); | 181 | result = nfs_revalidate_mapping_protected(inode, iocb->ki_filp->f_mapping); |
| 182 | if (!result) { | 182 | if (!result) { |
| 183 | result = generic_file_read_iter(iocb, to); | 183 | result = generic_file_read_iter(iocb, to); |
| 184 | if (result > 0) | 184 | if (result > 0) |
| @@ -199,7 +199,7 @@ nfs_file_splice_read(struct file *filp, loff_t *ppos, | |||
| 199 | dprintk("NFS: splice_read(%pD2, %lu@%Lu)\n", | 199 | dprintk("NFS: splice_read(%pD2, %lu@%Lu)\n", |
| 200 | filp, (unsigned long) count, (unsigned long long) *ppos); | 200 | filp, (unsigned long) count, (unsigned long long) *ppos); |
| 201 | 201 | ||
| 202 | res = nfs_revalidate_mapping(inode, filp->f_mapping); | 202 | res = nfs_revalidate_mapping_protected(inode, filp->f_mapping); |
| 203 | if (!res) { | 203 | if (!res) { |
| 204 | res = generic_file_splice_read(filp, ppos, pipe, count, flags); | 204 | res = generic_file_splice_read(filp, ppos, pipe, count, flags); |
| 205 | if (res > 0) | 205 | if (res > 0) |
| @@ -372,6 +372,10 @@ start: | |||
| 372 | nfs_wait_bit_killable, TASK_KILLABLE); | 372 | nfs_wait_bit_killable, TASK_KILLABLE); |
| 373 | if (ret) | 373 | if (ret) |
| 374 | return ret; | 374 | return ret; |
| 375 | /* | ||
| 376 | * Wait for O_DIRECT to complete | ||
| 377 | */ | ||
| 378 | nfs_inode_dio_wait(mapping->host); | ||
| 375 | 379 | ||
| 376 | page = grab_cache_page_write_begin(mapping, index, flags); | 380 | page = grab_cache_page_write_begin(mapping, index, flags); |
| 377 | if (!page) | 381 | if (!page) |
| @@ -619,6 +623,9 @@ static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
| 619 | /* make sure the cache has finished storing the page */ | 623 | /* make sure the cache has finished storing the page */ |
| 620 | nfs_fscache_wait_on_page_write(NFS_I(inode), page); | 624 | nfs_fscache_wait_on_page_write(NFS_I(inode), page); |
| 621 | 625 | ||
| 626 | wait_on_bit_action(&NFS_I(inode)->flags, NFS_INO_INVALIDATING, | ||
| 627 | nfs_wait_bit_killable, TASK_KILLABLE); | ||
| 628 | |||
| 622 | lock_page(page); | 629 | lock_page(page); |
| 623 | mapping = page_file_mapping(page); | 630 | mapping = page_file_mapping(page); |
| 624 | if (mapping != inode->i_mapping) | 631 | if (mapping != inode->i_mapping) |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 83107be3dd01..d42dff6d5e98 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
| @@ -556,6 +556,7 @@ EXPORT_SYMBOL_GPL(nfs_setattr); | |||
| 556 | * This is a copy of the common vmtruncate, but with the locking | 556 | * This is a copy of the common vmtruncate, but with the locking |
| 557 | * corrected to take into account the fact that NFS requires | 557 | * corrected to take into account the fact that NFS requires |
| 558 | * inode->i_size to be updated under the inode->i_lock. | 558 | * inode->i_size to be updated under the inode->i_lock. |
| 559 | * Note: must be called with inode->i_lock held! | ||
| 559 | */ | 560 | */ |
| 560 | static int nfs_vmtruncate(struct inode * inode, loff_t offset) | 561 | static int nfs_vmtruncate(struct inode * inode, loff_t offset) |
| 561 | { | 562 | { |
| @@ -565,14 +566,14 @@ static int nfs_vmtruncate(struct inode * inode, loff_t offset) | |||
| 565 | if (err) | 566 | if (err) |
| 566 | goto out; | 567 | goto out; |
| 567 | 568 | ||
| 568 | spin_lock(&inode->i_lock); | ||
| 569 | i_size_write(inode, offset); | 569 | i_size_write(inode, offset); |
| 570 | /* Optimisation */ | 570 | /* Optimisation */ |
| 571 | if (offset == 0) | 571 | if (offset == 0) |
| 572 | NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_DATA; | 572 | NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_DATA; |
| 573 | spin_unlock(&inode->i_lock); | ||
| 574 | 573 | ||
| 574 | spin_unlock(&inode->i_lock); | ||
| 575 | truncate_pagecache(inode, offset); | 575 | truncate_pagecache(inode, offset); |
| 576 | spin_lock(&inode->i_lock); | ||
| 576 | out: | 577 | out: |
| 577 | return err; | 578 | return err; |
| 578 | } | 579 | } |
| @@ -585,10 +586,15 @@ out: | |||
| 585 | * Note: we do this in the *proc.c in order to ensure that | 586 | * Note: we do this in the *proc.c in order to ensure that |
| 586 | * it works for things like exclusive creates too. | 587 | * it works for things like exclusive creates too. |
| 587 | */ | 588 | */ |
| 588 | void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr) | 589 | void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr, |
| 590 | struct nfs_fattr *fattr) | ||
| 589 | { | 591 | { |
| 592 | /* Barrier: bump the attribute generation count. */ | ||
| 593 | nfs_fattr_set_barrier(fattr); | ||
| 594 | |||
| 595 | spin_lock(&inode->i_lock); | ||
| 596 | NFS_I(inode)->attr_gencount = fattr->gencount; | ||
| 590 | if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) { | 597 | if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) { |
| 591 | spin_lock(&inode->i_lock); | ||
| 592 | if ((attr->ia_valid & ATTR_MODE) != 0) { | 598 | if ((attr->ia_valid & ATTR_MODE) != 0) { |
| 593 | int mode = attr->ia_mode & S_IALLUGO; | 599 | int mode = attr->ia_mode & S_IALLUGO; |
| 594 | mode |= inode->i_mode & ~S_IALLUGO; | 600 | mode |= inode->i_mode & ~S_IALLUGO; |
| @@ -600,12 +606,13 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr) | |||
| 600 | inode->i_gid = attr->ia_gid; | 606 | inode->i_gid = attr->ia_gid; |
| 601 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_ACCESS | 607 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_ACCESS |
| 602 | | NFS_INO_INVALID_ACL); | 608 | | NFS_INO_INVALID_ACL); |
| 603 | spin_unlock(&inode->i_lock); | ||
| 604 | } | 609 | } |
| 605 | if ((attr->ia_valid & ATTR_SIZE) != 0) { | 610 | if ((attr->ia_valid & ATTR_SIZE) != 0) { |
| 606 | nfs_inc_stats(inode, NFSIOS_SETATTRTRUNC); | 611 | nfs_inc_stats(inode, NFSIOS_SETATTRTRUNC); |
| 607 | nfs_vmtruncate(inode, attr->ia_size); | 612 | nfs_vmtruncate(inode, attr->ia_size); |
| 608 | } | 613 | } |
| 614 | nfs_update_inode(inode, fattr); | ||
| 615 | spin_unlock(&inode->i_lock); | ||
| 609 | } | 616 | } |
| 610 | EXPORT_SYMBOL_GPL(nfs_setattr_update_inode); | 617 | EXPORT_SYMBOL_GPL(nfs_setattr_update_inode); |
| 611 | 618 | ||
| @@ -1028,6 +1035,7 @@ static int nfs_invalidate_mapping(struct inode *inode, struct address_space *map | |||
| 1028 | 1035 | ||
| 1029 | if (mapping->nrpages != 0) { | 1036 | if (mapping->nrpages != 0) { |
| 1030 | if (S_ISREG(inode->i_mode)) { | 1037 | if (S_ISREG(inode->i_mode)) { |
| 1038 | unmap_mapping_range(mapping, 0, 0, 0); | ||
| 1031 | ret = nfs_sync_mapping(mapping); | 1039 | ret = nfs_sync_mapping(mapping); |
| 1032 | if (ret < 0) | 1040 | if (ret < 0) |
| 1033 | return ret; | 1041 | return ret; |
| @@ -1060,11 +1068,14 @@ static bool nfs_mapping_need_revalidate_inode(struct inode *inode) | |||
| 1060 | } | 1068 | } |
| 1061 | 1069 | ||
| 1062 | /** | 1070 | /** |
| 1063 | * nfs_revalidate_mapping - Revalidate the pagecache | 1071 | * __nfs_revalidate_mapping - Revalidate the pagecache |
| 1064 | * @inode - pointer to host inode | 1072 | * @inode - pointer to host inode |
| 1065 | * @mapping - pointer to mapping | 1073 | * @mapping - pointer to mapping |
| 1074 | * @may_lock - take inode->i_mutex? | ||
| 1066 | */ | 1075 | */ |
| 1067 | int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping) | 1076 | static int __nfs_revalidate_mapping(struct inode *inode, |
| 1077 | struct address_space *mapping, | ||
| 1078 | bool may_lock) | ||
| 1068 | { | 1079 | { |
| 1069 | struct nfs_inode *nfsi = NFS_I(inode); | 1080 | struct nfs_inode *nfsi = NFS_I(inode); |
| 1070 | unsigned long *bitlock = &nfsi->flags; | 1081 | unsigned long *bitlock = &nfsi->flags; |
| @@ -1113,7 +1124,12 @@ int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping) | |||
| 1113 | nfsi->cache_validity &= ~NFS_INO_INVALID_DATA; | 1124 | nfsi->cache_validity &= ~NFS_INO_INVALID_DATA; |
| 1114 | spin_unlock(&inode->i_lock); | 1125 | spin_unlock(&inode->i_lock); |
| 1115 | trace_nfs_invalidate_mapping_enter(inode); | 1126 | trace_nfs_invalidate_mapping_enter(inode); |
| 1116 | ret = nfs_invalidate_mapping(inode, mapping); | 1127 | if (may_lock) { |
| 1128 | mutex_lock(&inode->i_mutex); | ||
| 1129 | ret = nfs_invalidate_mapping(inode, mapping); | ||
| 1130 | mutex_unlock(&inode->i_mutex); | ||
| 1131 | } else | ||
| 1132 | ret = nfs_invalidate_mapping(inode, mapping); | ||
| 1117 | trace_nfs_invalidate_mapping_exit(inode, ret); | 1133 | trace_nfs_invalidate_mapping_exit(inode, ret); |
| 1118 | 1134 | ||
| 1119 | clear_bit_unlock(NFS_INO_INVALIDATING, bitlock); | 1135 | clear_bit_unlock(NFS_INO_INVALIDATING, bitlock); |
| @@ -1123,6 +1139,29 @@ out: | |||
| 1123 | return ret; | 1139 | return ret; |
| 1124 | } | 1140 | } |
| 1125 | 1141 | ||
| 1142 | /** | ||
| 1143 | * nfs_revalidate_mapping - Revalidate the pagecache | ||
| 1144 | * @inode - pointer to host inode | ||
| 1145 | * @mapping - pointer to mapping | ||
| 1146 | */ | ||
| 1147 | int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping) | ||
| 1148 | { | ||
| 1149 | return __nfs_revalidate_mapping(inode, mapping, false); | ||
| 1150 | } | ||
| 1151 | |||
| 1152 | /** | ||
| 1153 | * nfs_revalidate_mapping_protected - Revalidate the pagecache | ||
| 1154 | * @inode - pointer to host inode | ||
| 1155 | * @mapping - pointer to mapping | ||
| 1156 | * | ||
| 1157 | * Differs from nfs_revalidate_mapping() in that it grabs the inode->i_mutex | ||
| 1158 | * while invalidating the mapping. | ||
| 1159 | */ | ||
| 1160 | int nfs_revalidate_mapping_protected(struct inode *inode, struct address_space *mapping) | ||
| 1161 | { | ||
| 1162 | return __nfs_revalidate_mapping(inode, mapping, true); | ||
| 1163 | } | ||
| 1164 | |||
| 1126 | static unsigned long nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr) | 1165 | static unsigned long nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr) |
| 1127 | { | 1166 | { |
| 1128 | struct nfs_inode *nfsi = NFS_I(inode); | 1167 | struct nfs_inode *nfsi = NFS_I(inode); |
| @@ -1231,13 +1270,6 @@ static int nfs_ctime_need_update(const struct inode *inode, const struct nfs_fat | |||
| 1231 | return timespec_compare(&fattr->ctime, &inode->i_ctime) > 0; | 1270 | return timespec_compare(&fattr->ctime, &inode->i_ctime) > 0; |
| 1232 | } | 1271 | } |
| 1233 | 1272 | ||
| 1234 | static int nfs_size_need_update(const struct inode *inode, const struct nfs_fattr *fattr) | ||
| 1235 | { | ||
| 1236 | if (!(fattr->valid & NFS_ATTR_FATTR_SIZE)) | ||
| 1237 | return 0; | ||
| 1238 | return nfs_size_to_loff_t(fattr->size) > i_size_read(inode); | ||
| 1239 | } | ||
| 1240 | |||
| 1241 | static atomic_long_t nfs_attr_generation_counter; | 1273 | static atomic_long_t nfs_attr_generation_counter; |
| 1242 | 1274 | ||
| 1243 | static unsigned long nfs_read_attr_generation_counter(void) | 1275 | static unsigned long nfs_read_attr_generation_counter(void) |
| @@ -1249,6 +1281,7 @@ unsigned long nfs_inc_attr_generation_counter(void) | |||
| 1249 | { | 1281 | { |
| 1250 | return atomic_long_inc_return(&nfs_attr_generation_counter); | 1282 | return atomic_long_inc_return(&nfs_attr_generation_counter); |
| 1251 | } | 1283 | } |
| 1284 | EXPORT_SYMBOL_GPL(nfs_inc_attr_generation_counter); | ||
| 1252 | 1285 | ||
| 1253 | void nfs_fattr_init(struct nfs_fattr *fattr) | 1286 | void nfs_fattr_init(struct nfs_fattr *fattr) |
| 1254 | { | 1287 | { |
| @@ -1260,6 +1293,22 @@ void nfs_fattr_init(struct nfs_fattr *fattr) | |||
| 1260 | } | 1293 | } |
| 1261 | EXPORT_SYMBOL_GPL(nfs_fattr_init); | 1294 | EXPORT_SYMBOL_GPL(nfs_fattr_init); |
| 1262 | 1295 | ||
| 1296 | /** | ||
| 1297 | * nfs_fattr_set_barrier | ||
| 1298 | * @fattr: attributes | ||
| 1299 | * | ||
| 1300 | * Used to set a barrier after an attribute was updated. This | ||
| 1301 | * barrier ensures that older attributes from RPC calls that may | ||
| 1302 | * have raced with our update cannot clobber these new values. | ||
| 1303 | * Note that you are still responsible for ensuring that other | ||
| 1304 | * operations which change the attribute on the server do not | ||
| 1305 | * collide. | ||
| 1306 | */ | ||
| 1307 | void nfs_fattr_set_barrier(struct nfs_fattr *fattr) | ||
| 1308 | { | ||
| 1309 | fattr->gencount = nfs_inc_attr_generation_counter(); | ||
| 1310 | } | ||
| 1311 | |||
| 1263 | struct nfs_fattr *nfs_alloc_fattr(void) | 1312 | struct nfs_fattr *nfs_alloc_fattr(void) |
| 1264 | { | 1313 | { |
| 1265 | struct nfs_fattr *fattr; | 1314 | struct nfs_fattr *fattr; |
| @@ -1370,7 +1419,6 @@ static int nfs_inode_attrs_need_update(const struct inode *inode, const struct n | |||
| 1370 | 1419 | ||
| 1371 | return ((long)fattr->gencount - (long)nfsi->attr_gencount) > 0 || | 1420 | return ((long)fattr->gencount - (long)nfsi->attr_gencount) > 0 || |
| 1372 | nfs_ctime_need_update(inode, fattr) || | 1421 | nfs_ctime_need_update(inode, fattr) || |
| 1373 | nfs_size_need_update(inode, fattr) || | ||
| 1374 | ((long)nfsi->attr_gencount - (long)nfs_read_attr_generation_counter() > 0); | 1422 | ((long)nfsi->attr_gencount - (long)nfs_read_attr_generation_counter() > 0); |
| 1375 | } | 1423 | } |
| 1376 | 1424 | ||
| @@ -1460,6 +1508,7 @@ int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
| 1460 | int status; | 1508 | int status; |
| 1461 | 1509 | ||
| 1462 | spin_lock(&inode->i_lock); | 1510 | spin_lock(&inode->i_lock); |
| 1511 | nfs_fattr_set_barrier(fattr); | ||
| 1463 | status = nfs_post_op_update_inode_locked(inode, fattr); | 1512 | status = nfs_post_op_update_inode_locked(inode, fattr); |
| 1464 | spin_unlock(&inode->i_lock); | 1513 | spin_unlock(&inode->i_lock); |
| 1465 | 1514 | ||
| @@ -1468,7 +1517,7 @@ int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
| 1468 | EXPORT_SYMBOL_GPL(nfs_post_op_update_inode); | 1517 | EXPORT_SYMBOL_GPL(nfs_post_op_update_inode); |
| 1469 | 1518 | ||
| 1470 | /** | 1519 | /** |
| 1471 | * nfs_post_op_update_inode_force_wcc - try to update the inode attribute cache | 1520 | * nfs_post_op_update_inode_force_wcc_locked - update the inode attribute cache |
| 1472 | * @inode - pointer to inode | 1521 | * @inode - pointer to inode |
| 1473 | * @fattr - updated attributes | 1522 | * @fattr - updated attributes |
| 1474 | * | 1523 | * |
| @@ -1478,11 +1527,10 @@ EXPORT_SYMBOL_GPL(nfs_post_op_update_inode); | |||
| 1478 | * | 1527 | * |
| 1479 | * This function is mainly designed to be used by the ->write_done() functions. | 1528 | * This function is mainly designed to be used by the ->write_done() functions. |
| 1480 | */ | 1529 | */ |
| 1481 | int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr) | 1530 | int nfs_post_op_update_inode_force_wcc_locked(struct inode *inode, struct nfs_fattr *fattr) |
| 1482 | { | 1531 | { |
| 1483 | int status; | 1532 | int status; |
| 1484 | 1533 | ||
| 1485 | spin_lock(&inode->i_lock); | ||
| 1486 | /* Don't do a WCC update if these attributes are already stale */ | 1534 | /* Don't do a WCC update if these attributes are already stale */ |
| 1487 | if ((fattr->valid & NFS_ATTR_FATTR) == 0 || | 1535 | if ((fattr->valid & NFS_ATTR_FATTR) == 0 || |
| 1488 | !nfs_inode_attrs_need_update(inode, fattr)) { | 1536 | !nfs_inode_attrs_need_update(inode, fattr)) { |
| @@ -1514,6 +1562,27 @@ int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fa | |||
| 1514 | } | 1562 | } |
| 1515 | out_noforce: | 1563 | out_noforce: |
| 1516 | status = nfs_post_op_update_inode_locked(inode, fattr); | 1564 | status = nfs_post_op_update_inode_locked(inode, fattr); |
| 1565 | return status; | ||
| 1566 | } | ||
| 1567 | |||
| 1568 | /** | ||
| 1569 | * nfs_post_op_update_inode_force_wcc - try to update the inode attribute cache | ||
| 1570 | * @inode - pointer to inode | ||
| 1571 | * @fattr - updated attributes | ||
| 1572 | * | ||
| 1573 | * After an operation that has changed the inode metadata, mark the | ||
| 1574 | * attribute cache as being invalid, then try to update it. Fake up | ||
| 1575 | * weak cache consistency data, if none exist. | ||
| 1576 | * | ||
| 1577 | * This function is mainly designed to be used by the ->write_done() functions. | ||
| 1578 | */ | ||
| 1579 | int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr) | ||
| 1580 | { | ||
| 1581 | int status; | ||
| 1582 | |||
| 1583 | spin_lock(&inode->i_lock); | ||
| 1584 | nfs_fattr_set_barrier(fattr); | ||
| 1585 | status = nfs_post_op_update_inode_force_wcc_locked(inode, fattr); | ||
| 1517 | spin_unlock(&inode->i_lock); | 1586 | spin_unlock(&inode->i_lock); |
| 1518 | return status; | 1587 | return status; |
| 1519 | } | 1588 | } |
| @@ -1715,6 +1784,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
| 1715 | nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE); | 1784 | nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE); |
| 1716 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); | 1785 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); |
| 1717 | nfsi->attrtimeo_timestamp = now; | 1786 | nfsi->attrtimeo_timestamp = now; |
| 1787 | /* Set barrier to be more recent than all outstanding updates */ | ||
| 1718 | nfsi->attr_gencount = nfs_inc_attr_generation_counter(); | 1788 | nfsi->attr_gencount = nfs_inc_attr_generation_counter(); |
| 1719 | } else { | 1789 | } else { |
| 1720 | if (!time_in_range_open(now, nfsi->attrtimeo_timestamp, nfsi->attrtimeo_timestamp + nfsi->attrtimeo)) { | 1790 | if (!time_in_range_open(now, nfsi->attrtimeo_timestamp, nfsi->attrtimeo_timestamp + nfsi->attrtimeo)) { |
| @@ -1722,6 +1792,9 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
| 1722 | nfsi->attrtimeo = NFS_MAXATTRTIMEO(inode); | 1792 | nfsi->attrtimeo = NFS_MAXATTRTIMEO(inode); |
| 1723 | nfsi->attrtimeo_timestamp = now; | 1793 | nfsi->attrtimeo_timestamp = now; |
| 1724 | } | 1794 | } |
| 1795 | /* Set the barrier to be more recent than this fattr */ | ||
| 1796 | if ((long)fattr->gencount - (long)nfsi->attr_gencount > 0) | ||
| 1797 | nfsi->attr_gencount = fattr->gencount; | ||
| 1725 | } | 1798 | } |
| 1726 | invalid &= ~NFS_INO_INVALID_ATTR; | 1799 | invalid &= ~NFS_INO_INVALID_ATTR; |
| 1727 | /* Don't invalidate the data if we were to blame */ | 1800 | /* Don't invalidate the data if we were to blame */ |
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index b802fb3a2d99..9e6475bc5ba2 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
| @@ -459,6 +459,7 @@ void nfs_mark_request_commit(struct nfs_page *req, | |||
| 459 | struct nfs_commit_info *cinfo, | 459 | struct nfs_commit_info *cinfo, |
| 460 | u32 ds_commit_idx); | 460 | u32 ds_commit_idx); |
| 461 | int nfs_write_need_commit(struct nfs_pgio_header *); | 461 | int nfs_write_need_commit(struct nfs_pgio_header *); |
| 462 | void nfs_writeback_update_inode(struct nfs_pgio_header *hdr); | ||
| 462 | int nfs_generic_commit_list(struct inode *inode, struct list_head *head, | 463 | int nfs_generic_commit_list(struct inode *inode, struct list_head *head, |
| 463 | int how, struct nfs_commit_info *cinfo); | 464 | int how, struct nfs_commit_info *cinfo); |
| 464 | void nfs_retry_commit(struct list_head *page_list, | 465 | void nfs_retry_commit(struct list_head *page_list, |
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index 78e557c3ab87..1f11d2533ee4 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c | |||
| @@ -138,7 +138,7 @@ nfs3_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, | |||
| 138 | nfs_fattr_init(fattr); | 138 | nfs_fattr_init(fattr); |
| 139 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); | 139 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); |
| 140 | if (status == 0) | 140 | if (status == 0) |
| 141 | nfs_setattr_update_inode(inode, sattr); | 141 | nfs_setattr_update_inode(inode, sattr, fattr); |
| 142 | dprintk("NFS reply setattr: %d\n", status); | 142 | dprintk("NFS reply setattr: %d\n", status); |
| 143 | return status; | 143 | return status; |
| 144 | } | 144 | } |
| @@ -834,7 +834,7 @@ static int nfs3_write_done(struct rpc_task *task, struct nfs_pgio_header *hdr) | |||
| 834 | if (nfs3_async_handle_jukebox(task, inode)) | 834 | if (nfs3_async_handle_jukebox(task, inode)) |
| 835 | return -EAGAIN; | 835 | return -EAGAIN; |
| 836 | if (task->tk_status >= 0) | 836 | if (task->tk_status >= 0) |
| 837 | nfs_post_op_update_inode_force_wcc(inode, hdr->res.fattr); | 837 | nfs_writeback_update_inode(hdr); |
| 838 | return 0; | 838 | return 0; |
| 839 | } | 839 | } |
| 840 | 840 | ||
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c index 2a932fdc57cb..53852a4bd88b 100644 --- a/fs/nfs/nfs3xdr.c +++ b/fs/nfs/nfs3xdr.c | |||
| @@ -1987,6 +1987,11 @@ int nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, | |||
| 1987 | if (entry->fattr->valid & NFS_ATTR_FATTR_V3) | 1987 | if (entry->fattr->valid & NFS_ATTR_FATTR_V3) |
| 1988 | entry->d_type = nfs_umode_to_dtype(entry->fattr->mode); | 1988 | entry->d_type = nfs_umode_to_dtype(entry->fattr->mode); |
| 1989 | 1989 | ||
| 1990 | if (entry->fattr->fileid != entry->ino) { | ||
| 1991 | entry->fattr->mounted_on_fileid = entry->ino; | ||
| 1992 | entry->fattr->valid |= NFS_ATTR_FATTR_MOUNTED_ON_FILEID; | ||
| 1993 | } | ||
| 1994 | |||
| 1990 | /* In fact, a post_op_fh3: */ | 1995 | /* In fact, a post_op_fh3: */ |
| 1991 | p = xdr_inline_decode(xdr, 4); | 1996 | p = xdr_inline_decode(xdr, 4); |
| 1992 | if (unlikely(p == NULL)) | 1997 | if (unlikely(p == NULL)) |
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index 8646af9b11d2..86d6214ea022 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c | |||
| @@ -621,6 +621,9 @@ int nfs41_walk_client_list(struct nfs_client *new, | |||
| 621 | spin_lock(&nn->nfs_client_lock); | 621 | spin_lock(&nn->nfs_client_lock); |
| 622 | list_for_each_entry(pos, &nn->nfs_client_list, cl_share_link) { | 622 | list_for_each_entry(pos, &nn->nfs_client_list, cl_share_link) { |
| 623 | 623 | ||
| 624 | if (pos == new) | ||
| 625 | goto found; | ||
| 626 | |||
| 624 | if (pos->rpc_ops != new->rpc_ops) | 627 | if (pos->rpc_ops != new->rpc_ops) |
| 625 | continue; | 628 | continue; |
| 626 | 629 | ||
| @@ -639,10 +642,6 @@ int nfs41_walk_client_list(struct nfs_client *new, | |||
| 639 | prev = pos; | 642 | prev = pos; |
| 640 | 643 | ||
| 641 | status = nfs_wait_client_init_complete(pos); | 644 | status = nfs_wait_client_init_complete(pos); |
| 642 | if (pos->cl_cons_state == NFS_CS_SESSION_INITING) { | ||
| 643 | nfs4_schedule_lease_recovery(pos); | ||
| 644 | status = nfs4_wait_clnt_recover(pos); | ||
| 645 | } | ||
| 646 | spin_lock(&nn->nfs_client_lock); | 645 | spin_lock(&nn->nfs_client_lock); |
| 647 | if (status < 0) | 646 | if (status < 0) |
| 648 | break; | 647 | break; |
| @@ -668,7 +667,7 @@ int nfs41_walk_client_list(struct nfs_client *new, | |||
| 668 | */ | 667 | */ |
| 669 | if (!nfs4_match_client_owner_id(pos, new)) | 668 | if (!nfs4_match_client_owner_id(pos, new)) |
| 670 | continue; | 669 | continue; |
| 671 | 670 | found: | |
| 672 | atomic_inc(&pos->cl_count); | 671 | atomic_inc(&pos->cl_count); |
| 673 | *result = pos; | 672 | *result = pos; |
| 674 | status = 0; | 673 | status = 0; |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 88180ac5ea0e..627f37c44456 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
| @@ -901,6 +901,7 @@ static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo) | |||
| 901 | if (!cinfo->atomic || cinfo->before != dir->i_version) | 901 | if (!cinfo->atomic || cinfo->before != dir->i_version) |
| 902 | nfs_force_lookup_revalidate(dir); | 902 | nfs_force_lookup_revalidate(dir); |
| 903 | dir->i_version = cinfo->after; | 903 | dir->i_version = cinfo->after; |
| 904 | nfsi->attr_gencount = nfs_inc_attr_generation_counter(); | ||
| 904 | nfs_fscache_invalidate(dir); | 905 | nfs_fscache_invalidate(dir); |
| 905 | spin_unlock(&dir->i_lock); | 906 | spin_unlock(&dir->i_lock); |
| 906 | } | 907 | } |
| @@ -1552,6 +1553,9 @@ static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, fmode_t fmod | |||
| 1552 | 1553 | ||
| 1553 | opendata->o_arg.open_flags = 0; | 1554 | opendata->o_arg.open_flags = 0; |
| 1554 | opendata->o_arg.fmode = fmode; | 1555 | opendata->o_arg.fmode = fmode; |
| 1556 | opendata->o_arg.share_access = nfs4_map_atomic_open_share( | ||
| 1557 | NFS_SB(opendata->dentry->d_sb), | ||
| 1558 | fmode, 0); | ||
| 1555 | memset(&opendata->o_res, 0, sizeof(opendata->o_res)); | 1559 | memset(&opendata->o_res, 0, sizeof(opendata->o_res)); |
| 1556 | memset(&opendata->c_res, 0, sizeof(opendata->c_res)); | 1560 | memset(&opendata->c_res, 0, sizeof(opendata->c_res)); |
| 1557 | nfs4_init_opendata_res(opendata); | 1561 | nfs4_init_opendata_res(opendata); |
| @@ -2413,8 +2417,8 @@ static int _nfs4_do_open(struct inode *dir, | |||
| 2413 | opendata->o_res.f_attr, sattr, | 2417 | opendata->o_res.f_attr, sattr, |
| 2414 | state, label, olabel); | 2418 | state, label, olabel); |
| 2415 | if (status == 0) { | 2419 | if (status == 0) { |
| 2416 | nfs_setattr_update_inode(state->inode, sattr); | 2420 | nfs_setattr_update_inode(state->inode, sattr, |
| 2417 | nfs_post_op_update_inode(state->inode, opendata->o_res.f_attr); | 2421 | opendata->o_res.f_attr); |
| 2418 | nfs_setsecurity(state->inode, opendata->o_res.f_attr, olabel); | 2422 | nfs_setsecurity(state->inode, opendata->o_res.f_attr, olabel); |
| 2419 | } | 2423 | } |
| 2420 | } | 2424 | } |
| @@ -2651,7 +2655,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data) | |||
| 2651 | case -NFS4ERR_BAD_STATEID: | 2655 | case -NFS4ERR_BAD_STATEID: |
| 2652 | case -NFS4ERR_EXPIRED: | 2656 | case -NFS4ERR_EXPIRED: |
| 2653 | if (!nfs4_stateid_match(&calldata->arg.stateid, | 2657 | if (!nfs4_stateid_match(&calldata->arg.stateid, |
| 2654 | &state->stateid)) { | 2658 | &state->open_stateid)) { |
| 2655 | rpc_restart_call_prepare(task); | 2659 | rpc_restart_call_prepare(task); |
| 2656 | goto out_release; | 2660 | goto out_release; |
| 2657 | } | 2661 | } |
| @@ -2687,7 +2691,7 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) | |||
| 2687 | is_rdwr = test_bit(NFS_O_RDWR_STATE, &state->flags); | 2691 | is_rdwr = test_bit(NFS_O_RDWR_STATE, &state->flags); |
| 2688 | is_rdonly = test_bit(NFS_O_RDONLY_STATE, &state->flags); | 2692 | is_rdonly = test_bit(NFS_O_RDONLY_STATE, &state->flags); |
| 2689 | is_wronly = test_bit(NFS_O_WRONLY_STATE, &state->flags); | 2693 | is_wronly = test_bit(NFS_O_WRONLY_STATE, &state->flags); |
| 2690 | nfs4_stateid_copy(&calldata->arg.stateid, &state->stateid); | 2694 | nfs4_stateid_copy(&calldata->arg.stateid, &state->open_stateid); |
| 2691 | /* Calculate the change in open mode */ | 2695 | /* Calculate the change in open mode */ |
| 2692 | calldata->arg.fmode = 0; | 2696 | calldata->arg.fmode = 0; |
| 2693 | if (state->n_rdwr == 0) { | 2697 | if (state->n_rdwr == 0) { |
| @@ -3288,7 +3292,7 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, | |||
| 3288 | 3292 | ||
| 3289 | status = nfs4_do_setattr(inode, cred, fattr, sattr, state, NULL, label); | 3293 | status = nfs4_do_setattr(inode, cred, fattr, sattr, state, NULL, label); |
| 3290 | if (status == 0) { | 3294 | if (status == 0) { |
| 3291 | nfs_setattr_update_inode(inode, sattr); | 3295 | nfs_setattr_update_inode(inode, sattr, fattr); |
| 3292 | nfs_setsecurity(inode, fattr, label); | 3296 | nfs_setsecurity(inode, fattr, label); |
| 3293 | } | 3297 | } |
| 3294 | nfs4_label_free(label); | 3298 | nfs4_label_free(label); |
| @@ -4234,7 +4238,7 @@ static int nfs4_write_done_cb(struct rpc_task *task, | |||
| 4234 | } | 4238 | } |
| 4235 | if (task->tk_status >= 0) { | 4239 | if (task->tk_status >= 0) { |
| 4236 | renew_lease(NFS_SERVER(inode), hdr->timestamp); | 4240 | renew_lease(NFS_SERVER(inode), hdr->timestamp); |
| 4237 | nfs_post_op_update_inode_force_wcc(inode, &hdr->fattr); | 4241 | nfs_writeback_update_inode(hdr); |
| 4238 | } | 4242 | } |
| 4239 | return 0; | 4243 | return 0; |
| 4240 | } | 4244 | } |
| @@ -6893,9 +6897,13 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred, | |||
| 6893 | 6897 | ||
| 6894 | if (status == 0) { | 6898 | if (status == 0) { |
| 6895 | clp->cl_clientid = res.clientid; | 6899 | clp->cl_clientid = res.clientid; |
| 6896 | clp->cl_exchange_flags = (res.flags & ~EXCHGID4_FLAG_CONFIRMED_R); | 6900 | clp->cl_exchange_flags = res.flags; |
| 6897 | if (!(res.flags & EXCHGID4_FLAG_CONFIRMED_R)) | 6901 | /* Client ID is not confirmed */ |
| 6902 | if (!(res.flags & EXCHGID4_FLAG_CONFIRMED_R)) { | ||
| 6903 | clear_bit(NFS4_SESSION_ESTABLISHED, | ||
| 6904 | &clp->cl_session->session_state); | ||
| 6898 | clp->cl_seqid = res.seqid; | 6905 | clp->cl_seqid = res.seqid; |
| 6906 | } | ||
| 6899 | 6907 | ||
| 6900 | kfree(clp->cl_serverowner); | 6908 | kfree(clp->cl_serverowner); |
| 6901 | clp->cl_serverowner = res.server_owner; | 6909 | clp->cl_serverowner = res.server_owner; |
| @@ -7227,6 +7235,9 @@ static void nfs4_update_session(struct nfs4_session *session, | |||
| 7227 | struct nfs41_create_session_res *res) | 7235 | struct nfs41_create_session_res *res) |
| 7228 | { | 7236 | { |
| 7229 | nfs4_copy_sessionid(&session->sess_id, &res->sessionid); | 7237 | nfs4_copy_sessionid(&session->sess_id, &res->sessionid); |
| 7238 | /* Mark client id and session as being confirmed */ | ||
| 7239 | session->clp->cl_exchange_flags |= EXCHGID4_FLAG_CONFIRMED_R; | ||
| 7240 | set_bit(NFS4_SESSION_ESTABLISHED, &session->session_state); | ||
| 7230 | session->flags = res->flags; | 7241 | session->flags = res->flags; |
| 7231 | memcpy(&session->fc_attrs, &res->fc_attrs, sizeof(session->fc_attrs)); | 7242 | memcpy(&session->fc_attrs, &res->fc_attrs, sizeof(session->fc_attrs)); |
| 7232 | if (res->flags & SESSION4_BACK_CHAN) | 7243 | if (res->flags & SESSION4_BACK_CHAN) |
| @@ -7322,8 +7333,8 @@ int nfs4_proc_destroy_session(struct nfs4_session *session, | |||
| 7322 | dprintk("--> nfs4_proc_destroy_session\n"); | 7333 | dprintk("--> nfs4_proc_destroy_session\n"); |
| 7323 | 7334 | ||
| 7324 | /* session is still being setup */ | 7335 | /* session is still being setup */ |
| 7325 | if (session->clp->cl_cons_state != NFS_CS_READY) | 7336 | if (!test_and_clear_bit(NFS4_SESSION_ESTABLISHED, &session->session_state)) |
| 7326 | return status; | 7337 | return 0; |
| 7327 | 7338 | ||
| 7328 | status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); | 7339 | status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
| 7329 | trace_nfs4_destroy_session(session->clp, status); | 7340 | trace_nfs4_destroy_session(session->clp, status); |
diff --git a/fs/nfs/nfs4session.h b/fs/nfs/nfs4session.h index fc46c7455898..e3ea2c5324d6 100644 --- a/fs/nfs/nfs4session.h +++ b/fs/nfs/nfs4session.h | |||
| @@ -70,6 +70,7 @@ struct nfs4_session { | |||
| 70 | 70 | ||
| 71 | enum nfs4_session_state { | 71 | enum nfs4_session_state { |
| 72 | NFS4_SESSION_INITING, | 72 | NFS4_SESSION_INITING, |
| 73 | NFS4_SESSION_ESTABLISHED, | ||
| 73 | }; | 74 | }; |
| 74 | 75 | ||
| 75 | extern int nfs4_setup_slot_table(struct nfs4_slot_table *tbl, | 76 | extern int nfs4_setup_slot_table(struct nfs4_slot_table *tbl, |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 5ad908e9ce9c..f95e3b58bbc3 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
| @@ -346,9 +346,23 @@ int nfs41_discover_server_trunking(struct nfs_client *clp, | |||
| 346 | status = nfs4_proc_exchange_id(clp, cred); | 346 | status = nfs4_proc_exchange_id(clp, cred); |
| 347 | if (status != NFS4_OK) | 347 | if (status != NFS4_OK) |
| 348 | return status; | 348 | return status; |
| 349 | set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); | ||
| 350 | 349 | ||
| 351 | return nfs41_walk_client_list(clp, result, cred); | 350 | status = nfs41_walk_client_list(clp, result, cred); |
| 351 | if (status < 0) | ||
| 352 | return status; | ||
| 353 | if (clp != *result) | ||
| 354 | return 0; | ||
| 355 | |||
| 356 | /* Purge state if the client id was established in a prior instance */ | ||
| 357 | if (clp->cl_exchange_flags & EXCHGID4_FLAG_CONFIRMED_R) | ||
| 358 | set_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state); | ||
| 359 | else | ||
| 360 | set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); | ||
| 361 | nfs4_schedule_state_manager(clp); | ||
| 362 | status = nfs_wait_client_init_complete(clp); | ||
| 363 | if (status < 0) | ||
| 364 | nfs_put_client(clp); | ||
| 365 | return status; | ||
| 352 | } | 366 | } |
| 353 | 367 | ||
| 354 | #endif /* CONFIG_NFS_V4_1 */ | 368 | #endif /* CONFIG_NFS_V4_1 */ |
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index b09cc23d6f43..c63189acd052 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c | |||
| @@ -139,7 +139,7 @@ nfs_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, | |||
| 139 | nfs_fattr_init(fattr); | 139 | nfs_fattr_init(fattr); |
| 140 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); | 140 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); |
| 141 | if (status == 0) | 141 | if (status == 0) |
| 142 | nfs_setattr_update_inode(inode, sattr); | 142 | nfs_setattr_update_inode(inode, sattr, fattr); |
| 143 | dprintk("NFS reply setattr: %d\n", status); | 143 | dprintk("NFS reply setattr: %d\n", status); |
| 144 | return status; | 144 | return status; |
| 145 | } | 145 | } |
| @@ -609,10 +609,8 @@ static int nfs_proc_pgio_rpc_prepare(struct rpc_task *task, | |||
| 609 | 609 | ||
| 610 | static int nfs_write_done(struct rpc_task *task, struct nfs_pgio_header *hdr) | 610 | static int nfs_write_done(struct rpc_task *task, struct nfs_pgio_header *hdr) |
| 611 | { | 611 | { |
| 612 | struct inode *inode = hdr->inode; | ||
| 613 | |||
| 614 | if (task->tk_status >= 0) | 612 | if (task->tk_status >= 0) |
| 615 | nfs_post_op_update_inode_force_wcc(inode, hdr->res.fattr); | 613 | nfs_writeback_update_inode(hdr); |
| 616 | return 0; | 614 | return 0; |
| 617 | } | 615 | } |
| 618 | 616 | ||
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 595d81e354d1..849ed784d6ac 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
| @@ -1377,6 +1377,36 @@ static int nfs_should_remove_suid(const struct inode *inode) | |||
| 1377 | return 0; | 1377 | return 0; |
| 1378 | } | 1378 | } |
| 1379 | 1379 | ||
| 1380 | static void nfs_writeback_check_extend(struct nfs_pgio_header *hdr, | ||
| 1381 | struct nfs_fattr *fattr) | ||
| 1382 | { | ||
| 1383 | struct nfs_pgio_args *argp = &hdr->args; | ||
| 1384 | struct nfs_pgio_res *resp = &hdr->res; | ||
| 1385 | |||
| 1386 | if (!(fattr->valid & NFS_ATTR_FATTR_SIZE)) | ||
| 1387 | return; | ||
| 1388 | if (argp->offset + resp->count != fattr->size) | ||
| 1389 | return; | ||
| 1390 | if (nfs_size_to_loff_t(fattr->size) < i_size_read(hdr->inode)) | ||
| 1391 | return; | ||
| 1392 | /* Set attribute barrier */ | ||
| 1393 | nfs_fattr_set_barrier(fattr); | ||
| 1394 | } | ||
| 1395 | |||
| 1396 | void nfs_writeback_update_inode(struct nfs_pgio_header *hdr) | ||
| 1397 | { | ||
| 1398 | struct nfs_fattr *fattr = hdr->res.fattr; | ||
| 1399 | struct inode *inode = hdr->inode; | ||
| 1400 | |||
| 1401 | if (fattr == NULL) | ||
| 1402 | return; | ||
| 1403 | spin_lock(&inode->i_lock); | ||
| 1404 | nfs_writeback_check_extend(hdr, fattr); | ||
| 1405 | nfs_post_op_update_inode_force_wcc_locked(inode, fattr); | ||
| 1406 | spin_unlock(&inode->i_lock); | ||
| 1407 | } | ||
| 1408 | EXPORT_SYMBOL_GPL(nfs_writeback_update_inode); | ||
| 1409 | |||
| 1380 | /* | 1410 | /* |
| 1381 | * This function is called when the WRITE call is complete. | 1411 | * This function is called when the WRITE call is complete. |
| 1382 | */ | 1412 | */ |
