diff options
| -rw-r--r-- | fs/nfs/callback.c | 31 | ||||
| -rw-r--r-- | fs/nfs/callback.h | 1 | ||||
| -rw-r--r-- | fs/nfs/nfs4state.c | 6 | ||||
| -rw-r--r-- | include/linux/sunrpc/svc_xprt.h | 1 | ||||
| -rw-r--r-- | net/sunrpc/svcsock.c | 4 |
5 files changed, 42 insertions, 1 deletions
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index 0e9fae831dfa..c0b05497972b 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c | |||
| @@ -137,6 +137,33 @@ out_err: | |||
| 137 | 137 | ||
| 138 | #if defined(CONFIG_NFS_V4_1) | 138 | #if defined(CONFIG_NFS_V4_1) |
| 139 | /* | 139 | /* |
| 140 | * * CB_SEQUENCE operations will fail until the callback sessionid is set. | ||
| 141 | * */ | ||
| 142 | int nfs4_set_callback_sessionid(struct nfs_client *clp) | ||
| 143 | { | ||
| 144 | struct svc_serv *serv = clp->cl_rpcclient->cl_xprt->bc_serv; | ||
| 145 | struct nfs4_sessionid *bc_sid; | ||
| 146 | |||
| 147 | if (!serv->bc_xprt) | ||
| 148 | return -EINVAL; | ||
| 149 | |||
| 150 | /* on success freed in xprt_free */ | ||
| 151 | bc_sid = kmalloc(sizeof(struct nfs4_sessionid), GFP_KERNEL); | ||
| 152 | if (!bc_sid) | ||
| 153 | return -ENOMEM; | ||
| 154 | memcpy(bc_sid->data, &clp->cl_session->sess_id.data, | ||
| 155 | NFS4_MAX_SESSIONID_LEN); | ||
| 156 | spin_lock_bh(&serv->sv_cb_lock); | ||
| 157 | serv->bc_xprt->xpt_bc_sid = bc_sid; | ||
| 158 | spin_unlock_bh(&serv->sv_cb_lock); | ||
| 159 | dprintk("%s set xpt_bc_sid=%u:%u:%u:%u for bc_xprt %p\n", __func__, | ||
| 160 | ((u32 *)bc_sid->data)[0], ((u32 *)bc_sid->data)[1], | ||
| 161 | ((u32 *)bc_sid->data)[2], ((u32 *)bc_sid->data)[3], | ||
| 162 | serv->bc_xprt); | ||
| 163 | return 0; | ||
| 164 | } | ||
| 165 | |||
| 166 | /* | ||
| 140 | * The callback service for NFSv4.1 callbacks | 167 | * The callback service for NFSv4.1 callbacks |
| 141 | */ | 168 | */ |
| 142 | static int | 169 | static int |
| @@ -241,6 +268,10 @@ static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt, | |||
| 241 | struct nfs_callback_data *cb_info) | 268 | struct nfs_callback_data *cb_info) |
| 242 | { | 269 | { |
| 243 | } | 270 | } |
| 271 | int nfs4_set_callback_sessionid(struct nfs_client *clp) | ||
| 272 | { | ||
| 273 | return 0; | ||
| 274 | } | ||
| 244 | #endif /* CONFIG_NFS_V4_1 */ | 275 | #endif /* CONFIG_NFS_V4_1 */ |
| 245 | 276 | ||
| 246 | /* | 277 | /* |
diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h index 85a7cfd1b8dd..58d61a8ce8b9 100644 --- a/fs/nfs/callback.h +++ b/fs/nfs/callback.h | |||
| @@ -137,6 +137,7 @@ extern int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt); | |||
| 137 | extern void nfs_callback_down(int minorversion); | 137 | extern void nfs_callback_down(int minorversion); |
| 138 | extern int nfs4_validate_delegation_stateid(struct nfs_delegation *delegation, | 138 | extern int nfs4_validate_delegation_stateid(struct nfs_delegation *delegation, |
| 139 | const nfs4_stateid *stateid); | 139 | const nfs4_stateid *stateid); |
| 140 | extern int nfs4_set_callback_sessionid(struct nfs_client *clp); | ||
| 140 | #endif /* CONFIG_NFS_V4 */ | 141 | #endif /* CONFIG_NFS_V4 */ |
| 141 | /* | 142 | /* |
| 142 | * nfs41: Callbacks are expected to not cause substantial latency, | 143 | * nfs41: Callbacks are expected to not cause substantial latency, |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index f575a3126737..485e95e8fd62 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
| @@ -192,6 +192,12 @@ int nfs41_init_clientid(struct nfs_client *clp, struct rpc_cred *cred) | |||
| 192 | status = nfs4_proc_create_session(clp); | 192 | status = nfs4_proc_create_session(clp); |
| 193 | if (status != 0) | 193 | if (status != 0) |
| 194 | goto out; | 194 | goto out; |
| 195 | status = nfs4_set_callback_sessionid(clp); | ||
| 196 | if (status != 0) { | ||
| 197 | printk(KERN_WARNING "Sessionid not set. No callback service\n"); | ||
| 198 | nfs_callback_down(1); | ||
| 199 | status = 0; | ||
| 200 | } | ||
| 195 | nfs41_setup_state_renewal(clp); | 201 | nfs41_setup_state_renewal(clp); |
| 196 | nfs_mark_client_ready(clp, NFS_CS_READY); | 202 | nfs_mark_client_ready(clp, NFS_CS_READY); |
| 197 | out: | 203 | out: |
diff --git a/include/linux/sunrpc/svc_xprt.h b/include/linux/sunrpc/svc_xprt.h index aea0d438e3c7..357da5e0daa3 100644 --- a/include/linux/sunrpc/svc_xprt.h +++ b/include/linux/sunrpc/svc_xprt.h | |||
| @@ -78,6 +78,7 @@ struct svc_xprt { | |||
| 78 | size_t xpt_remotelen; /* length of address */ | 78 | size_t xpt_remotelen; /* length of address */ |
| 79 | struct rpc_wait_queue xpt_bc_pending; /* backchannel wait queue */ | 79 | struct rpc_wait_queue xpt_bc_pending; /* backchannel wait queue */ |
| 80 | struct list_head xpt_users; /* callbacks on free */ | 80 | struct list_head xpt_users; /* callbacks on free */ |
| 81 | void *xpt_bc_sid; /* back channel session ID */ | ||
| 81 | 82 | ||
| 82 | struct net *xpt_net; | 83 | struct net *xpt_net; |
| 83 | }; | 84 | }; |
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index e6b66d81115e..db3013e4aa04 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
| @@ -1605,7 +1605,9 @@ static struct svc_xprt *svc_bc_create_socket(struct svc_serv *serv, | |||
| 1605 | */ | 1605 | */ |
| 1606 | static void svc_bc_sock_free(struct svc_xprt *xprt) | 1606 | static void svc_bc_sock_free(struct svc_xprt *xprt) |
| 1607 | { | 1607 | { |
| 1608 | if (xprt) | 1608 | if (xprt) { |
| 1609 | kfree(xprt->xpt_bc_sid); | ||
| 1609 | kfree(container_of(xprt, struct svc_sock, sk_xprt)); | 1610 | kfree(container_of(xprt, struct svc_sock, sk_xprt)); |
| 1611 | } | ||
| 1610 | } | 1612 | } |
| 1611 | #endif /* CONFIG_NFS_V4_1 */ | 1613 | #endif /* CONFIG_NFS_V4_1 */ |
