linux/fs/nfs/mount_clnt.c
<<
>>
Prefs
   1/*
   2 * In-kernel MOUNT protocol client
   3 *
   4 * Copyright (C) 1997, Olaf Kirch <okir@monad.swb.de>
   5 */
   6
   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>
  13#include <linux/in.h>
  14#include <linux/sunrpc/clnt.h>
  15#include <linux/sunrpc/sched.h>
  16#include <linux/nfs_fs.h>
  17
  18#ifdef RPC_DEBUG
  19# define NFSDBG_FACILITY        NFSDBG_MOUNT
  20#endif
  21
  22static struct rpc_program       mnt_program;
  23
  24struct mnt_fhstatus {
  25        u32 status;
  26        struct nfs_fh *fh;
  27};
  28
  29/**
  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
  38 *
  39 * Uses default timeout parameters specified by underlying transport.
  40 */
  41int nfs_mount(struct sockaddr *addr, size_t len, char *hostname, char *path,
  42              int version, int protocol, struct nfs_fh *fh)
  43{
  44        struct mnt_fhstatus     result = {
  45                .fh             = fh
  46        };
  47        struct rpc_message msg  = {
  48                .rpc_argp       = path,
  49                .rpc_resp       = &result,
  50        };
  51        struct rpc_create_args args = {
  52                .protocol       = protocol,
  53                .address        = addr,
  54                .addrsize       = len,
  55                .servername     = hostname,
  56                .program        = &mnt_program,
  57                .version        = version,
  58                .authflavor     = RPC_AUTH_UNIX,
  59                .flags          = 0,
  60        };
  61        struct rpc_clnt         *mnt_clnt;
  62        int                     status;
  63
  64        dprintk("NFS: sending MNT request for %s:%s\n",
  65                (hostname ? hostname : "server"), path);
  66
  67        mnt_clnt = rpc_create(&args);
  68        if (IS_ERR(mnt_clnt))
  69                goto out_clnt_err;
  70
  71        if (version == NFS_MNT3_VERSION)
  72                msg.rpc_proc = &mnt_clnt->cl_procinfo[MOUNTPROC3_MNT];
  73        else
  74                msg.rpc_proc = &mnt_clnt->cl_procinfo[MNTPROC_MNT];
  75
  76        status = rpc_call_sync(mnt_clnt, &msg, 0);
  77        rpc_shutdown_client(mnt_clnt);
  78
  79        if (status < 0)
  80                goto out_call_err;
  81        if (result.status != 0)
  82                goto out_mnt_err;
  83
  84        dprintk("NFS: MNT request succeeded\n");
  85        status = 0;
  86
  87out:
  88        return status;
  89
  90out_clnt_err:
  91        status = PTR_ERR(mnt_clnt);
  92        dprintk("NFS: failed to create RPC client, status=%d\n", status);
  93        goto out;
  94
  95out_call_err:
  96        dprintk("NFS: failed to start MNT request, status=%d\n", status);
  97        goto out;
  98
  99out_mnt_err:
 100        dprintk("NFS: MNT server returned result %d\n", result.status);
 101        status = -EACCES;
 102        goto out;
 103}
 104
 105/*
 106 * XDR encode/decode functions for MOUNT
 107 */
 108static int xdr_encode_dirpath(struct rpc_rqst *req, __be32 *p,
 109                              const char *path)
 110{
 111        p = xdr_encode_string(p, path);
 112
 113        req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
 114        return 0;
 115}
 116
 117static int xdr_decode_fhstatus(struct rpc_rqst *req, __be32 *p,
 118                               struct mnt_fhstatus *res)
 119{
 120        struct nfs_fh *fh = res->fh;
 121
 122        if ((res->status = ntohl(*p++)) == 0) {
 123                fh->size = NFS2_FHSIZE;
 124                memcpy(fh->data, p, NFS2_FHSIZE);
 125        }
 126        return 0;
 127}
 128
 129static int xdr_decode_fhstatus3(struct rpc_rqst *req, __be32 *p,
 130                                struct mnt_fhstatus *res)
 131{
 132        struct nfs_fh *fh = res->fh;
 133
 134        if ((res->status = ntohl(*p++)) == 0) {
 135                int size = ntohl(*p++);
 136                if (size <= NFS3_FHSIZE) {
 137                        fh->size = size;
 138                        memcpy(fh->data, p, size);
 139                } else
 140                        res->status = -EBADHANDLE;
 141        }
 142        return 0;
 143}
 144
 145#define MNT_dirpath_sz          (1 + 256)
 146#define MNT_fhstatus_sz         (1 + 8)
 147#define MNT_fhstatus3_sz        (1 + 16)
 148
 149static struct rpc_procinfo mnt_procedures[] = {
 150        [MNTPROC_MNT] = {
 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,
 157                .p_name         = "MOUNT",
 158        },
 159};
 160
 161static struct rpc_procinfo mnt3_procedures[] = {
 162        [MOUNTPROC3_MNT] = {
 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,
 169                .p_name         = "MOUNT",
 170        },
 171};
 172
 173
 174static struct rpc_version mnt_version1 = {
 175        .number         = 1,
 176        .nrprocs        = 2,
 177        .procs          = mnt_procedures,
 178};
 179
 180static struct rpc_version mnt_version3 = {
 181        .number         = 3,
 182        .nrprocs        = 2,
 183        .procs          = mnt3_procedures,
 184};
 185
 186static struct rpc_version *mnt_version[] = {
 187        NULL,
 188        &mnt_version1,
 189        NULL,
 190        &mnt_version3,
 191};
 192
 193static struct rpc_stat mnt_stats;
 194
 195static struct rpc_program mnt_program = {
 196        .name           = "mount",
 197        .number         = NFS_MNT_PROGRAM,
 198        .nrvers         = ARRAY_SIZE(mnt_version),
 199        .version        = mnt_version,
 200        .stats          = &mnt_stats,
 201};
 202
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.