diff options
| author | Trond Myklebust <trond.myklebust@fys.uio.no> | 2003-04-08 04:27:37 +0200 |
|---|---|---|
| committer | Trond Myklebust <trond.myklebust@fys.uio.no> | 2003-04-08 04:27:37 +0200 |
| commit | 45f3fae685e9579979b0dbed506c424688d72881 (patch) | |
| tree | eef8b81a6e74125a4c8b93b6b2fcf0372dc46075 | |
| parent | 62175be2bd850d3c2db5065fb3ef4dff3272c068 (diff) | |
Setup code to tear down the NFSv4 state once we're done with a file.
| -rw-r--r-- | fs/nfs/nfs4proc.c | 71 | ||||
| -rw-r--r-- | fs/nfs/nfs4state.c | 4 | ||||
| -rw-r--r-- | fs/nfs/nfs4xdr.c | 67 | ||||
| -rw-r--r-- | include/linux/nfs4.h | 1 | ||||
| -rw-r--r-- | include/linux/nfs_fs.h | 1 | ||||
| -rw-r--r-- | include/linux/nfs_xdr.h | 14 |
6 files changed, 119 insertions, 39 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 15ce5d40f2c2..98e7cc17329e 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -81,19 +81,6 @@ nfs4_setup_access(struct nfs4_compound *cp, u32 req_access, u32 *resp_supported, } static void -nfs4_setup_close(struct nfs4_compound *cp, nfs4_stateid stateid, u32 seqid) -{ - struct nfs4_close *close = GET_OP(cp, close); - - close->cl_stateid = stateid; - close->cl_seqid = seqid; - - OPNUM(cp) = OP_CLOSE; - cp->req_nops++; - cp->renew_index = cp->req_nops; -} - -static void nfs4_setup_create_dir(struct nfs4_compound *cp, struct qstr *name, struct iattr *sattr, struct nfs4_change_info *info) { @@ -710,16 +697,44 @@ do_setattr(struct nfs_server *server, struct nfs_fattr *fattr, return nfs4_call_compound(&compound, NULL, 0); } -static int -do_close(struct nfs_server *server, struct nfs_fh *fhandle, u32 seqid, char *stateid) +/* + * It is possible for data to be read/written from a mem-mapped file + * after the sys_close call (which hits the vfs layer as a flush). + * This means that we can't safely call nfsv4 close on a file until + * the inode is cleared. This in turn means that we are not good + * NFSv4 citizens - we do not indicate to the server to update the file's + * share state even when we are done with one of the three share + * stateid's in the inode. + */ +int +nfs4_do_close(struct inode *inode, struct nfs4_shareowner *sp) { - struct nfs4_compound compound; - struct nfs4_op ops[2]; - - nfs4_setup_compound(&compound, ops, server, "close"); - nfs4_setup_putfh(&compound, fhandle); - nfs4_setup_close(&compound, stateid, seqid); - return nfs4_call_compound(&compound, NULL, 0); + int status = 0; + struct nfs_closeargs arg = { + .fh = NFS_FH(inode), + }; + struct nfs_closeres res = { + .status = 0, + }; + struct rpc_message msg = { + .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE], + .rpc_argp = &arg, + .rpc_resp = &res, + }; + + memcpy(arg.stateid, sp->so_stateid, sizeof(nfs4_stateid)); + /* Serialization for the sequence id */ + down(&sp->so_sema); + arg.seqid = sp->so_seqid, + status = rpc_call_sync(NFS_SERVER(inode)->client, &msg, 0); + + /* hmm. we are done with the inode, and in the process of freeing + * the shareowner. we keep this around to process errors + */ + nfs4_increment_seqid(status, sp); + up(&sp->so_sema); + + return status; } static int @@ -820,6 +835,12 @@ nfs4_proc_getattr(struct inode *inode, struct nfs_fattr *fattr) return nfs4_call_compound(&compound, NULL, 0); } +/* + * The file is not closed if it is opened due to the a request to change + * the size of the file. The open call will not be needed once the + * VFS layer lookup-intents are implemented. + * Close is called when the inode is destroyed. + */ static int nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, struct iattr *sattr) @@ -851,15 +872,12 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, */ if (fattr->fileid != NFS_FILEID(inode)) { printk(KERN_WARNING "nfs: raced in setattr, returning -EIO\n"); - do_close(NFS_SERVER(inode), NFS_FH(inode), sp->so_seqid, sp->so_stateid); return -EIO; } } status = do_setattr(NFS_SERVER(inode), fattr, NFS_FH(inode), sattr, fake == 1? zero_stateid: sp->so_stateid); - if (size_change) - do_close(NFS_SERVER(inode), NFS_FH(inode), sp->so_seqid, sp->so_stateid); return status; } @@ -1059,8 +1077,7 @@ nfs4_proc_write(struct inode *inode, struct rpc_cred *cred, * conditions due to the lookup, create, and open VFS calls from sys_open() * placed on the wire. * - * Given the above sorry state of affairs, I'm simply sending an OPEN, a - * possible SETATTR, and then a CLOSE + * Given the above sorry state of affairs, I'm simply sending an OPEN. * The file will be opened again in the subsequent VFS open call * (nfs4_proc_file_open). * diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 059880274526..8243f6d7398d 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -124,7 +124,7 @@ nfs4_get_shareowner(struct inode *dir) } /* - * Called for each inode shareowner in nfs_clear_inode, + * Called for each non-null inode shareowner in nfs_clear_inode, * or if nfs4_do_open fails. */ void @@ -132,6 +132,8 @@ nfs4_put_shareowner(struct inode *inode, struct nfs4_shareowner *sp) { if (!sp) return; + if (sp->so_flags & O_ACCMODE) + nfs4_do_close(inode, sp); kfree(sp); } diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 319d16b0bd01..7bd0e88ebd02 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -144,6 +144,13 @@ extern int nfs_stat_to_errno(int); #define NFS4_dec_open_confirm_sz compound_decode_hdr_maxsz + \ decode_putfh_maxsz + \ op_decode_hdr_maxsz + 4 +#define NFS4_enc_close_sz compound_encode_hdr_maxsz + \ + encode_putfh_maxsz + \ + op_encode_hdr_maxsz + 5 +#define NFS4_dec_close_sz compound_decode_hdr_maxsz + \ + decode_putfh_maxsz + \ + op_decode_hdr_maxsz + 4 + @@ -378,14 +385,14 @@ encode_access(struct xdr_stream *xdr, struct nfs4_access *access) } static int -encode_close(struct xdr_stream *xdr, struct nfs4_close *close) +encode_close(struct xdr_stream *xdr, struct nfs_closeargs *arg) { uint32_t *p; RESERVE_SPACE(8+sizeof(nfs4_stateid)); WRITE32(OP_CLOSE); - WRITE32(close->cl_seqid); - WRITEMEM(close->cl_stateid, sizeof(nfs4_stateid)); + WRITE32(arg->seqid); + WRITEMEM(arg->stateid, sizeof(nfs4_stateid)); return 0; } @@ -858,9 +865,6 @@ encode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs case OP_ACCESS: status = encode_access(xdr, &cp->ops[i].u.access); break; - case OP_CLOSE: - status = encode_close(xdr, &cp->ops[i].u.close); - break; case OP_CREATE: status = encode_create(xdr, &cp->ops[i].u.create); break; @@ -941,6 +945,28 @@ nfs4_xdr_enc_compound(struct rpc_rqst *req, uint32_t *p, struct nfs4_compound *c return status; } /* + * Encode a CLOSE request + */ +static int +nfs4_xdr_enc_close(struct rpc_rqst *req, uint32_t *p, struct nfs_closeargs *args) +{ + struct xdr_stream xdr; + struct compound_hdr hdr = { + .nops = 2, + }; + int status; + + xdr_init_encode(&xdr, &req->rq_snd_buf, p); + encode_compound_hdr(&xdr, &hdr); + status = encode_putfh(&xdr, args->fh); + if(status) + goto out; + status = encode_close(&xdr, args); +out: + return status; +} + +/* * Encode an OPEN request */ static int @@ -1229,7 +1255,7 @@ decode_access(struct xdr_stream *xdr, struct nfs4_access *access) } static int -decode_close(struct xdr_stream *xdr, struct nfs4_close *close) +decode_close(struct xdr_stream *xdr, struct nfs_closeres *res) { uint32_t *p; int status; @@ -1238,7 +1264,7 @@ decode_close(struct xdr_stream *xdr, struct nfs4_close *close) if (status) return status; READ_BUF(sizeof(nfs4_stateid)); - COPYMEM(close->cl_stateid, sizeof(nfs4_stateid)); + COPYMEM(res->stateid, sizeof(nfs4_stateid)); return 0; } @@ -2076,9 +2102,6 @@ decode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs case OP_ACCESS: status = decode_access(xdr, &op->u.access); break; - case OP_CLOSE: - status = decode_close(xdr, &op->u.close); - break; case OP_CREATE: status = decode_create(xdr, &op->u.create); break; @@ -2165,6 +2188,27 @@ out: return status; } +/* + * Decode CLOSE response + */ +static int +nfs4_xdr_dec_close(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_closeres *res) +{ + struct xdr_stream xdr; + struct compound_hdr hdr; + int status; + + xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p); + status = decode_compound_hdr(&xdr, &hdr); + if (status) + goto out; + status = decode_putfh(&xdr); + if (status) + goto out; + status = decode_close(&xdr, res); +out: + return status; +} /* * Decode OPEN response @@ -2374,6 +2418,7 @@ struct rpc_procinfo nfs4_procedures[] = { PROC(COMMIT, enc_commit, dec_commit), PROC(OPEN, enc_open, dec_open), PROC(OPEN_CONFIRM, enc_open_confirm, dec_open_confirm), + PROC(CLOSE, enc_close, dec_close), }; struct rpc_version nfs_version4 = { diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h index 02c77391d6f8..ace7f169b5dc 100644 --- a/include/linux/nfs4.h +++ b/include/linux/nfs4.h @@ -208,6 +208,7 @@ enum { NFSPROC4_CLNT_COMMIT, NFSPROC4_CLNT_OPEN, NFSPROC4_CLNT_OPEN_CONFIRM, + NFSPROC4_CLNT_CLOSE, }; #endif diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 7d53fd8a8710..3d7525998534 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -491,6 +491,7 @@ struct nfs4_shareowner { /* nfs4proc.c */ extern int nfs4_proc_renew(struct nfs_server *server); +extern int nfs4_do_close(struct inode *inode, struct nfs4_shareowner *sp); /* nfs4renewd.c */ extern int nfs4_init_renewd(struct nfs_server *server); diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 2d1544931139..1b1db6599e6e 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -131,6 +131,20 @@ struct nfs_open_confirmres { nfs4_stateid stateid; }; +/* + * Arguments to the close call. + */ +struct nfs_closeargs { + struct nfs_fh * fh; + nfs4_stateid stateid; + __u32 seqid; +}; + +struct nfs_closeres { + __u32 status; + nfs4_stateid stateid; +}; + /* * Arguments to the read call. |
