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