2 * linux/fs/nfs/mount_clnt.c
4 * MOUNT client to support NFSroot.
6 * Copyright (C) 1997, Olaf Kirch <okir@monad.swb.de>
9 #include <linux/types.h>
10 #include <linux/socket.h>
11 #include <linux/kernel.h>
12 #include <linux/errno.h>
13 #include <linux/uio.h>
14 #include <linux/net.h>
16 #include <linux/inet.h>
17 #include <linux/sunrpc/clnt.h>
18 #include <linux/sunrpc/xprt.h>
19 #include <linux/sunrpc/sched.h>
20 #include <linux/nfs_fs.h>
23 # define NFSDBG_FACILITY NFSDBG_ROOT
27 #define MOUNT_PROGRAM 100005
28 #define MOUNT_VERSION 1
33 static int nfs_gen_mount(struct sockaddr_in
*,
34 char *, struct nfs_fh
*, int);
35 static struct rpc_clnt
* mnt_create(char *, struct sockaddr_in
*, int);
36 extern struct rpc_program mnt_program
;
44 * Obtain an NFS file handle for the given host and path
47 nfs_mount(struct sockaddr_in
*addr
, char *path
, struct nfs_fh
*fh
)
49 return nfs_gen_mount(addr
, path
, fh
, NFS_MNT_VERSION
);
53 nfs3_mount(struct sockaddr_in
*addr
, char *path
, struct nfs_fh
*fh
)
55 return nfs_gen_mount(addr
, path
, fh
, NFS_MNT3_VERSION
);
59 nfs_gen_mount(struct sockaddr_in
*addr
, char *path
, struct nfs_fh
*fh
, int version
)
61 struct rpc_clnt
*mnt_clnt
;
62 struct mnt_fhstatus result
= { 0, fh
};
67 dprintk("NFS: nfs_mount(%08x:%s)\n",
68 (unsigned)ntohl(addr
->sin_addr
.s_addr
), path
);
70 strcpy(hostname
, in_ntoa(addr
->sin_addr
.s_addr
));
71 if (!(mnt_clnt
= mnt_create(hostname
, addr
, version
)))
74 call
= (version
== 3) ? MOUNTPROC3_MNT
: MNTPROC_MNT
;
75 status
= rpc_call(mnt_clnt
, call
, path
, &result
, 0);
76 return status
< 0? status
: (result
.status
? -EACCES
: 0);
79 static struct rpc_clnt
*
80 mnt_create(char *hostname
, struct sockaddr_in
*srvaddr
, int version
)
82 struct rpc_xprt
*xprt
;
83 struct rpc_clnt
*clnt
;
85 if (!(xprt
= xprt_create_proto(IPPROTO_UDP
, srvaddr
, NULL
)))
88 clnt
= rpc_create_client(xprt
, hostname
,
89 &mnt_program
, version
,
94 clnt
->cl_softrtry
= 1;
103 * XDR encode/decode functions for MOUNT
106 xdr_error(struct rpc_rqst
*req
, u32
*p
, void *dummy
)
112 xdr_encode_dirpath(struct rpc_rqst
*req
, u32
*p
, const char *path
)
114 p
= xdr_encode_string(p
, path
);
116 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
121 xdr_decode_fhstatus(struct rpc_rqst
*req
, u32
*p
, struct mnt_fhstatus
*res
)
123 struct nfs_fh
*fh
= res
->fh
;
125 memset((void *)fh
, 0, sizeof(*fh
));
126 if ((res
->status
= ntohl(*p
++)) == 0) {
127 fh
->size
= NFS2_FHSIZE
;
128 memcpy(fh
->data
, p
, NFS2_FHSIZE
);
134 xdr_decode_fhstatus3(struct rpc_rqst
*req
, u32
*p
, struct mnt_fhstatus
*res
)
136 struct nfs_fh
*fh
= res
->fh
;
138 memset((void *)fh
, 0, sizeof(*fh
));
139 if ((res
->status
= ntohl(*p
++)) == 0) {
140 int size
= ntohl(*p
++);
141 if (size
<= NFS3_FHSIZE
) {
143 memcpy(fh
->data
, p
, size
);
145 res
->status
= -EBADHANDLE
;
150 #define MNT_dirpath_sz (1 + 256)
151 #define MNT_fhstatus_sz (1 + 8)
153 static struct rpc_procinfo mnt_procedures
[2] = {
155 (kxdrproc_t
) xdr_error
,
156 (kxdrproc_t
) xdr_error
, 0, 0 },
158 (kxdrproc_t
) xdr_encode_dirpath
,
159 (kxdrproc_t
) xdr_decode_fhstatus
,
160 MNT_dirpath_sz
<< 2, 0 },
163 static struct rpc_procinfo mnt3_procedures
[2] = {
165 (kxdrproc_t
) xdr_error
,
166 (kxdrproc_t
) xdr_error
, 0, 0 },
168 (kxdrproc_t
) xdr_encode_dirpath
,
169 (kxdrproc_t
) xdr_decode_fhstatus3
,
170 MNT_dirpath_sz
<< 2, 0 },
174 static struct rpc_version mnt_version1
= {
178 static struct rpc_version mnt_version3
= {
179 3, 2, mnt3_procedures
182 static struct rpc_version
* mnt_version
[] = {
189 static struct rpc_stat mnt_stats
;
191 struct rpc_program mnt_program
= {
194 sizeof(mnt_version
)/sizeof(mnt_version
[0]),