Merge branch 'bugfixes' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6

* 'bugfixes' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6:
NFSv4: fix delegated locking
NFS: Ensure that the WRITE and COMMIT RPC calls are always uninterruptible
NFS: Fix a race with the new commit code
NFS: Ensure that writeback_single_inode() calls write_inode() when syncing
NFS: Fix the mode calculation in nfs_find_open_context
NFSv4: Fall back to ordinary lookup if nfs4_atomic_open() returns EISDIR

+39 -23
+2 -1
fs/nfs/client.c
··· 1294 1295 /* Initialise the client representation from the mount data */ 1296 server->flags = data->flags; 1297 - server->caps |= NFS_CAP_ATOMIC_OPEN|NFS_CAP_CHANGE_ATTR; 1298 server->options = data->options; 1299 1300 /* Get a client record */
··· 1294 1295 /* Initialise the client representation from the mount data */ 1296 server->flags = data->flags; 1297 + server->caps |= NFS_CAP_ATOMIC_OPEN|NFS_CAP_CHANGE_ATTR| 1298 + NFS_CAP_POSIX_LOCK; 1299 server->options = data->options; 1300 1301 /* Get a client record */
+1 -1
fs/nfs/dir.c
··· 1025 res = NULL; 1026 goto out; 1027 /* This turned out not to be a regular file */ 1028 case -ENOTDIR: 1029 goto no_open; 1030 case -ELOOP: 1031 if (!(nd->intent.open.flags & O_NOFOLLOW)) 1032 goto no_open; 1033 - /* case -EISDIR: */ 1034 /* case -EINVAL: */ 1035 default: 1036 goto out;
··· 1025 res = NULL; 1026 goto out; 1027 /* This turned out not to be a regular file */ 1028 + case -EISDIR: 1029 case -ENOTDIR: 1030 goto no_open; 1031 case -ELOOP: 1032 if (!(nd->intent.open.flags & O_NOFOLLOW)) 1033 goto no_open; 1034 /* case -EINVAL: */ 1035 default: 1036 goto out;
+4 -4
fs/nfs/inode.c
··· 623 list_for_each_entry(pos, &nfsi->open_files, list) { 624 if (cred != NULL && pos->cred != cred) 625 continue; 626 - if ((pos->mode & mode) == mode) { 627 - ctx = get_nfs_open_context(pos); 628 - break; 629 - } 630 } 631 spin_unlock(&inode->i_lock); 632 return ctx;
··· 623 list_for_each_entry(pos, &nfsi->open_files, list) { 624 if (cred != NULL && pos->cred != cred) 625 continue; 626 + if ((pos->mode & (FMODE_READ|FMODE_WRITE)) != mode) 627 + continue; 628 + ctx = get_nfs_open_context(pos); 629 + break; 630 } 631 spin_unlock(&inode->i_lock); 632 return ctx;
+3 -1
fs/nfs/nfs4proc.c
··· 1523 nfs_post_op_update_inode(dir, o_res->dir_attr); 1524 } else 1525 nfs_refresh_inode(dir, o_res->dir_attr); 1526 if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) { 1527 status = _nfs4_proc_open_confirm(data); 1528 if (status != 0) ··· 1666 status = PTR_ERR(state); 1667 if (IS_ERR(state)) 1668 goto err_opendata_put; 1669 - if ((opendata->o_res.rflags & NFS4_OPEN_RESULT_LOCKTYPE_POSIX) != 0) 1670 set_bit(NFS_STATE_POSIX_LOCKS, &state->flags); 1671 nfs4_opendata_put(opendata); 1672 nfs4_put_state_owner(sp);
··· 1523 nfs_post_op_update_inode(dir, o_res->dir_attr); 1524 } else 1525 nfs_refresh_inode(dir, o_res->dir_attr); 1526 + if ((o_res->rflags & NFS4_OPEN_RESULT_LOCKTYPE_POSIX) == 0) 1527 + server->caps &= ~NFS_CAP_POSIX_LOCK; 1528 if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) { 1529 status = _nfs4_proc_open_confirm(data); 1530 if (status != 0) ··· 1664 status = PTR_ERR(state); 1665 if (IS_ERR(state)) 1666 goto err_opendata_put; 1667 + if (server->caps & NFS_CAP_POSIX_LOCK) 1668 set_bit(NFS_STATE_POSIX_LOCKS, &state->flags); 1669 nfs4_opendata_put(opendata); 1670 nfs4_put_state_owner(sp);
+28 -16
fs/nfs/write.c
··· 201 struct inode *inode = page->mapping->host; 202 struct nfs_server *nfss = NFS_SERVER(inode); 203 204 if (atomic_long_inc_return(&nfss->writeback) > 205 NFS_CONGESTION_ON_THRESH) { 206 set_bdi_congested(&nfss->backing_dev_info, ··· 217 struct nfs_server *nfss = NFS_SERVER(inode); 218 219 end_page_writeback(page); 220 if (atomic_long_dec_return(&nfss->writeback) < NFS_CONGESTION_OFF_THRESH) 221 clear_bdi_congested(&nfss->backing_dev_info, BLK_RW_ASYNC); 222 } ··· 423 nfs_mark_request_dirty(struct nfs_page *req) 424 { 425 __set_page_dirty_nobuffers(req->wb_page); 426 } 427 428 #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) ··· 663 req = nfs_setup_write_request(ctx, page, offset, count); 664 if (IS_ERR(req)) 665 return PTR_ERR(req); 666 /* Update file length */ 667 nfs_grow_file(page, offset, count); 668 nfs_mark_uptodate(page, req->wb_pgbase, req->wb_bytes); 669 nfs_clear_page_tag_locked(req); 670 return 0; 671 } ··· 744 status = nfs_writepage_setup(ctx, page, offset, count); 745 if (status < 0) 746 nfs_set_pageerror(page); 747 - else 748 - __set_page_dirty_nobuffers(page); 749 750 dprintk("NFS: nfs_updatepage returns %d (isize %lld)\n", 751 status, (long long)i_size_read(inode)); ··· 752 753 static void nfs_writepage_release(struct nfs_page *req) 754 { 755 756 - if (PageError(req->wb_page) || !nfs_reschedule_unstable_write(req)) { 757 - nfs_end_page_writeback(req->wb_page); 758 nfs_inode_remove_request(req); 759 - } else 760 - nfs_end_page_writeback(req->wb_page); 761 nfs_clear_page_tag_locked(req); 762 } 763 764 static int flush_task_priority(int how) ··· 781 int how) 782 { 783 struct inode *inode = req->wb_context->path.dentry->d_inode; 784 - int flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; 785 int priority = flush_task_priority(how); 786 struct rpc_task *task; 787 struct rpc_message msg = { ··· 795 .callback_ops = call_ops, 796 .callback_data = data, 797 .workqueue = nfsiod_workqueue, 798 - .flags = flags, 799 .priority = priority, 800 }; 801 802 /* Set up the RPC argument and reply structs 803 * NB: take care not to mess about with data->commit et al. */ ··· 837 (unsigned long long)data->args.offset); 838 839 task = rpc_run_task(&task_setup_data); 840 - if (IS_ERR(task)) 841 - return PTR_ERR(task); 842 rpc_put_task(task); 843 - return 0; 844 } 845 846 /* If a nfs_flush_* function fails, it should remove reqs from @head and ··· 857 */ 858 static void nfs_redirty_request(struct nfs_page *req) 859 { 860 nfs_mark_request_dirty(req); 861 - nfs_end_page_writeback(req->wb_page); 862 nfs_clear_page_tag_locked(req); 863 } 864 865 /* ··· 1096 if (nfs_write_need_commit(data)) { 1097 memcpy(&req->wb_verf, &data->verf, sizeof(req->wb_verf)); 1098 nfs_mark_request_commit(req); 1099 - nfs_end_page_writeback(page); 1100 dprintk(" marked for commit\n"); 1101 goto next; 1102 } 1103 dprintk(" OK\n"); 1104 remove_request: 1105 - nfs_end_page_writeback(page); 1106 nfs_inode_remove_request(req); 1107 next: 1108 nfs_clear_page_tag_locked(req); 1109 } 1110 nfs_writedata_release(calldata); 1111 } ··· 1218 { 1219 struct nfs_page *first = nfs_list_entry(head->next); 1220 struct inode *inode = first->wb_context->path.dentry->d_inode; 1221 - int flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; 1222 int priority = flush_task_priority(how); 1223 struct rpc_task *task; 1224 struct rpc_message msg = { ··· 1232 .callback_ops = &nfs_commit_ops, 1233 .callback_data = data, 1234 .workqueue = nfsiod_workqueue, 1235 - .flags = flags, 1236 .priority = priority, 1237 }; 1238 ··· 1262 task = rpc_run_task(&task_setup_data); 1263 if (IS_ERR(task)) 1264 return PTR_ERR(task); 1265 rpc_put_task(task); 1266 return 0; 1267 }
··· 201 struct inode *inode = page->mapping->host; 202 struct nfs_server *nfss = NFS_SERVER(inode); 203 204 + page_cache_get(page); 205 if (atomic_long_inc_return(&nfss->writeback) > 206 NFS_CONGESTION_ON_THRESH) { 207 set_bdi_congested(&nfss->backing_dev_info, ··· 216 struct nfs_server *nfss = NFS_SERVER(inode); 217 218 end_page_writeback(page); 219 + page_cache_release(page); 220 if (atomic_long_dec_return(&nfss->writeback) < NFS_CONGESTION_OFF_THRESH) 221 clear_bdi_congested(&nfss->backing_dev_info, BLK_RW_ASYNC); 222 } ··· 421 nfs_mark_request_dirty(struct nfs_page *req) 422 { 423 __set_page_dirty_nobuffers(req->wb_page); 424 + __mark_inode_dirty(req->wb_page->mapping->host, I_DIRTY_DATASYNC); 425 } 426 427 #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) ··· 660 req = nfs_setup_write_request(ctx, page, offset, count); 661 if (IS_ERR(req)) 662 return PTR_ERR(req); 663 + nfs_mark_request_dirty(req); 664 /* Update file length */ 665 nfs_grow_file(page, offset, count); 666 nfs_mark_uptodate(page, req->wb_pgbase, req->wb_bytes); 667 + nfs_mark_request_dirty(req); 668 nfs_clear_page_tag_locked(req); 669 return 0; 670 } ··· 739 status = nfs_writepage_setup(ctx, page, offset, count); 740 if (status < 0) 741 nfs_set_pageerror(page); 742 743 dprintk("NFS: nfs_updatepage returns %d (isize %lld)\n", 744 status, (long long)i_size_read(inode)); ··· 749 750 static void nfs_writepage_release(struct nfs_page *req) 751 { 752 + struct page *page = req->wb_page; 753 754 + if (PageError(req->wb_page) || !nfs_reschedule_unstable_write(req)) 755 nfs_inode_remove_request(req); 756 nfs_clear_page_tag_locked(req); 757 + nfs_end_page_writeback(page); 758 } 759 760 static int flush_task_priority(int how) ··· 779 int how) 780 { 781 struct inode *inode = req->wb_context->path.dentry->d_inode; 782 int priority = flush_task_priority(how); 783 struct rpc_task *task; 784 struct rpc_message msg = { ··· 794 .callback_ops = call_ops, 795 .callback_data = data, 796 .workqueue = nfsiod_workqueue, 797 + .flags = RPC_TASK_ASYNC, 798 .priority = priority, 799 }; 800 + int ret = 0; 801 802 /* Set up the RPC argument and reply structs 803 * NB: take care not to mess about with data->commit et al. */ ··· 835 (unsigned long long)data->args.offset); 836 837 task = rpc_run_task(&task_setup_data); 838 + if (IS_ERR(task)) { 839 + ret = PTR_ERR(task); 840 + goto out; 841 + } 842 + if (how & FLUSH_SYNC) { 843 + ret = rpc_wait_for_completion_task(task); 844 + if (ret == 0) 845 + ret = task->tk_status; 846 + } 847 rpc_put_task(task); 848 + out: 849 + return ret; 850 } 851 852 /* If a nfs_flush_* function fails, it should remove reqs from @head and ··· 847 */ 848 static void nfs_redirty_request(struct nfs_page *req) 849 { 850 + struct page *page = req->wb_page; 851 + 852 nfs_mark_request_dirty(req); 853 nfs_clear_page_tag_locked(req); 854 + nfs_end_page_writeback(page); 855 } 856 857 /* ··· 1084 if (nfs_write_need_commit(data)) { 1085 memcpy(&req->wb_verf, &data->verf, sizeof(req->wb_verf)); 1086 nfs_mark_request_commit(req); 1087 dprintk(" marked for commit\n"); 1088 goto next; 1089 } 1090 dprintk(" OK\n"); 1091 remove_request: 1092 nfs_inode_remove_request(req); 1093 next: 1094 nfs_clear_page_tag_locked(req); 1095 + nfs_end_page_writeback(page); 1096 } 1097 nfs_writedata_release(calldata); 1098 } ··· 1207 { 1208 struct nfs_page *first = nfs_list_entry(head->next); 1209 struct inode *inode = first->wb_context->path.dentry->d_inode; 1210 int priority = flush_task_priority(how); 1211 struct rpc_task *task; 1212 struct rpc_message msg = { ··· 1222 .callback_ops = &nfs_commit_ops, 1223 .callback_data = data, 1224 .workqueue = nfsiod_workqueue, 1225 + .flags = RPC_TASK_ASYNC, 1226 .priority = priority, 1227 }; 1228 ··· 1252 task = rpc_run_task(&task_setup_data); 1253 if (IS_ERR(task)) 1254 return PTR_ERR(task); 1255 + if (how & FLUSH_SYNC) 1256 + rpc_wait_for_completion_task(task); 1257 rpc_put_task(task); 1258 return 0; 1259 }
+1
include/linux/nfs_fs_sb.h
··· 176 #define NFS_CAP_ATIME (1U << 11) 177 #define NFS_CAP_CTIME (1U << 12) 178 #define NFS_CAP_MTIME (1U << 13) 179 180 181 /* maximum number of slots to use */
··· 176 #define NFS_CAP_ATIME (1U << 11) 177 #define NFS_CAP_CTIME (1U << 12) 178 #define NFS_CAP_MTIME (1U << 13) 179 + #define NFS_CAP_POSIX_LOCK (1U << 14) 180 181 182 /* maximum number of slots to use */