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