OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [nfs/] [nfs3xdr.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * linux/fs/nfs/nfs3xdr.c
3
 *
4
 * XDR functions to encode/decode NFSv3 RPC arguments and results.
5
 *
6
 * Copyright (C) 1996, 1997 Olaf Kirch
7
 */
8
 
9
#include <linux/param.h>
10
#include <linux/sched.h>
11
#include <linux/mm.h>
12
#include <linux/slab.h>
13
#include <linux/utsname.h>
14
#include <linux/errno.h>
15
#include <linux/string.h>
16
#include <linux/in.h>
17
#include <linux/pagemap.h>
18
#include <linux/proc_fs.h>
19
#include <linux/kdev_t.h>
20
#include <linux/sunrpc/clnt.h>
21
#include <linux/nfs.h>
22
#include <linux/nfs3.h>
23
#include <linux/nfs_fs.h>
24
 
25
#define NFSDBG_FACILITY         NFSDBG_XDR
26
 
27
/* Mapping from NFS error code to "errno" error code. */
28
#define errno_NFSERR_IO         EIO
29
 
30
extern int                      nfs_stat_to_errno(int);
31
 
32
/*
33
 * Declare the space requirements for NFS arguments and replies as
34
 * number of 32bit-words
35
 */
36
#define NFS3_fhandle_sz         1+16
37
#define NFS3_fh_sz              NFS3_fhandle_sz /* shorthand */
38
#define NFS3_sattr_sz           15
39
#define NFS3_filename_sz        1+(NFS3_MAXNAMLEN>>2)
40
#define NFS3_path_sz            1+(NFS3_MAXPATHLEN>>2)
41
#define NFS3_fattr_sz           21
42
#define NFS3_wcc_attr_sz                6
43
#define NFS3_pre_op_attr_sz     1+NFS3_wcc_attr_sz
44
#define NFS3_post_op_attr_sz    1+NFS3_fattr_sz
45
#define NFS3_wcc_data_sz                NFS3_pre_op_attr_sz+NFS3_post_op_attr_sz
46
#define NFS3_fsstat_sz          
47
#define NFS3_fsinfo_sz          
48
#define NFS3_pathconf_sz                
49
#define NFS3_entry_sz           NFS3_filename_sz+3
50
 
51
#define NFS3_enc_void_sz        0
52
#define NFS3_sattrargs_sz       NFS3_fh_sz+NFS3_sattr_sz+3
53
#define NFS3_diropargs_sz       NFS3_fh_sz+NFS3_filename_sz
54
#define NFS3_accessargs_sz      NFS3_fh_sz+1
55
#define NFS3_readlinkargs_sz    NFS3_fh_sz
56
#define NFS3_readargs_sz        NFS3_fh_sz+3
57
#define NFS3_writeargs_sz       NFS3_fh_sz+5
58
#define NFS3_createargs_sz      NFS3_diropargs_sz+NFS3_sattr_sz
59
#define NFS3_mkdirargs_sz       NFS3_diropargs_sz+NFS3_sattr_sz
60
#define NFS3_symlinkargs_sz     NFS3_diropargs_sz+NFS3_path_sz+NFS3_sattr_sz
61
#define NFS3_mknodargs_sz       NFS3_diropargs_sz+2+NFS3_sattr_sz
62
#define NFS3_renameargs_sz      NFS3_diropargs_sz+NFS3_diropargs_sz
63
#define NFS3_linkargs_sz                NFS3_fh_sz+NFS3_diropargs_sz
64
#define NFS3_readdirargs_sz     NFS3_fh_sz+2
65
#define NFS3_commitargs_sz      NFS3_fh_sz+3
66
 
67
#define NFS3_dec_void_sz        0
68
#define NFS3_attrstat_sz        1+NFS3_fattr_sz
69
#define NFS3_wccstat_sz         1+NFS3_wcc_data_sz
70
#define NFS3_lookupres_sz       1+NFS3_fh_sz+(2 * NFS3_post_op_attr_sz)
71
#define NFS3_accessres_sz       1+NFS3_post_op_attr_sz+1
72
#define NFS3_readlinkres_sz     1+NFS3_post_op_attr_sz
73
#define NFS3_readres_sz         1+NFS3_post_op_attr_sz+3
74
#define NFS3_writeres_sz        1+NFS3_wcc_data_sz+4
75
#define NFS3_createres_sz       1+NFS3_fh_sz+NFS3_post_op_attr_sz+NFS3_wcc_data_sz
76
#define NFS3_renameres_sz       1+(2 * NFS3_wcc_data_sz)
77
#define NFS3_linkres_sz         1+NFS3_post_op_attr_sz+NFS3_wcc_data_sz
78
#define NFS3_readdirres_sz      1+NFS3_post_op_attr_sz+2
79
#define NFS3_fsstatres_sz       1+NFS3_post_op_attr_sz+13
80
#define NFS3_fsinfores_sz       1+NFS3_post_op_attr_sz+12
81
#define NFS3_pathconfres_sz     1+NFS3_post_op_attr_sz+6
82
#define NFS3_commitres_sz       1+NFS3_wcc_data_sz+2
83
 
84
/*
85
 * Map file type to S_IFMT bits
86
 */
87
static struct {
88
        unsigned int    mode;
89
        unsigned int    nfs2type;
90
} nfs_type2fmt[] = {
91
      { 0,               NFNON   },
92
      { S_IFREG,        NFREG   },
93
      { S_IFDIR,        NFDIR   },
94
      { S_IFBLK,        NFBLK   },
95
      { S_IFCHR,        NFCHR   },
96
      { S_IFLNK,        NFLNK   },
97
      { S_IFSOCK,       NFSOCK  },
98
      { S_IFIFO,        NFFIFO  },
99
      { 0,               NFBAD   }
100
};
101
 
102
/*
103
 * Common NFS XDR functions as inlines
104
 */
105
static inline u32 *
106
xdr_encode_fhandle(u32 *p, struct nfs_fh *fh)
107
{
108
        *p++ = htonl(fh->size);
109
        memcpy(p, fh->data, fh->size);
110
        return p + XDR_QUADLEN(fh->size);
111
}
112
 
113
static inline u32 *
114
xdr_decode_fhandle(u32 *p, struct nfs_fh *fh)
115
{
116
        /*
117
         * Zero all nonused bytes
118
         */
119
        memset((u8 *)fh, 0, sizeof(*fh));
120
        if ((fh->size = ntohl(*p++)) <= NFS3_FHSIZE) {
121
                memcpy(fh->data, p, fh->size);
122
                return p + XDR_QUADLEN(fh->size);
123
        }
124
        return NULL;
125
}
126
 
127
/*
128
 * Encode/decode time.
129
 * Since the VFS doesn't care for fractional times, we ignore the
130
 * nanosecond field.
131
 */
132
static inline u32 *
133
xdr_encode_time(u32 *p, time_t time)
134
{
135
        *p++ = htonl(time);
136
        *p++ = 0;
137
        return p;
138
}
139
 
140
static inline u32 *
141
xdr_decode_time3(u32 *p, u64 *timep)
142
{
143
        u64 tmp = (u64)ntohl(*p++) << 32;
144
        *timep = tmp + (u64)ntohl(*p++);
145
        return p;
146
}
147
 
148
static inline u32 *
149
xdr_encode_time3(u32 *p, u64 time)
150
{
151
        *p++ = htonl(time >> 32);
152
        *p++ = htonl(time & 0xFFFFFFFF);
153
        return p;
154
}
155
 
156
static u32 *
157
xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr)
158
{
159
        unsigned int    type;
160
        int             fmode;
161
 
162
        type = ntohl(*p++);
163
        if (type >= NF3BAD)
164
                type = NF3BAD;
165
        fmode = nfs_type2fmt[type].mode;
166
        fattr->type = nfs_type2fmt[type].nfs2type;
167
        fattr->mode = (ntohl(*p++) & ~S_IFMT) | fmode;
168
        fattr->nlink = ntohl(*p++);
169
        fattr->uid = ntohl(*p++);
170
        fattr->gid = ntohl(*p++);
171
        p = xdr_decode_hyper(p, &fattr->size);
172
        p = xdr_decode_hyper(p, &fattr->du.nfs3.used);
173
        /* Turn remote device info into Linux-specific dev_t */
174
        fattr->rdev = ntohl(*p++) << MINORBITS;
175
        fattr->rdev |= ntohl(*p++) & MINORMASK;
176
        p = xdr_decode_hyper(p, &fattr->fsid);
177
        p = xdr_decode_hyper(p, &fattr->fileid);
178
        p = xdr_decode_time3(p, &fattr->atime);
179
        p = xdr_decode_time3(p, &fattr->mtime);
180
        p = xdr_decode_time3(p, &fattr->ctime);
181
 
182
        /* Update the mode bits */
183
        fattr->valid |= (NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3);
184
        return p;
185
}
186
 
187
static inline u32 *
188
xdr_encode_sattr(u32 *p, struct iattr *attr)
189
{
190
        if (attr->ia_valid & ATTR_MODE) {
191
                *p++ = xdr_one;
192
                *p++ = htonl(attr->ia_mode);
193
        } else {
194
                *p++ = xdr_zero;
195
        }
196
        if (attr->ia_valid & ATTR_UID) {
197
                *p++ = xdr_one;
198
                *p++ = htonl(attr->ia_uid);
199
        } else {
200
                *p++ = xdr_zero;
201
        }
202
        if (attr->ia_valid & ATTR_GID) {
203
                *p++ = xdr_one;
204
                *p++ = htonl(attr->ia_gid);
205
        } else {
206
                *p++ = xdr_zero;
207
        }
208
        if (attr->ia_valid & ATTR_SIZE) {
209
                *p++ = xdr_one;
210
                p = xdr_encode_hyper(p, (__u64) attr->ia_size);
211
        } else {
212
                *p++ = xdr_zero;
213
        }
214
        if (attr->ia_valid & ATTR_ATIME_SET) {
215
                *p++ = xdr_two;
216
                p = xdr_encode_time(p, attr->ia_atime);
217
        } else if (attr->ia_valid & ATTR_ATIME) {
218
                *p++ = xdr_one;
219
        } else {
220
                *p++ = xdr_zero;
221
        }
222
        if (attr->ia_valid & ATTR_MTIME_SET) {
223
                *p++ = xdr_two;
224
                p = xdr_encode_time(p, attr->ia_mtime);
225
        } else if (attr->ia_valid & ATTR_MTIME) {
226
                *p++ = xdr_one;
227
        } else {
228
                *p++ = xdr_zero;
229
        }
230
        return p;
231
}
232
 
233
static inline u32 *
234
xdr_decode_wcc_attr(u32 *p, struct nfs_fattr *fattr)
235
{
236
        p = xdr_decode_hyper(p, &fattr->pre_size);
237
        p = xdr_decode_time3(p, &fattr->pre_mtime);
238
        p = xdr_decode_time3(p, &fattr->pre_ctime);
239
        fattr->valid |= NFS_ATTR_WCC;
240
        return p;
241
}
242
 
243
static inline u32 *
244
xdr_decode_post_op_attr(u32 *p, struct nfs_fattr *fattr)
245
{
246
        if (*p++)
247
                p = xdr_decode_fattr(p, fattr);
248
        return p;
249
}
250
 
251
static inline u32 *
252
xdr_decode_pre_op_attr(u32 *p, struct nfs_fattr *fattr)
253
{
254
        if (*p++)
255
                return xdr_decode_wcc_attr(p, fattr);
256
        return p;
257
}
258
 
259
 
260
static inline u32 *
261
xdr_decode_wcc_data(u32 *p, struct nfs_fattr *fattr)
262
{
263
        p = xdr_decode_pre_op_attr(p, fattr);
264
        return xdr_decode_post_op_attr(p, fattr);
265
}
266
 
267
/*
268
 * NFS encode functions
269
 */
270
/*
271
 * Encode void argument
272
 */
273
static int
274
nfs3_xdr_enc_void(struct rpc_rqst *req, u32 *p, void *dummy)
275
{
276
        req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
277
        return 0;
278
}
279
 
280
/*
281
 * Encode file handle argument
282
 */
283
static int
284
nfs3_xdr_fhandle(struct rpc_rqst *req, u32 *p, struct nfs_fh *fh)
285
{
286
        p = xdr_encode_fhandle(p, fh);
287
        req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
288
        return 0;
289
}
290
 
291
/*
292
 * Encode SETATTR arguments
293
 */
294
static int
295
nfs3_xdr_sattrargs(struct rpc_rqst *req, u32 *p, struct nfs3_sattrargs *args)
296
{
297
        p = xdr_encode_fhandle(p, args->fh);
298
        p = xdr_encode_sattr(p, args->sattr);
299
        *p++ = htonl(args->guard);
300
        if (args->guard)
301
                p = xdr_encode_time3(p, args->guardtime);
302
        req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
303
        return 0;
304
}
305
 
306
/*
307
 * Encode directory ops argument
308
 */
309
static int
310
nfs3_xdr_diropargs(struct rpc_rqst *req, u32 *p, struct nfs3_diropargs *args)
311
{
312
        p = xdr_encode_fhandle(p, args->fh);
313
        p = xdr_encode_array(p, args->name, args->len);
314
        req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
315
        return 0;
316
}
317
 
318
/*
319
 * Encode access() argument
320
 */
321
static int
322
nfs3_xdr_accessargs(struct rpc_rqst *req, u32 *p, struct nfs3_accessargs *args)
323
{
324
        p = xdr_encode_fhandle(p, args->fh);
325
        *p++ = htonl(args->access);
326
        req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
327
        return 0;
328
}
329
 
330
/*
331
 * Arguments to a READ call. Since we read data directly into the page
332
 * cache, we also set up the reply iovec here so that iov[1] points
333
 * exactly to the page we want to fetch.
334
 */
335
static int
336
nfs3_xdr_readargs(struct rpc_rqst *req, u32 *p, struct nfs_readargs *args)
337
{
338
        struct rpc_auth *auth = req->rq_task->tk_auth;
339
        unsigned int replen;
340
        u32 count = args->count;
341
 
342
        p = xdr_encode_fhandle(p, args->fh);
343
        p = xdr_encode_hyper(p, args->offset);
344
        *p++ = htonl(count);
345
        req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
346
 
347
        /* Inline the page array */
348
        replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readres_sz) << 2;
349
        xdr_inline_pages(&req->rq_rcv_buf, replen,
350
                         args->pages, args->pgbase, count);
351
        return 0;
352
}
353
 
354
/*
355
 * Write arguments. Splice the buffer to be written into the iovec.
356
 */
357
static int
358
nfs3_xdr_writeargs(struct rpc_rqst *req, u32 *p, struct nfs_writeargs *args)
359
{
360
        struct xdr_buf *sndbuf = &req->rq_snd_buf;
361
        u32 count = args->count;
362
 
363
        p = xdr_encode_fhandle(p, args->fh);
364
        p = xdr_encode_hyper(p, args->offset);
365
        *p++ = htonl(count);
366
        *p++ = htonl(args->stable);
367
        *p++ = htonl(count);
368
        sndbuf->len = xdr_adjust_iovec(sndbuf->head, p);
369
 
370
        /* Copy the page array */
371
        xdr_encode_pages(sndbuf, args->pages, args->pgbase, count);
372
        return 0;
373
}
374
 
375
/*
376
 * Encode CREATE arguments
377
 */
378
static int
379
nfs3_xdr_createargs(struct rpc_rqst *req, u32 *p, struct nfs3_createargs *args)
380
{
381
        p = xdr_encode_fhandle(p, args->fh);
382
        p = xdr_encode_array(p, args->name, args->len);
383
 
384
        *p++ = htonl(args->createmode);
385
        if (args->createmode == NFS3_CREATE_EXCLUSIVE) {
386
                *p++ = args->verifier[0];
387
                *p++ = args->verifier[1];
388
        } else
389
                p = xdr_encode_sattr(p, args->sattr);
390
 
391
        req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
392
        return 0;
393
}
394
 
395
/*
396
 * Encode MKDIR arguments
397
 */
398
static int
399
nfs3_xdr_mkdirargs(struct rpc_rqst *req, u32 *p, struct nfs3_mkdirargs *args)
400
{
401
        p = xdr_encode_fhandle(p, args->fh);
402
        p = xdr_encode_array(p, args->name, args->len);
403
        p = xdr_encode_sattr(p, args->sattr);
404
        req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
405
        return 0;
406
}
407
 
408
/*
409
 * Encode SYMLINK arguments
410
 */
411
static int
412
nfs3_xdr_symlinkargs(struct rpc_rqst *req, u32 *p, struct nfs3_symlinkargs *args)
413
{
414
        p = xdr_encode_fhandle(p, args->fromfh);
415
        p = xdr_encode_array(p, args->fromname, args->fromlen);
416
        p = xdr_encode_sattr(p, args->sattr);
417
        p = xdr_encode_array(p, args->topath, args->tolen);
418
        req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
419
        return 0;
420
}
421
 
422
/*
423
 * Encode MKNOD arguments
424
 */
425
static int
426
nfs3_xdr_mknodargs(struct rpc_rqst *req, u32 *p, struct nfs3_mknodargs *args)
427
{
428
        p = xdr_encode_fhandle(p, args->fh);
429
        p = xdr_encode_array(p, args->name, args->len);
430
        *p++ = htonl(args->type);
431
        p = xdr_encode_sattr(p, args->sattr);
432
        if (args->type == NF3CHR || args->type == NF3BLK) {
433
                *p++ = htonl(args->rdev >> MINORBITS);
434
                *p++ = htonl(args->rdev & MINORMASK);
435
        }
436
 
437
        req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
438
        return 0;
439
}
440
 
441
/*
442
 * Encode RENAME arguments
443
 */
444
static int
445
nfs3_xdr_renameargs(struct rpc_rqst *req, u32 *p, struct nfs3_renameargs *args)
446
{
447
        p = xdr_encode_fhandle(p, args->fromfh);
448
        p = xdr_encode_array(p, args->fromname, args->fromlen);
449
        p = xdr_encode_fhandle(p, args->tofh);
450
        p = xdr_encode_array(p, args->toname, args->tolen);
451
        req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
452
        return 0;
453
}
454
 
455
/*
456
 * Encode LINK arguments
457
 */
458
static int
459
nfs3_xdr_linkargs(struct rpc_rqst *req, u32 *p, struct nfs3_linkargs *args)
460
{
461
        p = xdr_encode_fhandle(p, args->fromfh);
462
        p = xdr_encode_fhandle(p, args->tofh);
463
        p = xdr_encode_array(p, args->toname, args->tolen);
464
        req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
465
        return 0;
466
}
467
 
468
/*
469
 * Encode arguments to readdir call
470
 */
471
static int
472
nfs3_xdr_readdirargs(struct rpc_rqst *req, u32 *p, struct nfs3_readdirargs *args)
473
{
474
        struct rpc_auth *auth = req->rq_task->tk_auth;
475
        unsigned int replen;
476
        u32 count = args->count;
477
 
478
        p = xdr_encode_fhandle(p, args->fh);
479
        p = xdr_encode_hyper(p, args->cookie);
480
        *p++ = args->verf[0];
481
        *p++ = args->verf[1];
482
        if (args->plus) {
483
                /* readdirplus: need dircount + buffer size.
484
                 * We just make sure we make dircount big enough */
485
                *p++ = htonl(count >> 3);
486
        }
487
        *p++ = htonl(count);
488
        req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
489
 
490
        /* Inline the page array */
491
        replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readdirres_sz) << 2;
492
        xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, count);
493
        return 0;
494
}
495
 
496
/*
497
 * Decode the result of a readdir call.
498
 * We just check for syntactical correctness.
499
 */
500
static int
501
nfs3_xdr_readdirres(struct rpc_rqst *req, u32 *p, struct nfs3_readdirres *res)
502
{
503
        struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
504
        struct iovec *iov = rcvbuf->head;
505
        struct page **page;
506
        int hdrlen, recvd;
507
        int status, nr;
508
        unsigned int len, pglen;
509
        u32 *entry, *end;
510
 
511
        status = ntohl(*p++);
512
        /* Decode post_op_attrs */
513
        p = xdr_decode_post_op_attr(p, res->dir_attr);
514
        if (status)
515
                return -nfs_stat_to_errno(status);
516
        /* Decode verifier cookie */
517
        if (res->verf) {
518
                res->verf[0] = *p++;
519
                res->verf[1] = *p++;
520
        } else {
521
                p += 2;
522
        }
523
 
524
        hdrlen = (u8 *) p - (u8 *) iov->iov_base;
525
        if (iov->iov_len < hdrlen) {
526
                printk(KERN_WARNING "NFS: READDIR reply header overflowed:"
527
                                "length %d > %Zu\n", hdrlen, iov->iov_len);
528
                return -errno_NFSERR_IO;
529
        } else if (iov->iov_len != hdrlen) {
530
                dprintk("NFS: READDIR header is short. iovec will be shifted.\n");
531
                xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
532
        }
533
 
534
        pglen = rcvbuf->page_len;
535
        recvd = req->rq_received - hdrlen;
536
        if (pglen > recvd)
537
                pglen = recvd;
538
        page = rcvbuf->pages;
539
        p = kmap(*page);
540
        end = (u32 *)((char *)p + pglen);
541
        entry = p;
542
        for (nr = 0; *p++; nr++) {
543
                if (p + 3 > end)
544
                        goto short_pkt;
545
                p += 2;                         /* inode # */
546
                len = ntohl(*p++);              /* string length */
547
                p += XDR_QUADLEN(len) + 2;      /* name + cookie */
548
                if (len > NFS3_MAXNAMLEN) {
549
                        printk(KERN_WARNING "NFS: giant filename in readdir (len %x)!\n",
550
                                                len);
551
                        goto err_unmap;
552
                }
553
 
554
                if (res->plus) {
555
                        /* post_op_attr */
556
                        if (p > end)
557
                                goto short_pkt;
558
                        if (*p++) {
559
                                p += 21;
560
                                if (p > end)
561
                                        goto short_pkt;
562
                        }
563
                        /* post_op_fh3 */
564
                        if (*p++) {
565
                                if (p > end)
566
                                        goto short_pkt;
567
                                len = ntohl(*p++);
568
                                if (len > NFS3_FHSIZE) {
569
                                        printk(KERN_WARNING "NFS: giant filehandle in "
570
                                                "readdir (len %x)!\n", len);
571
                                        goto err_unmap;
572
                                }
573
                                p += XDR_QUADLEN(len);
574
                        }
575
                }
576
 
577
                if (p + 2 > end)
578
                        goto short_pkt;
579
                entry = p;
580
        }
581
        if (!nr && (entry[0] != 0 || entry[1] == 0))
582
                goto short_pkt;
583
 out:
584
        kunmap(*page);
585
        return nr;
586
 short_pkt:
587
        entry[0] = entry[1] = 0;
588
        /* truncate listing ? */
589
        if (!nr) {
590
                printk(KERN_NOTICE "NFS: readdir reply truncated!\n");
591
                entry[1] = 1;
592
        }
593
        goto out;
594
err_unmap:
595
        kunmap(*page);
596
        return -errno_NFSERR_IO;
597
}
598
 
599
u32 *
600
nfs3_decode_dirent(u32 *p, struct nfs_entry *entry, int plus)
601
{
602
        if (!*p++) {
603
                if (!*p)
604
                        return ERR_PTR(-EAGAIN);
605
                entry->eof = 1;
606
                return ERR_PTR(-EBADCOOKIE);
607
        }
608
 
609
        p = xdr_decode_hyper(p, &entry->ino);
610
        entry->len  = ntohl(*p++);
611
        entry->name = (const char *) p;
612
        p += XDR_QUADLEN(entry->len);
613
        entry->prev_cookie = entry->cookie;
614
        p = xdr_decode_hyper(p, &entry->cookie);
615
 
616
        if (plus) {
617
                struct nfs_fattr fattr;
618
                p = xdr_decode_post_op_attr(p, &fattr);
619
                /* In fact, a post_op_fh3: */
620
                if (*p++) {
621
                        struct nfs_fh fh;
622
                        p = xdr_decode_fhandle(p, &fh);
623
                }
624
        }
625
 
626
        entry->eof = !p[0] && p[1];
627
        return p;
628
}
629
 
630
/*
631
 * Encode COMMIT arguments
632
 */
633
static int
634
nfs3_xdr_commitargs(struct rpc_rqst *req, u32 *p, struct nfs_writeargs *args)
635
{
636
        p = xdr_encode_fhandle(p, args->fh);
637
        p = xdr_encode_hyper(p, args->offset);
638
        *p++ = htonl(args->count);
639
        req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
640
        return 0;
641
}
642
 
643
/*
644
 * NFS XDR decode functions
645
 */
646
/*
647
 * Decode void reply
648
 */
649
static int
650
nfs3_xdr_dec_void(struct rpc_rqst *req, u32 *p, void *dummy)
651
{
652
        return 0;
653
}
654
 
655
/*
656
 * Decode attrstat reply.
657
 */
658
static int
659
nfs3_xdr_attrstat(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
660
{
661
        int     status;
662
 
663
        if ((status = ntohl(*p++)))
664
                return -nfs_stat_to_errno(status);
665
        xdr_decode_fattr(p, fattr);
666
        return 0;
667
}
668
 
669
/*
670
 * Decode status+wcc_data reply
671
 * SATTR, REMOVE, RMDIR
672
 */
673
static int
674
nfs3_xdr_wccstat(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
675
{
676
        int     status;
677
 
678
        if ((status = ntohl(*p++)))
679
                status = -nfs_stat_to_errno(status);
680
        xdr_decode_wcc_data(p, fattr);
681
        return status;
682
}
683
 
684
/*
685
 * Decode LOOKUP reply
686
 */
687
static int
688
nfs3_xdr_lookupres(struct rpc_rqst *req, u32 *p, struct nfs3_diropres *res)
689
{
690
        int     status;
691
 
692
        if ((status = ntohl(*p++))) {
693
                status = -nfs_stat_to_errno(status);
694
        } else {
695
                if (!(p = xdr_decode_fhandle(p, res->fh)))
696
                        return -errno_NFSERR_IO;
697
                p = xdr_decode_post_op_attr(p, res->fattr);
698
        }
699
        xdr_decode_post_op_attr(p, res->dir_attr);
700
        return status;
701
}
702
 
703
/*
704
 * Decode ACCESS reply
705
 */
706
static int
707
nfs3_xdr_accessres(struct rpc_rqst *req, u32 *p, struct nfs3_accessres *res)
708
{
709
        int     status = ntohl(*p++);
710
 
711
        p = xdr_decode_post_op_attr(p, res->fattr);
712
        if (status)
713
                return -nfs_stat_to_errno(status);
714
        res->access = ntohl(*p++);
715
        return 0;
716
}
717
 
718
static int
719
nfs3_xdr_readlinkargs(struct rpc_rqst *req, u32 *p, struct nfs3_readlinkargs *args)
720
{
721
        struct rpc_auth *auth = req->rq_task->tk_auth;
722
        unsigned int replen;
723
        u32 count = args->count - 4;
724
 
725
        p = xdr_encode_fhandle(p, args->fh);
726
        req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
727
 
728
        /* Inline the page array */
729
        replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readlinkres_sz) << 2;
730
        xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, count);
731
        return 0;
732
}
733
 
734
/*
735
 * Decode READLINK reply
736
 */
737
static int
738
nfs3_xdr_readlinkres(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
739
{
740
        struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
741
        struct iovec *iov = rcvbuf->head;
742
        unsigned int hdrlen;
743
        u32     *strlen, len;
744
        char    *string;
745
        int     status;
746
 
747
        status = ntohl(*p++);
748
        p = xdr_decode_post_op_attr(p, fattr);
749
 
750
        if (status != 0)
751
                return -nfs_stat_to_errno(status);
752
 
753
        hdrlen = (u8 *) p - (u8 *) iov->iov_base;
754
        if (iov->iov_len > hdrlen) {
755
                dprintk("NFS: READLINK header is short. iovec will be shifted.\n");
756
                xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
757
        }
758
 
759
        strlen = (u32*)kmap(rcvbuf->pages[0]);
760
        /* Convert length of symlink */
761
        len = ntohl(*strlen);
762
        if (len > rcvbuf->page_len)
763
                len = rcvbuf->page_len;
764
        *strlen = len;
765
        /* NULL terminate the string we got */
766
        string = (char *)(strlen + 1);
767
        string[len] = 0;
768
        kunmap(rcvbuf->pages[0]);
769
        return 0;
770
}
771
 
772
/*
773
 * Decode READ reply
774
 */
775
static int
776
nfs3_xdr_readres(struct rpc_rqst *req, u32 *p, struct nfs_readres *res)
777
{
778
        struct iovec *iov = req->rq_rvec;
779
        int     status, count, ocount, recvd, hdrlen;
780
 
781
        status = ntohl(*p++);
782
        p = xdr_decode_post_op_attr(p, res->fattr);
783
 
784
        if (status != 0)
785
                return -nfs_stat_to_errno(status);
786
 
787
        /* Decode reply could and EOF flag. NFSv3 is somewhat redundant
788
         * in that it puts the count both in the res struct and in the
789
         * opaque data count. */
790
        count    = ntohl(*p++);
791
        res->eof = ntohl(*p++);
792
        ocount   = ntohl(*p++);
793
 
794
        if (ocount != count) {
795
                printk(KERN_WARNING "NFS: READ count doesn't match RPC opaque count.\n");
796
                return -errno_NFSERR_IO;
797
        }
798
 
799
        hdrlen = (u8 *) p - (u8 *) iov->iov_base;
800
        if (iov->iov_len < hdrlen) {
801
                printk(KERN_WARNING "NFS: READ reply header overflowed:"
802
                                "length %d > %Zu\n", hdrlen, iov->iov_len);
803
                return -errno_NFSERR_IO;
804
        } else if (iov->iov_len != hdrlen) {
805
                dprintk("NFS: READ header is short. iovec will be shifted.\n");
806
                xdr_shift_buf(&req->rq_rcv_buf, iov->iov_len - hdrlen);
807
        }
808
 
809
        recvd = req->rq_received - hdrlen;
810
        if (count > recvd) {
811
                printk(KERN_WARNING "NFS: server cheating in read reply: "
812
                        "count %d > recvd %d\n", count, recvd);
813
                count = recvd;
814
                res->eof = 0;
815
        }
816
 
817
        if (count < res->count)
818
                res->count = count;
819
 
820
        return count;
821
}
822
 
823
/*
824
 * Decode WRITE response
825
 */
826
static int
827
nfs3_xdr_writeres(struct rpc_rqst *req, u32 *p, struct nfs_writeres *res)
828
{
829
        int     status;
830
 
831
        status = ntohl(*p++);
832
        p = xdr_decode_wcc_data(p, res->fattr);
833
 
834
        if (status != 0)
835
                return -nfs_stat_to_errno(status);
836
 
837
        res->count = ntohl(*p++);
838
        res->verf->committed = (enum nfs3_stable_how)ntohl(*p++);
839
        res->verf->verifier[0] = *p++;
840
        res->verf->verifier[1] = *p++;
841
 
842
        return res->count;
843
}
844
 
845
/*
846
 * Decode a CREATE response
847
 */
848
static int
849
nfs3_xdr_createres(struct rpc_rqst *req, u32 *p, struct nfs3_diropres *res)
850
{
851
        int     status;
852
 
853
        status = ntohl(*p++);
854
        if (status == 0) {
855
                if (*p++) {
856
                        if (!(p = xdr_decode_fhandle(p, res->fh)))
857
                                return -errno_NFSERR_IO;
858
                        p = xdr_decode_post_op_attr(p, res->fattr);
859
                } else {
860
                        memset(res->fh, 0, sizeof(*res->fh));
861
                        /* Do decode post_op_attr but set it to NULL */
862
                        p = xdr_decode_post_op_attr(p, res->fattr);
863
                        res->fattr->valid = 0;
864
                }
865
        } else {
866
                status = -nfs_stat_to_errno(status);
867
        }
868
        p = xdr_decode_wcc_data(p, res->dir_attr);
869
        return status;
870
}
871
 
872
/*
873
 * Decode RENAME reply
874
 */
875
static int
876
nfs3_xdr_renameres(struct rpc_rqst *req, u32 *p, struct nfs3_renameres *res)
877
{
878
        int     status;
879
 
880
        if ((status = ntohl(*p++)) != 0)
881
                status = -nfs_stat_to_errno(status);
882
        p = xdr_decode_wcc_data(p, res->fromattr);
883
        p = xdr_decode_wcc_data(p, res->toattr);
884
        return status;
885
}
886
 
887
/*
888
 * Decode LINK reply
889
 */
890
static int
891
nfs3_xdr_linkres(struct rpc_rqst *req, u32 *p, struct nfs3_linkres *res)
892
{
893
        int     status;
894
 
895
        if ((status = ntohl(*p++)) != 0)
896
                status = -nfs_stat_to_errno(status);
897
        p = xdr_decode_post_op_attr(p, res->fattr);
898
        p = xdr_decode_wcc_data(p, res->dir_attr);
899
        return status;
900
}
901
 
902
/*
903
 * Decode FSSTAT reply
904
 */
905
static int
906
nfs3_xdr_fsstatres(struct rpc_rqst *req, u32 *p, struct nfs_fsinfo *res)
907
{
908
        struct nfs_fattr dummy;
909
        int             status;
910
 
911
        status = ntohl(*p++);
912
 
913
        p = xdr_decode_post_op_attr(p, &dummy);
914
        if (status != 0)
915
                return -nfs_stat_to_errno(status);
916
 
917
        p = xdr_decode_hyper(p, &res->tbytes);
918
        p = xdr_decode_hyper(p, &res->fbytes);
919
        p = xdr_decode_hyper(p, &res->abytes);
920
        p = xdr_decode_hyper(p, &res->tfiles);
921
        p = xdr_decode_hyper(p, &res->ffiles);
922
        p = xdr_decode_hyper(p, &res->afiles);
923
 
924
        /* ignore invarsec */
925
        return 0;
926
}
927
 
928
/*
929
 * Decode FSINFO reply
930
 */
931
static int
932
nfs3_xdr_fsinfores(struct rpc_rqst *req, u32 *p, struct nfs_fsinfo *res)
933
{
934
        struct nfs_fattr dummy;
935
        int             status;
936
 
937
        status = ntohl(*p++);
938
 
939
        p = xdr_decode_post_op_attr(p, &dummy);
940
        if (status != 0)
941
                return -nfs_stat_to_errno(status);
942
 
943
        res->rtmax  = ntohl(*p++);
944
        res->rtpref = ntohl(*p++);
945
        res->rtmult = ntohl(*p++);
946
        res->wtmax  = ntohl(*p++);
947
        res->wtpref = ntohl(*p++);
948
        res->wtmult = ntohl(*p++);
949
        res->dtpref = ntohl(*p++);
950
        p = xdr_decode_hyper(p, &res->maxfilesize);
951
 
952
        /* ignore time_delta and properties */
953
        return 0;
954
}
955
 
956
/*
957
 * Decode PATHCONF reply
958
 */
959
static int
960
nfs3_xdr_pathconfres(struct rpc_rqst *req, u32 *p, struct nfs_fsinfo *res)
961
{
962
        struct nfs_fattr dummy;
963
        int             status;
964
 
965
        status = ntohl(*p++);
966
 
967
        p = xdr_decode_post_op_attr(p, &dummy);
968
        if (status != 0)
969
                return -nfs_stat_to_errno(status);
970
        res->linkmax = ntohl(*p++);
971
        res->namelen = ntohl(*p++);
972
 
973
        /* ignore remaining fields */
974
        return 0;
975
}
976
 
977
/*
978
 * Decode COMMIT reply
979
 */
980
static int
981
nfs3_xdr_commitres(struct rpc_rqst *req, u32 *p, struct nfs_writeres *res)
982
{
983
        int             status;
984
 
985
        status = ntohl(*p++);
986
        p = xdr_decode_wcc_data(p, res->fattr);
987
        if (status != 0)
988
                return -nfs_stat_to_errno(status);
989
 
990
        res->verf->verifier[0] = *p++;
991
        res->verf->verifier[1] = *p++;
992
        return 0;
993
}
994
 
995
#ifndef MAX
996
# define MAX(a, b)      (((a) > (b))? (a) : (b))
997
#endif
998
 
999
#define PROC(proc, argtype, restype, timer)                             \
1000
    { .p_procname  = "nfs3_" #proc,                                     \
1001
      .p_encode    = (kxdrproc_t) nfs3_xdr_##argtype,                   \
1002
      .p_decode    = (kxdrproc_t) nfs3_xdr_##restype,                   \
1003
      .p_bufsiz    = MAX(NFS3_##argtype##_sz,NFS3_##restype##_sz) << 2, \
1004
      .p_timer     = timer                                              \
1005
    }
1006
 
1007
static struct rpc_procinfo      nfs3_procedures[22] = {
1008
  PROC(null,            enc_void,       dec_void, 0),
1009
  PROC(getattr,         fhandle,        attrstat, 1),
1010
  PROC(setattr,         sattrargs,      wccstat, 0),
1011
  PROC(lookup,          diropargs,      lookupres, 2),
1012
  PROC(access,          accessargs,     accessres, 1),
1013
  PROC(readlink,        readlinkargs,   readlinkres, 3),
1014
  PROC(read,            readargs,       readres, 3),
1015
  PROC(write,           writeargs,      writeres, 4),
1016
  PROC(create,          createargs,     createres, 0),
1017
  PROC(mkdir,           mkdirargs,      createres, 0),
1018
  PROC(symlink,         symlinkargs,    createres, 0),
1019
  PROC(mknod,           mknodargs,      createres, 0),
1020
  PROC(remove,          diropargs,      wccstat, 0),
1021
  PROC(rmdir,           diropargs,      wccstat, 0),
1022
  PROC(rename,          renameargs,     renameres, 0),
1023
  PROC(link,            linkargs,       linkres, 0),
1024
  PROC(readdir,         readdirargs,    readdirres, 3),
1025
  PROC(readdirplus,     readdirargs,    readdirres, 3),
1026
  PROC(fsstat,          fhandle,        fsstatres, 0),
1027
  PROC(fsinfo,          fhandle,        fsinfores, 0),
1028
  PROC(pathconf,        fhandle,        pathconfres, 0),
1029
  PROC(commit,          commitargs,     commitres, 5),
1030
};
1031
 
1032
struct rpc_version              nfs_version3 = {
1033
        3,
1034
        sizeof(nfs3_procedures)/sizeof(nfs3_procedures[0]),
1035
        nfs3_procedures
1036
};
1037
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.