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/sunrpc/clnt.h>
17 #include <linux/sunrpc/sched.h>
18 #include <linux/nfs_fs.h>
21 # define NFSDBG_FACILITY NFSDBG_ROOT
25 #define MOUNT_PROGRAM 100005
26 #define MOUNT_VERSION 1
31 static struct rpc_clnt
* mnt_create(struct sockaddr_in
*, int, int);
32 static struct rpc_program mnt_program
;
40 * Obtain an NFS file handle for the given host and path
43 nfsroot_mount(struct sockaddr_in
*addr
, char *path
, struct nfs_fh
*fh
,
44 int version
, int protocol
)
46 struct rpc_clnt
*mnt_clnt
;
47 struct mnt_fhstatus result
= {
50 struct rpc_message msg
= {
56 dprintk("NFS: nfs_mount(%08x:%s)\n",
57 (unsigned)ntohl(addr
->sin_addr
.s_addr
), path
);
59 mnt_clnt
= mnt_create(addr
, version
, protocol
);
61 return PTR_ERR(mnt_clnt
);
63 if (version
== NFS_MNT3_VERSION
)
64 msg
.rpc_proc
= &mnt_clnt
->cl_procinfo
[MOUNTPROC3_MNT
];
66 msg
.rpc_proc
= &mnt_clnt
->cl_procinfo
[MNTPROC_MNT
];
68 status
= rpc_call_sync(mnt_clnt
, &msg
, 0);
69 rpc_shutdown_client(mnt_clnt
);
70 return status
< 0? status
: (result
.status
? -EACCES
: 0);
73 static struct rpc_clnt
*mnt_create(struct sockaddr_in
*srvaddr
, int version
,
76 struct rpc_create_args args
= {
78 .address
= (struct sockaddr
*)srvaddr
,
79 .addrsize
= sizeof(*srvaddr
),
80 .program
= &mnt_program
,
82 .authflavor
= RPC_AUTH_UNIX
,
83 .flags
= RPC_CLNT_CREATE_INTR
,
86 return rpc_create(&args
);
90 * XDR encode/decode functions for MOUNT
93 xdr_encode_dirpath(struct rpc_rqst
*req
, __be32
*p
, const char *path
)
95 p
= xdr_encode_string(p
, path
);
97 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
102 xdr_decode_fhstatus(struct rpc_rqst
*req
, __be32
*p
, struct mnt_fhstatus
*res
)
104 struct nfs_fh
*fh
= res
->fh
;
106 if ((res
->status
= ntohl(*p
++)) == 0) {
107 fh
->size
= NFS2_FHSIZE
;
108 memcpy(fh
->data
, p
, NFS2_FHSIZE
);
114 xdr_decode_fhstatus3(struct rpc_rqst
*req
, __be32
*p
, struct mnt_fhstatus
*res
)
116 struct nfs_fh
*fh
= res
->fh
;
118 if ((res
->status
= ntohl(*p
++)) == 0) {
119 int size
= ntohl(*p
++);
120 if (size
<= NFS3_FHSIZE
) {
122 memcpy(fh
->data
, p
, size
);
124 res
->status
= -EBADHANDLE
;
129 #define MNT_dirpath_sz (1 + 256)
130 #define MNT_fhstatus_sz (1 + 8)
131 #define MNT_fhstatus3_sz (1 + 16)
133 static struct rpc_procinfo mnt_procedures
[] = {
135 .p_proc
= MNTPROC_MNT
,
136 .p_encode
= (kxdrproc_t
) xdr_encode_dirpath
,
137 .p_decode
= (kxdrproc_t
) xdr_decode_fhstatus
,
138 .p_arglen
= MNT_dirpath_sz
,
139 .p_replen
= MNT_fhstatus_sz
,
140 .p_statidx
= MNTPROC_MNT
,
145 static struct rpc_procinfo mnt3_procedures
[] = {
147 .p_proc
= MOUNTPROC3_MNT
,
148 .p_encode
= (kxdrproc_t
) xdr_encode_dirpath
,
149 .p_decode
= (kxdrproc_t
) xdr_decode_fhstatus3
,
150 .p_arglen
= MNT_dirpath_sz
,
151 .p_replen
= MNT_fhstatus3_sz
,
152 .p_statidx
= MOUNTPROC3_MNT
,
158 static struct rpc_version mnt_version1
= {
161 .procs
= mnt_procedures
164 static struct rpc_version mnt_version3
= {
167 .procs
= mnt3_procedures
170 static struct rpc_version
* mnt_version
[] = {
177 static struct rpc_stat mnt_stats
;
179 static struct rpc_program mnt_program
= {
181 .number
= NFS_MNT_PROGRAM
,
182 .nrvers
= ARRAY_SIZE(mnt_version
),
183 .version
= mnt_version
,