From 8c21c62c4452f4e66c3dac9b3f6b74474fad3e08 Mon Sep 17 00:00:00 2001 From: Weston Andros Adamson Date: Tue, 13 Aug 2013 16:37:37 -0400 Subject: [PATCH] nfs4.1: Add SP4_MACH_CRED write and commit support WRITE and COMMIT can use the machine credential. If WRITE is supported and COMMIT is not, make all (mach cred) writes FILE_SYNC4. Signed-off-by: Weston Andros Adamson Signed-off-by: Trond Myklebust --- fs/nfs/nfs4_fs.h | 50 ++++++++++++++++++++++++++++++++++++++--------- fs/nfs/nfs4proc.c | 10 ++++++++++ fs/nfs/write.c | 6 ++++++ include/linux/nfs_fs_sb.h | 2 ++ 4 files changed, 59 insertions(+), 9 deletions(-) diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 3559e89..d2db3ce 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h @@ -269,15 +269,9 @@ is_ds_client(struct nfs_client *clp) return clp->cl_exchange_flags & EXCHGID4_FLAG_USE_PNFS_DS; } -/* - * Function responsible for determining if an rpc_message should use the - * machine cred under SP4_MACH_CRED and if so switching the credential and - * authflavor (using the nfs_client's rpc_clnt which will be krb5i/p). - * Should be called before rpc_call_sync/rpc_call_async. - */ -static inline void -nfs4_state_protect(struct nfs_client *clp, unsigned long sp4_mode, - struct rpc_clnt **clntp, struct rpc_message *msg) +static inline bool +_nfs4_state_protect(struct nfs_client *clp, unsigned long sp4_mode, + struct rpc_clnt **clntp, struct rpc_message *msg) { struct rpc_cred *newcred = NULL; rpc_authflavor_t flavor; @@ -295,7 +289,37 @@ nfs4_state_protect(struct nfs_client *clp, unsigned long sp4_mode, WARN_ON(flavor != RPC_AUTH_GSS_KRB5I && flavor != RPC_AUTH_GSS_KRB5P); *clntp = clp->cl_rpcclient; + + return true; } + return false; +} + +/* + * Function responsible for determining if an rpc_message should use the + * machine cred under SP4_MACH_CRED and if so switching the credential and + * authflavor (using the nfs_client's rpc_clnt which will be krb5i/p). + * Should be called before rpc_call_sync/rpc_call_async. + */ +static inline void +nfs4_state_protect(struct nfs_client *clp, unsigned long sp4_mode, + struct rpc_clnt **clntp, struct rpc_message *msg) +{ + _nfs4_state_protect(clp, sp4_mode, clntp, msg); +} + +/* + * Special wrapper to nfs4_state_protect for write. + * If WRITE can use machine cred but COMMIT cannot, make sure all writes + * that use machine cred use NFS_FILE_SYNC. + */ +static inline void +nfs4_state_protect_write(struct nfs_client *clp, struct rpc_clnt **clntp, + struct rpc_message *msg, struct nfs_write_data *wdata) +{ + if (_nfs4_state_protect(clp, NFS_SP4_MACH_CRED_WRITE, clntp, msg) && + !test_bit(NFS_SP4_MACH_CRED_COMMIT, &clp->cl_sp4_flags)) + wdata->args.stable = NFS_FILE_SYNC; } #else /* CONFIG_NFS_v4_1 */ static inline struct nfs4_session *nfs4_get_session(const struct nfs_server *server) @@ -320,6 +344,12 @@ nfs4_state_protect(struct nfs_client *clp, unsigned long sp4_flags, struct rpc_clnt **clntp, struct rpc_message *msg) { } + +static inline void +nfs4_state_protect_write(struct nfs_client *clp, struct rpc_clnt **clntp, + struct rpc_message *msg, struct nfs_write_data *wdata) +{ +} #endif /* CONFIG_NFS_V4_1 */ extern const struct nfs4_minor_version_ops *nfs_v4_minor_ops[]; @@ -455,6 +485,8 @@ static inline bool nfs4_valid_open_stateid(const struct nfs4_state *state) #define nfs4_close_state(a, b) do { } while (0) #define nfs4_close_sync(a, b) do { } while (0) +#define nfs4_state_protect(a, b, c, d) do { } while (0) +#define nfs4_state_protect_write(a, b, c, d) do { } while (0) #endif /* CONFIG_NFS_V4 */ #endif /* __LINUX_FS_NFS_NFS4_FS.H */ diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 4818a38..e3cdfe3 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -6223,6 +6223,16 @@ static int nfs4_sp4_select_mode(struct nfs_client *clp, dfprintk(MOUNT, " stateid mode enabled\n"); set_bit(NFS_SP4_MACH_CRED_STATEID, &clp->cl_sp4_flags); } + + if (test_bit(OP_WRITE, sp->allow.u.longs)) { + dfprintk(MOUNT, " write mode enabled\n"); + set_bit(NFS_SP4_MACH_CRED_WRITE, &clp->cl_sp4_flags); + } + + if (test_bit(OP_COMMIT, sp->allow.u.longs)) { + dfprintk(MOUNT, " commit mode enabled\n"); + set_bit(NFS_SP4_MACH_CRED_COMMIT, &clp->cl_sp4_flags); + } } return 0; diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 379450c..40979e8 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -1022,6 +1022,9 @@ int nfs_initiate_write(struct rpc_clnt *clnt, data->args.count, (unsigned long long)data->args.offset); + nfs4_state_protect_write(NFS_SERVER(inode)->nfs_client, + &task_setup_data.rpc_client, &msg, data); + task = rpc_run_task(&task_setup_data); if (IS_ERR(task)) { ret = PTR_ERR(task); @@ -1488,6 +1491,9 @@ int nfs_initiate_commit(struct rpc_clnt *clnt, struct nfs_commit_data *data, dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid); + nfs4_state_protect(NFS_SERVER(data->inode)->nfs_client, + NFS_SP4_MACH_CRED_COMMIT, &task_setup_data.rpc_client, &msg); + task = rpc_run_task(&task_setup_data); if (IS_ERR(task)) return PTR_ERR(task); diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index 1795865..e8ff178 100644 --- a/include/linux/nfs_fs_sb.h +++ b/include/linux/nfs_fs_sb.h @@ -97,6 +97,8 @@ struct nfs_client { #define NFS_SP4_MACH_CRED_CLEANUP 2 /* CLOSE and LOCKU */ #define NFS_SP4_MACH_CRED_SECINFO 3 /* SECINFO and SECINFO_NO_NAME */ #define NFS_SP4_MACH_CRED_STATEID 4 /* TEST_STATEID and FREE_STATEID */ +#define NFS_SP4_MACH_CRED_WRITE 5 /* WRITE */ +#define NFS_SP4_MACH_CRED_COMMIT 6 /* COMMIT */ #endif /* CONFIG_NFS_V4 */ #ifdef CONFIG_NFS_FSCACHE -- 2.7.4