2 * In-kernel MOUNT protocol client
4 * Copyright (C) 1997, Olaf Kirch <okir@monad.swb.de>
7 #include <linux/types.h>
8 #include <linux/socket.h>
9 #include <linux/kernel.h>
10 #include <linux/errno.h>
11 #include <linux/uio.h>
12 #include <linux/net.h>
14 #include <linux/sunrpc/clnt.h>
15 #include <linux/sunrpc/sched.h>
16 #include <linux/nfs_fs.h>
19 # define NFSDBG_FACILITY NFSDBG_MOUNT
22 static struct rpc_program mnt_program
;
30 * nfs_mount - Obtain an NFS file handle for the given host and path
31 * @addr: pointer to server's address
32 * @len: size of server's address
33 * @hostname: name of server host, or NULL
34 * @path: pointer to string containing export path to mount
35 * @version: mount version to use for this request
36 * @protocol: transport protocol to use for thie request
37 * @fh: pointer to location to place returned file handle
39 * Uses default timeout parameters specified by underlying transport.
41 int nfs_mount(struct sockaddr
*addr
, size_t len
, char *hostname
, char *path
,
42 int version
, int protocol
, struct nfs_fh
*fh
)
44 struct mnt_fhstatus result
= {
47 struct rpc_message msg
= {
51 struct rpc_create_args args
= {
55 .servername
= hostname
,
56 .program
= &mnt_program
,
58 .authflavor
= RPC_AUTH_UNIX
,
61 struct rpc_clnt
*mnt_clnt
;
64 dprintk("NFS: sending MNT request for %s:%s\n",
65 (hostname
? hostname
: "server"), path
);
67 mnt_clnt
= rpc_create(&args
);
71 if (version
== NFS_MNT3_VERSION
)
72 msg
.rpc_proc
= &mnt_clnt
->cl_procinfo
[MOUNTPROC3_MNT
];
74 msg
.rpc_proc
= &mnt_clnt
->cl_procinfo
[MNTPROC_MNT
];
76 status
= rpc_call_sync(mnt_clnt
, &msg
, 0);
77 rpc_shutdown_client(mnt_clnt
);
81 if (result
.status
!= 0)
84 dprintk("NFS: MNT request succeeded\n");
91 status
= PTR_ERR(mnt_clnt
);
92 dprintk("NFS: failed to create RPC client, status=%d\n", status
);
96 dprintk("NFS: failed to start MNT request, status=%d\n", status
);
100 dprintk("NFS: MNT server returned result %d\n", result
.status
);
106 * XDR encode/decode functions for MOUNT
108 static int xdr_encode_dirpath(struct rpc_rqst
*req
, __be32
*p
,
111 p
= xdr_encode_string(p
, path
);
113 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
117 static int xdr_decode_fhstatus(struct rpc_rqst
*req
, __be32
*p
,
118 struct mnt_fhstatus
*res
)
120 struct nfs_fh
*fh
= res
->fh
;
122 if ((res
->status
= ntohl(*p
++)) == 0) {
123 fh
->size
= NFS2_FHSIZE
;
124 memcpy(fh
->data
, p
, NFS2_FHSIZE
);
129 static int xdr_decode_fhstatus3(struct rpc_rqst
*req
, __be32
*p
,
130 struct mnt_fhstatus
*res
)
132 struct nfs_fh
*fh
= res
->fh
;
134 if ((res
->status
= ntohl(*p
++)) == 0) {
135 int size
= ntohl(*p
++);
136 if (size
<= NFS3_FHSIZE
) {
138 memcpy(fh
->data
, p
, size
);
140 res
->status
= -EBADHANDLE
;
145 #define MNT_dirpath_sz (1 + 256)
146 #define MNT_fhstatus_sz (1 + 8)
147 #define MNT_fhstatus3_sz (1 + 16)
149 static struct rpc_procinfo mnt_procedures
[] = {
151 .p_proc
= MNTPROC_MNT
,
152 .p_encode
= (kxdrproc_t
) xdr_encode_dirpath
,
153 .p_decode
= (kxdrproc_t
) xdr_decode_fhstatus
,
154 .p_arglen
= MNT_dirpath_sz
,
155 .p_replen
= MNT_fhstatus_sz
,
156 .p_statidx
= MNTPROC_MNT
,
161 static struct rpc_procinfo mnt3_procedures
[] = {
163 .p_proc
= MOUNTPROC3_MNT
,
164 .p_encode
= (kxdrproc_t
) xdr_encode_dirpath
,
165 .p_decode
= (kxdrproc_t
) xdr_decode_fhstatus3
,
166 .p_arglen
= MNT_dirpath_sz
,
167 .p_replen
= MNT_fhstatus3_sz
,
168 .p_statidx
= MOUNTPROC3_MNT
,
174 static struct rpc_version mnt_version1
= {
177 .procs
= mnt_procedures
,
180 static struct rpc_version mnt_version3
= {
183 .procs
= mnt3_procedures
,
186 static struct rpc_version
*mnt_version
[] = {
193 static struct rpc_stat mnt_stats
;
195 static struct rpc_program mnt_program
= {
197 .number
= NFS_MNT_PROGRAM
,
198 .nrvers
= ARRAY_SIZE(mnt_version
),
199 .version
= mnt_version
,