diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2009-06-17 20:59:58 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2009-06-17 20:59:58 -0400 |
commit | 301933a0acfdec837fd8b4884093b3f0fff01d8a (patch) | |
tree | 1f2412a30d710493179b1b3743cf30302872df15 /net/sunrpc/svc.c | |
parent | 3fe0344faf7fdcb158bd5c1a9aec960a8d70c8e8 (diff) | |
parent | 68f3f90133d56e0c38f04f991e662c2b21592b31 (diff) |
Merge commit 'linux-pnfs/nfs41-for-2.6.31' into nfsv41-for-2.6.31
Diffstat (limited to 'net/sunrpc/svc.c')
-rw-r--r-- | net/sunrpc/svc.c | 134 |
1 files changed, 104 insertions, 30 deletions
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index 5ed8931dfe98..952f206ff307 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/sunrpc/stats.h> | 25 | #include <linux/sunrpc/stats.h> |
26 | #include <linux/sunrpc/svcsock.h> | 26 | #include <linux/sunrpc/svcsock.h> |
27 | #include <linux/sunrpc/clnt.h> | 27 | #include <linux/sunrpc/clnt.h> |
28 | #include <linux/sunrpc/bc_xprt.h> | ||
28 | 29 | ||
29 | #define RPCDBG_FACILITY RPCDBG_SVCDSP | 30 | #define RPCDBG_FACILITY RPCDBG_SVCDSP |
30 | 31 | ||
@@ -486,6 +487,10 @@ svc_destroy(struct svc_serv *serv) | |||
486 | if (svc_serv_is_pooled(serv)) | 487 | if (svc_serv_is_pooled(serv)) |
487 | svc_pool_map_put(); | 488 | svc_pool_map_put(); |
488 | 489 | ||
490 | #if defined(CONFIG_NFS_V4_1) | ||
491 | svc_sock_destroy(serv->bc_xprt); | ||
492 | #endif /* CONFIG_NFS_V4_1 */ | ||
493 | |||
489 | svc_unregister(serv); | 494 | svc_unregister(serv); |
490 | kfree(serv->sv_pools); | 495 | kfree(serv->sv_pools); |
491 | kfree(serv); | 496 | kfree(serv); |
@@ -970,20 +975,18 @@ svc_printk(struct svc_rqst *rqstp, const char *fmt, ...) | |||
970 | } | 975 | } |
971 | 976 | ||
972 | /* | 977 | /* |
973 | * Process the RPC request. | 978 | * Common routine for processing the RPC request. |
974 | */ | 979 | */ |
975 | int | 980 | static int |
976 | svc_process(struct svc_rqst *rqstp) | 981 | svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv) |
977 | { | 982 | { |
978 | struct svc_program *progp; | 983 | struct svc_program *progp; |
979 | struct svc_version *versp = NULL; /* compiler food */ | 984 | struct svc_version *versp = NULL; /* compiler food */ |
980 | struct svc_procedure *procp = NULL; | 985 | struct svc_procedure *procp = NULL; |
981 | struct kvec * argv = &rqstp->rq_arg.head[0]; | ||
982 | struct kvec * resv = &rqstp->rq_res.head[0]; | ||
983 | struct svc_serv *serv = rqstp->rq_server; | 986 | struct svc_serv *serv = rqstp->rq_server; |
984 | kxdrproc_t xdr; | 987 | kxdrproc_t xdr; |
985 | __be32 *statp; | 988 | __be32 *statp; |
986 | u32 dir, prog, vers, proc; | 989 | u32 prog, vers, proc; |
987 | __be32 auth_stat, rpc_stat; | 990 | __be32 auth_stat, rpc_stat; |
988 | int auth_res; | 991 | int auth_res; |
989 | __be32 *reply_statp; | 992 | __be32 *reply_statp; |
@@ -993,19 +996,6 @@ svc_process(struct svc_rqst *rqstp) | |||
993 | if (argv->iov_len < 6*4) | 996 | if (argv->iov_len < 6*4) |
994 | goto err_short_len; | 997 | goto err_short_len; |
995 | 998 | ||
996 | /* setup response xdr_buf. | ||
997 | * Initially it has just one page | ||
998 | */ | ||
999 | rqstp->rq_resused = 1; | ||
1000 | resv->iov_base = page_address(rqstp->rq_respages[0]); | ||
1001 | resv->iov_len = 0; | ||
1002 | rqstp->rq_res.pages = rqstp->rq_respages + 1; | ||
1003 | rqstp->rq_res.len = 0; | ||
1004 | rqstp->rq_res.page_base = 0; | ||
1005 | rqstp->rq_res.page_len = 0; | ||
1006 | rqstp->rq_res.buflen = PAGE_SIZE; | ||
1007 | rqstp->rq_res.tail[0].iov_base = NULL; | ||
1008 | rqstp->rq_res.tail[0].iov_len = 0; | ||
1009 | /* Will be turned off only in gss privacy case: */ | 999 | /* Will be turned off only in gss privacy case: */ |
1010 | rqstp->rq_splice_ok = 1; | 1000 | rqstp->rq_splice_ok = 1; |
1011 | /* Will be turned off only when NFSv4 Sessions are used */ | 1001 | /* Will be turned off only when NFSv4 Sessions are used */ |
@@ -1014,17 +1004,13 @@ svc_process(struct svc_rqst *rqstp) | |||
1014 | /* Setup reply header */ | 1004 | /* Setup reply header */ |
1015 | rqstp->rq_xprt->xpt_ops->xpo_prep_reply_hdr(rqstp); | 1005 | rqstp->rq_xprt->xpt_ops->xpo_prep_reply_hdr(rqstp); |
1016 | 1006 | ||
1017 | rqstp->rq_xid = svc_getu32(argv); | ||
1018 | svc_putu32(resv, rqstp->rq_xid); | 1007 | svc_putu32(resv, rqstp->rq_xid); |
1019 | 1008 | ||
1020 | dir = svc_getnl(argv); | ||
1021 | vers = svc_getnl(argv); | 1009 | vers = svc_getnl(argv); |
1022 | 1010 | ||
1023 | /* First words of reply: */ | 1011 | /* First words of reply: */ |
1024 | svc_putnl(resv, 1); /* REPLY */ | 1012 | svc_putnl(resv, 1); /* REPLY */ |
1025 | 1013 | ||
1026 | if (dir != 0) /* direction != CALL */ | ||
1027 | goto err_bad_dir; | ||
1028 | if (vers != 2) /* RPC version number */ | 1014 | if (vers != 2) /* RPC version number */ |
1029 | goto err_bad_rpc; | 1015 | goto err_bad_rpc; |
1030 | 1016 | ||
@@ -1147,7 +1133,7 @@ svc_process(struct svc_rqst *rqstp) | |||
1147 | sendit: | 1133 | sendit: |
1148 | if (svc_authorise(rqstp)) | 1134 | if (svc_authorise(rqstp)) |
1149 | goto dropit; | 1135 | goto dropit; |
1150 | return svc_send(rqstp); | 1136 | return 1; /* Caller can now send it */ |
1151 | 1137 | ||
1152 | dropit: | 1138 | dropit: |
1153 | svc_authorise(rqstp); /* doesn't hurt to call this twice */ | 1139 | svc_authorise(rqstp); /* doesn't hurt to call this twice */ |
@@ -1161,12 +1147,6 @@ err_short_len: | |||
1161 | 1147 | ||
1162 | goto dropit; /* drop request */ | 1148 | goto dropit; /* drop request */ |
1163 | 1149 | ||
1164 | err_bad_dir: | ||
1165 | svc_printk(rqstp, "bad direction %d, dropping request\n", dir); | ||
1166 | |||
1167 | serv->sv_stats->rpcbadfmt++; | ||
1168 | goto dropit; /* drop request */ | ||
1169 | |||
1170 | err_bad_rpc: | 1150 | err_bad_rpc: |
1171 | serv->sv_stats->rpcbadfmt++; | 1151 | serv->sv_stats->rpcbadfmt++; |
1172 | svc_putnl(resv, 1); /* REJECT */ | 1152 | svc_putnl(resv, 1); /* REJECT */ |
@@ -1220,6 +1200,100 @@ err_bad: | |||
1220 | EXPORT_SYMBOL_GPL(svc_process); | 1200 | EXPORT_SYMBOL_GPL(svc_process); |
1221 | 1201 | ||
1222 | /* | 1202 | /* |
1203 | * Process the RPC request. | ||
1204 | */ | ||
1205 | int | ||
1206 | svc_process(struct svc_rqst *rqstp) | ||
1207 | { | ||
1208 | struct kvec *argv = &rqstp->rq_arg.head[0]; | ||
1209 | struct kvec *resv = &rqstp->rq_res.head[0]; | ||
1210 | struct svc_serv *serv = rqstp->rq_server; | ||
1211 | u32 dir; | ||
1212 | int error; | ||
1213 | |||
1214 | /* | ||
1215 | * Setup response xdr_buf. | ||
1216 | * Initially it has just one page | ||
1217 | */ | ||
1218 | rqstp->rq_resused = 1; | ||
1219 | resv->iov_base = page_address(rqstp->rq_respages[0]); | ||
1220 | resv->iov_len = 0; | ||
1221 | rqstp->rq_res.pages = rqstp->rq_respages + 1; | ||
1222 | rqstp->rq_res.len = 0; | ||
1223 | rqstp->rq_res.page_base = 0; | ||
1224 | rqstp->rq_res.page_len = 0; | ||
1225 | rqstp->rq_res.buflen = PAGE_SIZE; | ||
1226 | rqstp->rq_res.tail[0].iov_base = NULL; | ||
1227 | rqstp->rq_res.tail[0].iov_len = 0; | ||
1228 | |||
1229 | rqstp->rq_xid = svc_getu32(argv); | ||
1230 | |||
1231 | dir = svc_getnl(argv); | ||
1232 | if (dir != 0) { | ||
1233 | /* direction != CALL */ | ||
1234 | svc_printk(rqstp, "bad direction %d, dropping request\n", dir); | ||
1235 | serv->sv_stats->rpcbadfmt++; | ||
1236 | svc_drop(rqstp); | ||
1237 | return 0; | ||
1238 | } | ||
1239 | |||
1240 | error = svc_process_common(rqstp, argv, resv); | ||
1241 | if (error <= 0) | ||
1242 | return error; | ||
1243 | |||
1244 | return svc_send(rqstp); | ||
1245 | } | ||
1246 | |||
1247 | #if defined(CONFIG_NFS_V4_1) | ||
1248 | /* | ||
1249 | * Process a backchannel RPC request that arrived over an existing | ||
1250 | * outbound connection | ||
1251 | */ | ||
1252 | int | ||
1253 | bc_svc_process(struct svc_serv *serv, struct rpc_rqst *req, | ||
1254 | struct svc_rqst *rqstp) | ||
1255 | { | ||
1256 | struct kvec *argv = &rqstp->rq_arg.head[0]; | ||
1257 | struct kvec *resv = &rqstp->rq_res.head[0]; | ||
1258 | int error; | ||
1259 | |||
1260 | /* Build the svc_rqst used by the common processing routine */ | ||
1261 | rqstp->rq_xprt = serv->bc_xprt; | ||
1262 | rqstp->rq_xid = req->rq_xid; | ||
1263 | rqstp->rq_prot = req->rq_xprt->prot; | ||
1264 | rqstp->rq_server = serv; | ||
1265 | |||
1266 | rqstp->rq_addrlen = sizeof(req->rq_xprt->addr); | ||
1267 | memcpy(&rqstp->rq_addr, &req->rq_xprt->addr, rqstp->rq_addrlen); | ||
1268 | memcpy(&rqstp->rq_arg, &req->rq_rcv_buf, sizeof(rqstp->rq_arg)); | ||
1269 | memcpy(&rqstp->rq_res, &req->rq_snd_buf, sizeof(rqstp->rq_res)); | ||
1270 | |||
1271 | /* reset result send buffer "put" position */ | ||
1272 | resv->iov_len = 0; | ||
1273 | |||
1274 | if (rqstp->rq_prot != IPPROTO_TCP) { | ||
1275 | printk(KERN_ERR "No support for Non-TCP transports!\n"); | ||
1276 | BUG(); | ||
1277 | } | ||
1278 | |||
1279 | /* | ||
1280 | * Skip the next two words because they've already been | ||
1281 | * processed in the trasport | ||
1282 | */ | ||
1283 | svc_getu32(argv); /* XID */ | ||
1284 | svc_getnl(argv); /* CALLDIR */ | ||
1285 | |||
1286 | error = svc_process_common(rqstp, argv, resv); | ||
1287 | if (error <= 0) | ||
1288 | return error; | ||
1289 | |||
1290 | memcpy(&req->rq_snd_buf, &rqstp->rq_res, sizeof(req->rq_snd_buf)); | ||
1291 | return bc_send(req); | ||
1292 | } | ||
1293 | EXPORT_SYMBOL(bc_svc_process); | ||
1294 | #endif /* CONFIG_NFS_V4_1 */ | ||
1295 | |||
1296 | /* | ||
1223 | * Return (transport-specific) limit on the rpc payload. | 1297 | * Return (transport-specific) limit on the rpc payload. |
1224 | */ | 1298 | */ |
1225 | u32 svc_max_payload(const struct svc_rqst *rqstp) | 1299 | u32 svc_max_payload(const struct svc_rqst *rqstp) |