diff -u --recursive --new-file linux-2.5.59-05-nfsv4-readstate/fs/nfs/nfs3proc.c linux-2.5.59-06-nfsv4-writestate/fs/nfs/nfs3proc.c --- linux-2.5.59-05-nfsv4-readstate/fs/nfs/nfs3proc.c 2003-01-17 14:16:56.000000000 +0100 +++ linux-2.5.59-06-nfsv4-writestate/fs/nfs/nfs3proc.c 2003-01-17 14:17:15.000000000 +0100 @@ -262,7 +262,7 @@ static int nfs3_proc_write(struct inode *inode, struct rpc_cred *cred, - struct nfs_fattr *fattr, int flags, + struct nfs_fattr *fattr, int flags, unsigned int oflags, unsigned int base, unsigned int count, struct page *page, struct nfs_writeverf *verf) { diff -u --recursive --new-file linux-2.5.59-05-nfsv4-readstate/fs/nfs/nfs4proc.c linux-2.5.59-06-nfsv4-writestate/fs/nfs/nfs4proc.c --- linux-2.5.59-05-nfsv4-readstate/fs/nfs/nfs4proc.c 2003-01-17 14:16:56.000000000 +0100 +++ linux-2.5.59-06-nfsv4-writestate/fs/nfs/nfs4proc.c 2003-01-17 14:17:15.000000000 +0100 @@ -55,7 +55,10 @@ extern struct rpc_procinfo nfs4_procedures[]; static nfs4_stateid zero_stateid = - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +static nfs4_stateid one_stateid = + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + static spinlock_t renew_lock = SPIN_LOCK_UNLOCKED; static void @@ -1069,11 +1072,12 @@ static int nfs4_proc_write(struct inode *inode, struct rpc_cred *cred, - struct nfs_fattr *fattr, int flags, + struct nfs_fattr *fattr, int flags, unsigned int oflags, unsigned int base, unsigned int count, struct page *page, struct nfs_writeverf *verf) { struct nfs_server *server = NFS_SERVER(inode); + struct nfs4_shareowner *sp; uint64_t offset = page_offset(page) + base; struct nfs_writeargs arg = { .fh = NFS_FH(inode), @@ -1097,6 +1101,22 @@ int rpcflags = (flags & NFS_RW_SWAP) ? NFS_RPC_SWAPFLAGS : 0; dprintk("NFS call write %d @ %Ld\n", count, (long long)offset); + + /* + * If oflags are not set, try first to use O_RDONLY, then + * O_RDWR stateid. + */ + if (oflags) + sp = nfs4_get_inode_share(inode, oflags); + else + sp = nfs4_get_inode_share(inode, + NFS4_SHARE_ACCESS_BOTH | NFS4_SHARE_ACCESS_WRITE); + + if (sp) + memcpy(arg.stateid,sp->so_stateid, sizeof(nfs4_stateid)); + else + memcpy(arg.stateid, one_stateid, sizeof(nfs4_stateid)); + fattr->valid = 0; return rpc_call_sync(server->client, &msg, rpcflags); } @@ -1540,6 +1560,7 @@ }; struct inode *inode = data->inode; struct nfs_page *req = nfs_list_entry(data->pages.next); + struct nfs4_shareowner *sp; int stable; int flags; @@ -1562,6 +1583,21 @@ data->res.verf = &data->verf; data->timestamp = jiffies; + if(req->wb_file) { + unsigned int oflags = req->wb_file->f_flags; + + if ((oflags & 3) != 3) + oflags++; + sp = nfs4_get_inode_share(inode, oflags); + } else + sp = nfs4_get_inode_share(inode, + NFS4_SHARE_ACCESS_BOTH | NFS4_SHARE_ACCESS_WRITE); + + if (sp) + memcpy(data->args.stateid,sp->so_stateid, sizeof(nfs4_stateid)); + else + memcpy(data->args.stateid, one_stateid, sizeof(nfs4_stateid)); + /* Set the initial flags for the task. */ flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; diff -u --recursive --new-file linux-2.5.59-05-nfsv4-readstate/fs/nfs/nfs4xdr.c linux-2.5.59-06-nfsv4-writestate/fs/nfs/nfs4xdr.c --- linux-2.5.59-05-nfsv4-readstate/fs/nfs/nfs4xdr.c 2003-01-17 14:16:56.000000000 +0100 +++ linux-2.5.59-06-nfsv4-writestate/fs/nfs/nfs4xdr.c 2003-01-17 14:17:15.000000000 +0100 @@ -834,10 +834,7 @@ RESERVE_SPACE(36); WRITE32(OP_WRITE); - WRITE32(0xffffffff); /* magic stateid -1 */ - WRITE32(0xffffffff); - WRITE32(0xffffffff); - WRITE32(0xffffffff); + WRITEMEM(args->stateid, sizeof(nfs4_stateid)); WRITE64(args->offset); WRITE32(args->stable); WRITE32(args->count); diff -u --recursive --new-file linux-2.5.59-05-nfsv4-readstate/fs/nfs/proc.c linux-2.5.59-06-nfsv4-writestate/fs/nfs/proc.c --- linux-2.5.59-05-nfsv4-readstate/fs/nfs/proc.c 2003-01-17 14:16:56.000000000 +0100 +++ linux-2.5.59-06-nfsv4-writestate/fs/nfs/proc.c 2003-01-17 14:17:15.000000000 +0100 @@ -187,7 +187,7 @@ static int nfs_proc_write(struct inode *inode, struct rpc_cred *cred, - struct nfs_fattr *fattr, int how, + struct nfs_fattr *fattr, int how, unsigned int oflags, unsigned int base, unsigned int count, struct page *page, struct nfs_writeverf *verf) { diff -u --recursive --new-file linux-2.5.59-05-nfsv4-readstate/fs/nfs/write.c linux-2.5.59-06-nfsv4-writestate/fs/nfs/write.c --- linux-2.5.59-05-nfsv4-readstate/fs/nfs/write.c 2003-01-08 12:30:45.000000000 +0100 +++ linux-2.5.59-06-nfsv4-writestate/fs/nfs/write.c 2003-01-17 14:17:15.000000000 +0100 @@ -139,10 +139,15 @@ u8 *buffer; struct nfs_fattr fattr; struct nfs_writeverf verf; + unsigned int oflags = 0; - if (file) + if (file) { cred = get_rpccred(nfs_file_cred(file)); + oflags = file->f_flags; + if((oflags &3) != 3) + oflags++; + } if (!cred) cred = get_rpccred(NFS_I(inode)->mm_cred); @@ -160,7 +165,7 @@ wsize = count; result = NFS_PROTO(inode)->write(inode, cred, &fattr, flags, - offset, wsize, page, &verf); + oflags, offset, wsize, page, &verf); if (result < 0) { /* Must mark the page invalid after I/O error */ diff -u --recursive --new-file linux-2.5.59-05-nfsv4-readstate/include/linux/nfs_xdr.h linux-2.5.59-06-nfsv4-writestate/include/linux/nfs_xdr.h --- linux-2.5.59-05-nfsv4-readstate/include/linux/nfs_xdr.h 2003-01-17 14:16:56.000000000 +0100 +++ linux-2.5.59-06-nfsv4-writestate/include/linux/nfs_xdr.h 2003-01-17 14:17:15.000000000 +0100 @@ -180,6 +180,7 @@ struct nfs_writeargs { struct nfs_fh * fh; + nfs4_stateid stateid; __u64 offset; __u32 count; enum nfs3_stable_how stable; @@ -635,7 +636,7 @@ struct page *, int *eofp); int (*write) (struct inode *, struct rpc_cred *, struct nfs_fattr *, - int, unsigned int, unsigned int, + int, unsigned int, unsigned int, unsigned int, struct page *, struct nfs_writeverf *verfp); int (*commit) (struct inode *, struct nfs_fattr *, unsigned long, unsigned int);