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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [fs/] [nfs/] [proc.c] - Blame information for rev 1628

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1628 jcastillo
/*
2
 *  linux/fs/nfs/proc.c
3
 *
4
 *  Copyright (C) 1992, 1993, 1994  Rick Sladkey
5
 *
6
 *  OS-independent nfs remote procedure call functions
7
 *
8
 *  Tuned by Alan Cox <A.Cox@swansea.ac.uk> for >3K buffers
9
 *  so at last we can have decent(ish) throughput off a
10
 *  Sun server.
11
 *
12
 *  Coding optimized and cleaned up by Florian La Roche.
13
 *  Note: Error returns are optimized for NFS_OK, which isn't translated via
14
 *  nfs_stat_to_errno(), but happens to be already the right return code.
15
 *
16
 *  FixMe: We ought to define a sensible small max size for
17
 *  things like getattr that are tiny packets and use the
18
 *  old get_free_page stuff with it.
19
 *
20
 *  Also, the code currently doesn't check the size of the packet, when
21
 *  it decodes the packet.
22
 *
23
 *  Feel free to fix it and mail me the diffs if it worries you.
24
 */
25
 
26
/*
27
 * Fixes:
28
 *    Ion Badulescu <ionut@cs.columbia.edu>     : FIFO's need special handling in NFSv2
29
 */
30
 
31
/*
32
 * Defining NFS_PROC_DEBUG causes a lookup of a file named
33
 * "xyzzy" to toggle debugging.  Just cd to an NFS-mounted
34
 * filesystem and type 'ls xyzzy' to turn on debugging.
35
 */
36
 
37
#if 0
38
#define NFS_PROC_DEBUG
39
#endif
40
 
41
#include <linux/param.h>
42
#include <linux/sched.h>
43
#include <linux/mm.h>
44
#include <linux/malloc.h>
45
#include <linux/nfs_fs.h>
46
#include <linux/utsname.h>
47
#include <linux/errno.h>
48
#include <linux/string.h>
49
#include <linux/in.h>
50
#include <linux/pagemap.h>
51
 
52
#include <asm/segment.h>
53
 
54
#ifdef NFS_PROC_DEBUG
55
 
56
static int proc_debug = 0;
57
#define PRINTK(format, args...) \
58
        do {                                            \
59
                if (proc_debug)                         \
60
                        printk(format , ## args);       \
61
        } while (0)
62
 
63
#else /* !NFS_PROC_DEBUG */
64
 
65
#define PRINTK(format, args...) do ; while (0)
66
 
67
#endif /* !NFS_PROC_DEBUG */
68
 
69
/* Mapping from NFS error code to "errno" error code. */
70
#define errno_NFSERR_IO EIO
71
 
72
static int *nfs_rpc_header(int *p, int procedure, int ruid);
73
static int *nfs_rpc_verify(int *p);
74
static int nfs_stat_to_errno(int stat);
75
 
76
/*
77
 * Our memory allocation and release functions.
78
 */
79
 
80
#define NFS_SLACK_SPACE         1024    /* Total overkill */ 
81
/* !!! Be careful, this constant is now also used in sock.c...
82
   We should easily convert to not using it anymore for most cases... */
83
 
84
static inline int *nfs_rpc_alloc(int size)
85
{
86
        int *i;
87
 
88
        while (!(i = (int *)kmalloc(size+NFS_SLACK_SPACE,GFP_NFS))) {
89
                schedule();
90
        }
91
        return i;
92
}
93
 
94
static inline void nfs_rpc_free(int *p)
95
{
96
        kfree((void *)p);
97
}
98
 
99
/*
100
 * Here are a bunch of xdr encode/decode functions that convert
101
 * between machine dependent and xdr data formats.
102
 */
103
 
104
#define QUADLEN(len) (((len) + 3) >> 2)
105
 
106
static inline int *xdr_encode_fhandle(int *p, struct nfs_fh *fhandle)
107
{
108
        *((struct nfs_fh *) p) = *fhandle;
109
        return p + QUADLEN(sizeof(*fhandle));
110
}
111
 
112
static inline int *xdr_decode_fhandle(int *p, struct nfs_fh *fhandle)
113
{
114
        *fhandle = *((struct nfs_fh *) p);
115
        return p + QUADLEN(sizeof(*fhandle));
116
}
117
 
118
static inline int *xdr_encode_string(int *p, const char *string)
119
{
120
        int len = strlen(string);
121
        int quadlen = QUADLEN(len);
122
 
123
        p[quadlen] = 0;
124
        *p++ = htonl(len);
125
        memcpy(p, string, len);
126
        return p + quadlen;
127
}
128
 
129
static inline int *xdr_decode_string(int *p, char *string, unsigned int maxlen)
130
{
131
        unsigned int len = ntohl(*p++);
132
        if (len > maxlen)
133
                return NULL;
134
        memcpy(string, p, len);
135
        string[len] = '\0';
136
        return p + QUADLEN(len);
137
}
138
 
139
static inline int *xdr_decode_string2(int *p, char **string, unsigned int *len,
140
                        unsigned int maxlen)
141
{
142
        *len = ntohl(*p++);
143
        if (*len > maxlen)
144
                return NULL;
145
        *string = (char *) p;
146
        return p + QUADLEN(*len);
147
}
148
 
149
 
150
static inline int *xdr_encode_data(int *p, const char *data, int len)
151
{
152
        int quadlen = QUADLEN(len);
153
 
154
        p[quadlen] = 0;
155
        *p++ = htonl(len);
156
        memcpy_fromfs(p, data, len);
157
        return p + quadlen;
158
}
159
 
160
static inline int *xdr_decode_data(int *p, char *data, int *lenp, int maxlen)
161
{
162
        unsigned len = *lenp = ntohl(*p++);
163
        if (len > maxlen)
164
                return NULL;
165
        memcpy(data, p, len);
166
        return p + QUADLEN(len);
167
}
168
 
169
static int *xdr_decode_fattr(int *p, struct nfs_fattr *fattr)
170
{
171
        fattr->type = (enum nfs_ftype) ntohl(*p++);
172
        fattr->mode = ntohl(*p++);
173
        fattr->nlink = ntohl(*p++);
174
        fattr->uid = ntohl(*p++);
175
        fattr->gid = ntohl(*p++);
176
        fattr->size = ntohl(*p++);
177
        fattr->blocksize = ntohl(*p++);
178
        fattr->rdev = ntohl(*p++);
179
        fattr->blocks = ntohl(*p++);
180
        fattr->fsid = ntohl(*p++);
181
        fattr->fileid = ntohl(*p++);
182
        fattr->atime.seconds = ntohl(*p++);
183
        fattr->atime.useconds = ntohl(*p++);
184
        fattr->mtime.seconds = ntohl(*p++);
185
        fattr->mtime.useconds = ntohl(*p++);
186
        fattr->ctime.seconds = ntohl(*p++);
187
        fattr->ctime.useconds = ntohl(*p++);
188
        if (fattr->type == NFCHR && fattr->rdev == NFS_FIFO_DEV) {
189
                fattr->type = NFFIFO;
190
                fattr->mode = (fattr->mode & ~S_IFMT) | S_IFIFO;
191
                fattr->rdev = 0;
192
        }
193
        return p;
194
}
195
 
196
static int *xdr_encode_sattr(int *p, struct nfs_sattr *sattr)
197
{
198
        *p++ = htonl(sattr->mode);
199
        *p++ = htonl(sattr->uid);
200
        *p++ = htonl(sattr->gid);
201
        *p++ = htonl(sattr->size);
202
        *p++ = htonl(sattr->atime.seconds);
203
        *p++ = htonl(sattr->atime.useconds);
204
        *p++ = htonl(sattr->mtime.seconds);
205
        *p++ = htonl(sattr->mtime.useconds);
206
        return p;
207
}
208
 
209
static int *xdr_decode_entry(int *p, struct nfs_entry *entry)
210
{
211
        entry->fileid = ntohl(*p++);
212
        if (!(p = xdr_decode_string(p, entry->name, NFS_MAXNAMLEN)))
213
                return NULL;
214
        entry->cookie = ntohl(*p++);
215
        entry->eof = 0;
216
        return p;
217
}
218
 
219
static int *xdr_decode_fsinfo(int *p, struct nfs_fsinfo *res)
220
{
221
        res->tsize = ntohl(*p++);
222
        res->bsize = ntohl(*p++);
223
        res->blocks = ntohl(*p++);
224
        res->bfree = ntohl(*p++);
225
        res->bavail = ntohl(*p++);
226
        return p;
227
}
228
 
229
/*
230
 * One function for each procedure in the NFS protocol.
231
 */
232
 
233
int nfs_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
234
                     struct nfs_fattr *fattr)
235
{
236
        int *p, *p0;
237
        int status;
238
        int ruid = 0;
239
 
240
        PRINTK("NFS call  getattr\n");
241
        if (!(p0 = nfs_rpc_alloc(server->rsize)))
242
                return -EIO;
243
retry:
244
        p = nfs_rpc_header(p0, NFSPROC_GETATTR, ruid);
245
        p = xdr_encode_fhandle(p, fhandle);
246
        if ((status = nfs_rpc_call(server, p0, p, server->rsize)) < 0) {
247
                nfs_rpc_free(p0);
248
                return status;
249
        }
250
        if (!(p = nfs_rpc_verify(p0)))
251
                status = -errno_NFSERR_IO;
252
        else if ((status = ntohl(*p++)) == NFS_OK) {
253
                p = xdr_decode_fattr(p, fattr);
254
                PRINTK("NFS reply getattr\n");
255
                /* status = 0; */
256
        }
257
        else {
258
                if (!ruid && current->fsuid == 0 && current->uid != 0) {
259
                        ruid = 1;
260
                        goto retry;
261
                }
262
                PRINTK("NFS reply getattr failed = %d\n", status);
263
                status = -nfs_stat_to_errno(status);
264
        }
265
        nfs_rpc_free(p0);
266
        return status;
267
}
268
 
269
int nfs_proc_setattr(struct nfs_server *server, struct nfs_fh *fhandle,
270
                     struct nfs_sattr *sattr, struct nfs_fattr *fattr)
271
{
272
        int *p, *p0;
273
        int status;
274
        int ruid = 0;
275
 
276
        PRINTK("NFS call  setattr\n");
277
        if (!(p0 = nfs_rpc_alloc(server->wsize)))
278
                return -EIO;
279
retry:
280
        p = nfs_rpc_header(p0, NFSPROC_SETATTR, ruid);
281
        p = xdr_encode_fhandle(p, fhandle);
282
        p = xdr_encode_sattr(p, sattr);
283
        if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
284
                nfs_rpc_free(p0);
285
                return status;
286
        }
287
        if (!(p = nfs_rpc_verify(p0)))
288
                status = -errno_NFSERR_IO;
289
        else if ((status = ntohl(*p++)) == NFS_OK) {
290
                p = xdr_decode_fattr(p, fattr);
291
                PRINTK("NFS reply setattr\n");
292
                /* status = 0; */
293
        }
294
        else {
295
                if (!ruid && current->fsuid == 0 && current->uid != 0) {
296
                        ruid = 1;
297
                        goto retry;
298
                }
299
                PRINTK("NFS reply setattr failed = %d\n", status);
300
                status = -nfs_stat_to_errno(status);
301
        }
302
        nfs_rpc_free(p0);
303
        return status;
304
}
305
 
306
int nfs_proc_lookup(struct nfs_server *server, struct nfs_fh *dir, const char *name,
307
                    struct nfs_fh *fhandle, struct nfs_fattr *fattr)
308
{
309
        int *p, *p0;
310
        int status;
311
        int ruid = 0;
312
 
313
        PRINTK("NFS call  lookup %s\n", name);
314
#ifdef NFS_PROC_DEBUG
315
        if (!strcmp(name, "xyzzy"))
316
                proc_debug = 1 - proc_debug;
317
#endif
318
        if (!(p0 = nfs_rpc_alloc(server->rsize)))
319
                return -EIO;
320
retry:
321
        p = nfs_rpc_header(p0, NFSPROC_LOOKUP, ruid);
322
        p = xdr_encode_fhandle(p, dir);
323
        p = xdr_encode_string(p, name);
324
        if ((status = nfs_rpc_call(server, p0, p, server->rsize)) < 0) {
325
                nfs_rpc_free(p0);
326
                return status;
327
        }
328
        if (!(p = nfs_rpc_verify(p0)))
329
                status = -errno_NFSERR_IO;
330
        else if ((status = ntohl(*p++)) == NFS_OK) {
331
                p = xdr_decode_fhandle(p, fhandle);
332
                p = xdr_decode_fattr(p, fattr);
333
                PRINTK("NFS reply lookup\n");
334
                /* status = 0; */
335
        }
336
        else {
337
                if (!ruid && current->fsuid == 0 && current->uid != 0) {
338
                        ruid = 1;
339
                        goto retry;
340
                }
341
                PRINTK("NFS reply lookup failed = %d\n", status);
342
                status = -nfs_stat_to_errno(status);
343
        }
344
        nfs_rpc_free(p0);
345
        return status;
346
}
347
 
348
int nfs_proc_readlink(struct nfs_server *server, struct nfs_fh *fhandle,
349
                int **p0, char **string, unsigned int *len, unsigned int maxlen)
350
{
351
        int *p;
352
        int status, ruid = 0;
353
 
354
        PRINTK("NFS call  readlink\n");
355
        if (!(*p0 = nfs_rpc_alloc(server->rsize)))
356
                return -EIO;
357
retry:
358
        p = nfs_rpc_header(*p0, NFSPROC_READLINK, ruid);
359
        p = xdr_encode_fhandle(p, fhandle);
360
        if ((status = nfs_rpc_call(server, *p0, p, server->rsize)) < 0)
361
                return status;
362
        if (!(p = nfs_rpc_verify(*p0)))
363
                status = -errno_NFSERR_IO;
364
        else if ((status = ntohl(*p++)) == NFS_OK) {
365
                if (!(p = xdr_decode_string2(p, string, len, maxlen))) {
366
                        printk("nfs_proc_readlink: giant pathname\n");
367
                        status = -errno_NFSERR_IO;
368
                }
369
                else    /* status = 0, */
370
                        PRINTK("NFS reply readlink\n");
371
        }
372
        else {
373
                if (!ruid && current->fsuid == 0 && current->uid != 0) {
374
                        ruid = 1;
375
                        goto retry;
376
                }
377
                PRINTK("NFS reply readlink failed = %d\n", status);
378
                status = -nfs_stat_to_errno(status);
379
        }
380
        return status;
381
}
382
 
383
int nfs_proc_read(struct nfs_server *server, struct nfs_fh *fhandle,
384
          int offset, int count, char *data, struct nfs_fattr *fattr)
385
{
386
        int *p, *p0;
387
        int status;
388
        int ruid = 0;
389
        int len;
390
 
391
        PRINTK("NFS call  read %d @ %d\n", count, offset);
392
        if (!(p0 = nfs_rpc_alloc(server->rsize)))
393
                return -EIO;
394
retry:
395
        p = nfs_rpc_header(p0, NFSPROC_READ, ruid);
396
        p = xdr_encode_fhandle(p, fhandle);
397
        *p++ = htonl(offset);
398
        *p++ = htonl(count);
399
        *p++ = htonl(count); /* traditional, could be any value */
400
        if ((status = nfs_rpc_call(server, p0, p, server->rsize)) < 0) {
401
                nfs_rpc_free(p0);
402
                return status;
403
        }
404
        if (!(p = nfs_rpc_verify(p0)))
405
                status = -errno_NFSERR_IO;
406
        else if ((status = ntohl(*p++)) == NFS_OK) {
407
                p = xdr_decode_fattr(p, fattr);
408
                if (!(p = xdr_decode_data(p, data, &len, count))) {
409
                        printk("nfs_proc_read: giant data size\n");
410
                        status = -errno_NFSERR_IO;
411
                }
412
                else {
413
                        status = len;
414
                        PRINTK("NFS reply read %d\n", len);
415
                }
416
        }
417
        else {
418
                if (!ruid && current->fsuid == 0 && current->uid != 0) {
419
                        ruid = 1;
420
                        goto retry;
421
                }
422
                PRINTK("NFS reply read failed = %d\n", status);
423
                status = -nfs_stat_to_errno(status);
424
        }
425
        nfs_rpc_free(p0);
426
        return status;
427
}
428
 
429
int
430
nfs_proc_read_request(struct rpc_ioreq *req, struct nfs_server *server,
431
                        struct nfs_fh *fh, unsigned long offset,
432
                        unsigned long count, __u32 *buf)
433
{
434
        __u32   *p, *p0;
435
        int     len;
436
 
437
        PRINTK("NFS reqst read %ld @ %ld\n", count, offset);
438
        if (!(p0 = nfs_rpc_alloc(NFS_SLACK_SPACE)))
439
                return -EIO;
440
 
441
        p = nfs_rpc_header(p0, NFSPROC_READ, 0);
442
        p = xdr_encode_fhandle(p, fh);
443
        *p++ = htonl(offset);
444
        *p++ = htonl(count);
445
        *p++ = htonl(count); /* traditional, could be any value */
446
        req->rq_svec[0].iov_base = p0;
447
        req->rq_svec[0].iov_len  = (p - p0) << 2;
448
        req->rq_slen = (p - p0) << 2;
449
        req->rq_snr = 1;
450
 
451
        len = (6 + 1 + 17 + 1);         /* standard READ reply header */
452
        req->rq_rvec[0].iov_base = p0;
453
        req->rq_rvec[0].iov_len  = len << 2;
454
        req->rq_rvec[1].iov_base = buf;
455
        req->rq_rvec[1].iov_len  = count;
456
        req->rq_rvec[2].iov_base = p0 + len;            /* spill buffer */
457
        req->rq_rvec[2].iov_len  = (NFS_SLACK_SPACE - len) << 2;
458
        req->rq_rlen = count + NFS_SLACK_SPACE;
459
        req->rq_rnr = 3;
460
 
461
        req->rq_addr = &server->toaddr;
462
        req->rq_alen = sizeof(server->toaddr);
463
 
464
        return rpc_transmit(server->rsock, req);
465
}
466
 
467
int
468
nfs_proc_read_reply(struct rpc_ioreq *req, struct nfs_fattr *fattr)
469
{
470
        int             status;
471
        __u32           *p0, *p;
472
        int             count;
473
 
474
        p0 = (__u32 *) req->rq_rvec[0].iov_base;
475
 
476
        if (!(p = nfs_rpc_verify(p0))) {
477
                /* Tell the upper layers to retry */
478
                status = -EAGAIN;
479
                /* status = -errno_NFSERR_IO; */
480
        } else if ((status = ntohl(*p++)) == NFS_OK) {
481
                p = xdr_decode_fattr(p, fattr);
482
                count = ntohl(*p++);
483
                if (p != req->rq_rvec[2].iov_base) {
484
                        /* unexpected RPC reply header size. punt.
485
                         * fixme: move iovec contents to align data
486
                         * on page boundary and adjust RPC header size
487
                         * guess. */
488
                        status = -errno_NFSERR_IO;
489
                        PRINTK("NFS reply read odd header size %d\n",
490
                                        (p - p0) << 2);
491
                } else {
492
                        status = count;
493
                        PRINTK("NFS reply read %d\n", count);
494
                }
495
        }
496
        else {
497
                PRINTK("NFS reply read failed = %d\n", status);
498
                status = -nfs_stat_to_errno(status);
499
        }
500
        nfs_rpc_free(p0);
501
        return status;
502
}
503
 
504
int nfs_proc_write(struct inode * inode, int offset,
505
                   int count, const char *data, struct nfs_fattr *fattr)
506
{
507
        int *p, *p0;
508
        int status;
509
        int ruid = 0;
510
        void * kdata;   /* address of kernel copy */
511
        struct nfs_server * server = NFS_SERVER(inode);
512
        struct nfs_fh *fhandle = NFS_FH(inode);
513
 
514
        PRINTK("NFS call  write %d @ %d\n", count, offset);
515
        if (!(p0 = nfs_rpc_alloc(server->wsize)))
516
                return -EIO;
517
retry:
518
        p = nfs_rpc_header(p0, NFSPROC_WRITE, ruid);
519
        p = xdr_encode_fhandle(p, fhandle);
520
        *p++ = htonl(offset); /* traditional, could be any value */
521
        *p++ = htonl(offset);
522
        *p++ = htonl(count); /* traditional, could be any value */
523
        kdata = (void *) (p+1); /* start of data in RPC buffer */
524
        p = xdr_encode_data(p, data, count);
525
        if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
526
                nfs_rpc_free(p0);
527
                return status;
528
        }
529
        if (!(p = nfs_rpc_verify(p0)))
530
                status = -errno_NFSERR_IO;
531
        else if ((status = ntohl(*p++)) == NFS_OK) {
532
                update_vm_cache(inode, offset, kdata, count);
533
                p = xdr_decode_fattr(p, fattr);
534
                PRINTK("NFS reply write\n");
535
                /* status = 0; */
536
        }
537
        else {
538
                if (!ruid && current->fsuid == 0 && current->uid != 0) {
539
                        ruid = 1;
540
                        goto retry;
541
                }
542
                PRINTK("NFS reply write failed = %d\n", status);
543
                status = -nfs_stat_to_errno(status);
544
        }
545
        nfs_rpc_free(p0);
546
        return status;
547
}
548
 
549
int nfs_proc_create(struct nfs_server *server, struct nfs_fh *dir,
550
                    const char *name, struct nfs_sattr *sattr,
551
                    struct nfs_fh *fhandle, struct nfs_fattr *fattr)
552
{
553
        int *p, *p0;
554
        int status;
555
        int ruid = 0;
556
 
557
        PRINTK("NFS call  create %s\n", name);
558
        if (!(p0 = nfs_rpc_alloc(server->wsize)))
559
                return -EIO;
560
retry:
561
        p = nfs_rpc_header(p0, NFSPROC_CREATE, ruid);
562
        p = xdr_encode_fhandle(p, dir);
563
        p = xdr_encode_string(p, name);
564
        p = xdr_encode_sattr(p, sattr);
565
        if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
566
                nfs_rpc_free(p0);
567
                return status;
568
        }
569
        if (!(p = nfs_rpc_verify(p0)))
570
                status = -errno_NFSERR_IO;
571
        else if ((status = ntohl(*p++)) == NFS_OK) {
572
                p = xdr_decode_fhandle(p, fhandle);
573
                p = xdr_decode_fattr(p, fattr);
574
                PRINTK("NFS reply create\n");
575
                /* status = 0; */
576
        }
577
        else {
578
                if (!ruid && current->fsuid == 0 && current->uid != 0) {
579
                        ruid = 1;
580
                        goto retry;
581
                }
582
                PRINTK("NFS reply create failed = %d\n", status);
583
                status = -nfs_stat_to_errno(status);
584
        }
585
        nfs_rpc_free(p0);
586
        return status;
587
}
588
 
589
int nfs_proc_remove(struct nfs_server *server, struct nfs_fh *dir, const char *name)
590
{
591
        int *p, *p0;
592
        int status;
593
        int ruid = 0;
594
 
595
        PRINTK("NFS call  remove %s\n", name);
596
        if (!(p0 = nfs_rpc_alloc(server->wsize)))
597
                return -EIO;
598
retry:
599
        p = nfs_rpc_header(p0, NFSPROC_REMOVE, ruid);
600
        p = xdr_encode_fhandle(p, dir);
601
        p = xdr_encode_string(p, name);
602
        if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
603
                nfs_rpc_free(p0);
604
                return status;
605
        }
606
        if (!(p = nfs_rpc_verify(p0)))
607
                status = -errno_NFSERR_IO;
608
        else if ((status = ntohl(*p++)) == NFS_OK) {
609
                PRINTK("NFS reply remove\n");
610
                /* status = 0; */
611
        }
612
        else {
613
                if (!ruid && current->fsuid == 0 && current->uid != 0) {
614
                        ruid = 1;
615
                        goto retry;
616
                }
617
                PRINTK("NFS reply remove failed = %d\n", status);
618
                status = -nfs_stat_to_errno(status);
619
        }
620
        nfs_rpc_free(p0);
621
        return status;
622
}
623
 
624
int nfs_proc_rename(struct nfs_server *server,
625
                    struct nfs_fh *old_dir, const char *old_name,
626
                    struct nfs_fh *new_dir, const char *new_name,
627
                    int must_be_dir)
628
{
629
        int *p, *p0;
630
        int status;
631
        int ruid = 0;
632
 
633
        /*
634
         * Disallow "rename()" with trailing slashes over NFS: getting
635
         * POSIX.1 behaviour is just too unlikely.
636
         */
637
        if (must_be_dir)
638
                return -EINVAL;
639
        PRINTK("NFS call  rename %s -> %s\n", old_name, new_name);
640
        if (!(p0 = nfs_rpc_alloc(server->wsize)))
641
                return -EIO;
642
retry:
643
        p = nfs_rpc_header(p0, NFSPROC_RENAME, ruid);
644
        p = xdr_encode_fhandle(p, old_dir);
645
        p = xdr_encode_string(p, old_name);
646
        p = xdr_encode_fhandle(p, new_dir);
647
        p = xdr_encode_string(p, new_name);
648
        if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
649
                nfs_rpc_free(p0);
650
                return status;
651
        }
652
        if (!(p = nfs_rpc_verify(p0)))
653
                status = -errno_NFSERR_IO;
654
        else if ((status = ntohl(*p++)) == NFS_OK) {
655
                PRINTK("NFS reply rename\n");
656
                /* status = 0; */
657
        }
658
        else {
659
                if (!ruid && current->fsuid == 0 && current->uid != 0) {
660
                        ruid = 1;
661
                        goto retry;
662
                }
663
                PRINTK("NFS reply rename failed = %d\n", status);
664
                status = -nfs_stat_to_errno(status);
665
        }
666
        nfs_rpc_free(p0);
667
        return status;
668
}
669
 
670
int nfs_proc_link(struct nfs_server *server, struct nfs_fh *fhandle,
671
                  struct nfs_fh *dir, const char *name)
672
{
673
        int *p, *p0;
674
        int status;
675
        int ruid = 0;
676
 
677
        PRINTK("NFS call  link %s\n", name);
678
        if (!(p0 = nfs_rpc_alloc(server->wsize)))
679
                return -EIO;
680
retry:
681
        p = nfs_rpc_header(p0, NFSPROC_LINK, ruid);
682
        p = xdr_encode_fhandle(p, fhandle);
683
        p = xdr_encode_fhandle(p, dir);
684
        p = xdr_encode_string(p, name);
685
        if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
686
                nfs_rpc_free(p0);
687
                return status;
688
        }
689
        if (!(p = nfs_rpc_verify(p0)))
690
                status = -errno_NFSERR_IO;
691
        else if ((status = ntohl(*p++)) == NFS_OK) {
692
                PRINTK("NFS reply link\n");
693
                /* status = 0; */
694
        }
695
        else {
696
                if (!ruid && current->fsuid == 0 && current->uid != 0) {
697
                        ruid = 1;
698
                        goto retry;
699
                }
700
                PRINTK("NFS reply link failed = %d\n", status);
701
                status = -nfs_stat_to_errno(status);
702
        }
703
        nfs_rpc_free(p0);
704
        return status;
705
}
706
 
707
int nfs_proc_symlink(struct nfs_server *server, struct nfs_fh *dir,
708
                     const char *name, const char *path, struct nfs_sattr *sattr)
709
{
710
        int *p, *p0;
711
        int status;
712
        int ruid = 0;
713
 
714
        PRINTK("NFS call  symlink %s -> %s\n", name, path);
715
        if (!(p0 = nfs_rpc_alloc(server->wsize)))
716
                return -EIO;
717
retry:
718
        p = nfs_rpc_header(p0, NFSPROC_SYMLINK, ruid);
719
        p = xdr_encode_fhandle(p, dir);
720
        p = xdr_encode_string(p, name);
721
        p = xdr_encode_string(p, path);
722
        p = xdr_encode_sattr(p, sattr);
723
        if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
724
                nfs_rpc_free(p0);
725
                return status;
726
        }
727
        if (!(p = nfs_rpc_verify(p0)))
728
                status = -errno_NFSERR_IO;
729
        else if ((status = ntohl(*p++)) == NFS_OK) {
730
                PRINTK("NFS reply symlink\n");
731
                /* status = 0; */
732
        }
733
        else {
734
                if (!ruid && current->fsuid == 0 && current->uid != 0) {
735
                        ruid = 1;
736
                        goto retry;
737
                }
738
                PRINTK("NFS reply symlink failed = %d\n", status);
739
                status = -nfs_stat_to_errno(status);
740
        }
741
        nfs_rpc_free(p0);
742
        return status;
743
}
744
 
745
int nfs_proc_mkdir(struct nfs_server *server, struct nfs_fh *dir,
746
                   const char *name, struct nfs_sattr *sattr,
747
                   struct nfs_fh *fhandle, struct nfs_fattr *fattr)
748
{
749
        int *p, *p0;
750
        int status;
751
        int ruid = 0;
752
 
753
        PRINTK("NFS call  mkdir %s\n", name);
754
        if (!(p0 = nfs_rpc_alloc(server->wsize)))
755
                return -EIO;
756
retry:
757
        p = nfs_rpc_header(p0, NFSPROC_MKDIR, ruid);
758
        p = xdr_encode_fhandle(p, dir);
759
        p = xdr_encode_string(p, name);
760
        p = xdr_encode_sattr(p, sattr);
761
        if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
762
                nfs_rpc_free(p0);
763
                return status;
764
        }
765
        if (!(p = nfs_rpc_verify(p0)))
766
                status = -errno_NFSERR_IO;
767
        else if ((status = ntohl(*p++)) == NFS_OK) {
768
                p = xdr_decode_fhandle(p, fhandle);
769
                p = xdr_decode_fattr(p, fattr);
770
                PRINTK("NFS reply mkdir\n");
771
                /* status = 0; */
772
        }
773
        else {
774
                if (!ruid && current->fsuid == 0 && current->uid != 0) {
775
                        ruid = 1;
776
                        goto retry;
777
                }
778
                PRINTK("NFS reply mkdir failed = %d\n", status);
779
                status = -nfs_stat_to_errno(status);
780
        }
781
        nfs_rpc_free(p0);
782
        return status;
783
}
784
 
785
int nfs_proc_rmdir(struct nfs_server *server, struct nfs_fh *dir, const char *name)
786
{
787
        int *p, *p0;
788
        int status;
789
        int ruid = 0;
790
 
791
        PRINTK("NFS call  rmdir %s\n", name);
792
        if (!(p0 = nfs_rpc_alloc(server->wsize)))
793
                return -EIO;
794
retry:
795
        p = nfs_rpc_header(p0, NFSPROC_RMDIR, ruid);
796
        p = xdr_encode_fhandle(p, dir);
797
        p = xdr_encode_string(p, name);
798
        if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
799
                nfs_rpc_free(p0);
800
                return status;
801
        }
802
        if (!(p = nfs_rpc_verify(p0)))
803
                status = -errno_NFSERR_IO;
804
        else if ((status = ntohl(*p++)) == NFS_OK) {
805
                PRINTK("NFS reply rmdir\n");
806
                /* status = 0; */
807
        }
808
        else {
809
                if (!ruid && current->fsuid == 0 && current->uid != 0) {
810
                        ruid = 1;
811
                        goto retry;
812
                }
813
                PRINTK("NFS reply rmdir failed = %d\n", status);
814
                status = -nfs_stat_to_errno(status);
815
        }
816
        nfs_rpc_free(p0);
817
        return status;
818
}
819
 
820
int nfs_proc_readdir(struct nfs_server *server, struct nfs_fh *fhandle,
821
                     int cookie, int count, struct nfs_entry *entry)
822
{
823
        int *p, *p0;
824
        int status;
825
        int ruid = 0;
826
        int i;
827
        int size;
828
        int eof;
829
 
830
        PRINTK("NFS call  readdir %d @ %d\n", count, cookie);
831
        size = server->rsize;
832
        if (!(p0 = nfs_rpc_alloc(server->rsize)))
833
                return -EIO;
834
retry:
835
        p = nfs_rpc_header(p0, NFSPROC_READDIR, ruid);
836
        p = xdr_encode_fhandle(p, fhandle);
837
        *p++ = htonl(cookie);
838
        *p++ = htonl(size);
839
        if ((status = nfs_rpc_call(server, p0, p, server->rsize)) < 0) {
840
                nfs_rpc_free(p0);
841
                return status;
842
        }
843
        if (!(p = nfs_rpc_verify(p0)))
844
                status = -errno_NFSERR_IO;
845
        else if ((status = ntohl(*p++)) == NFS_OK) {
846
                for (i = 0; i < count && *p++; i++) {
847
                        if (!(p = xdr_decode_entry(p, entry++)))
848
                                break;
849
                }
850
                if (!p) {
851
                        printk("nfs_proc_readdir: giant filename\n");
852
                        status = -errno_NFSERR_IO;
853
                }
854
                else {
855
                        eof = (i == count && !*p++ && *p++)
856
                              || (i < count && *p++);
857
                        if (eof && i)
858
                                entry[-1].eof = 1;
859
                        PRINTK("NFS reply readdir %d %s\n", i,
860
                               eof ? "eof" : "");
861
                        status = i;
862
                }
863
        }
864
        else {
865
                if (!ruid && current->fsuid == 0 && current->uid != 0) {
866
                        ruid = 1;
867
                        goto retry;
868
                }
869
                PRINTK("NFS reply readdir failed = %d\n", status);
870
                status = -nfs_stat_to_errno(status);
871
        }
872
        nfs_rpc_free(p0);
873
        return status;
874
}
875
 
876
int nfs_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
877
                    struct nfs_fsinfo *res)
878
{
879
        int *p, *p0;
880
        int status;
881
        int ruid = 0;
882
 
883
        PRINTK("NFS call  statfs\n");
884
        if (!(p0 = nfs_rpc_alloc(server->rsize)))
885
                return -EIO;
886
retry:
887
        p = nfs_rpc_header(p0, NFSPROC_STATFS, ruid);
888
        p = xdr_encode_fhandle(p, fhandle);
889
        if ((status = nfs_rpc_call(server, p0, p, server->rsize)) < 0) {
890
                nfs_rpc_free(p0);
891
                return status;
892
        }
893
        if (!(p = nfs_rpc_verify(p0)))
894
                status = -errno_NFSERR_IO;
895
        else if ((status = ntohl(*p++)) == NFS_OK) {
896
                p = xdr_decode_fsinfo(p, res);
897
                PRINTK("NFS reply statfs\n");
898
                /* status = 0; */
899
        }
900
        else {
901
                if (!ruid && current->fsuid == 0 && current->uid != 0) {
902
                        ruid = 1;
903
                        goto retry;
904
                }
905
                PRINTK("NFS reply statfs failed = %d\n", status);
906
                status = -nfs_stat_to_errno(status);
907
        }
908
        nfs_rpc_free(p0);
909
        return status;
910
}
911
 
912
/*
913
 * Here are a few RPC-assist functions.
914
 */
915
 
916
int *rpc_header(int *p, int procedure, int program, int version,
917
                                        int uid, int gid, int *groups)
918
{
919
        int *p1, *p2;
920
        int i;
921
        static int xid = 0;
922
        unsigned char *sys = (unsigned char *) system_utsname.nodename;
923
 
924
        if (xid == 0) {
925
                xid = CURRENT_TIME;
926
                xid ^= (sys[3]<<24) | (sys[2]<<16) | (sys[1]<<8) | sys[0];
927
        }
928
        *p++ = htonl(++xid);
929
        *p++ = htonl(RPC_CALL);
930
        *p++ = htonl(RPC_VERSION);
931
        *p++ = htonl(program);
932
        *p++ = htonl(version);
933
        *p++ = htonl(procedure);
934
        *p++ = htonl(RPC_AUTH_UNIX);
935
        p1 = p++;
936
        *p++ = htonl(CURRENT_TIME); /* traditional, could be anything */
937
        p = xdr_encode_string(p, (char *) sys);
938
        *p++ = htonl(uid);
939
        *p++ = htonl(gid);
940
        p2 = p++;
941
        for (i = 0; i < 16 && i < NGROUPS && groups[i] != NOGROUP; i++)
942
                *p++ = htonl(groups[i]);
943
        *p2 = htonl(i);
944
        *p1 = htonl((p - (p1 + 1)) << 2);
945
        *p++ = htonl(RPC_AUTH_NULL);
946
        *p++ = htonl(0);
947
        return p;
948
}
949
 
950
 
951
static int *nfs_rpc_header(int *p, int procedure, int ruid)
952
{
953
        return rpc_header(p, procedure, NFS_PROGRAM, NFS_VERSION,
954
                        (ruid ? current->uid : current->fsuid),
955
                        current->egid, current->groups);
956
}
957
 
958
 
959
int *rpc_verify(int *p)
960
{
961
        unsigned int n;
962
 
963
        p++;
964
        if ((n = ntohl(*p++)) != RPC_REPLY) {
965
                printk("nfs_rpc_verify: not an RPC reply: %x\n", n);
966
                return NULL;
967
        }
968
        if ((n = ntohl(*p++)) != RPC_MSG_ACCEPTED) {
969
                printk("nfs_rpc_verify: RPC call rejected: %d\n", n);
970
                return NULL;
971
        }
972
        switch (n = ntohl(*p++)) {
973
        case RPC_AUTH_NULL: case RPC_AUTH_UNIX: case RPC_AUTH_SHORT:
974
                break;
975
        default:
976
                printk("nfs_rpc_verify: bad RPC authentication type: %d\n", n);
977
                return NULL;
978
        }
979
        if ((n = ntohl(*p++)) > 400) {
980
                printk("nfs_rpc_verify: giant auth size\n");
981
                return NULL;
982
        }
983
        p += QUADLEN(n);
984
        if ((n = ntohl(*p++)) != RPC_SUCCESS) {
985
                printk("nfs_rpc_verify: RPC call failed: %d\n", n);
986
                return NULL;
987
        }
988
        return p;
989
}
990
 
991
 
992
static int *nfs_rpc_verify(int *p)
993
{
994
        return rpc_verify(p);
995
}
996
 
997
 
998
/*
999
 * We need to translate between nfs status return values and
1000
 * the local errno values which may not be the same.
1001
 */
1002
 
1003
static struct {
1004
        int stat;
1005
        int errno;
1006
} nfs_errtbl[] = {
1007
        { NFS_OK,               0                },
1008
        { NFSERR_PERM,          EPERM           },
1009
        { NFSERR_NOENT,         ENOENT          },
1010
        { NFSERR_IO,            errno_NFSERR_IO },
1011
        { NFSERR_NXIO,          ENXIO           },
1012
        { NFSERR_EAGAIN,        EAGAIN          },
1013
        { NFSERR_ACCES,         EACCES          },
1014
        { NFSERR_EXIST,         EEXIST          },
1015
        { NFSERR_XDEV,          EXDEV           },
1016
        { NFSERR_NODEV,         ENODEV          },
1017
        { NFSERR_NOTDIR,        ENOTDIR         },
1018
        { NFSERR_ISDIR,         EISDIR          },
1019
        { NFSERR_INVAL,         EINVAL          },
1020
        { NFSERR_FBIG,          EFBIG           },
1021
        { NFSERR_NOSPC,         ENOSPC          },
1022
        { NFSERR_ROFS,          EROFS           },
1023
        { NFSERR_NAMETOOLONG,   ENAMETOOLONG    },
1024
        { NFSERR_NOTEMPTY,      ENOTEMPTY       },
1025
        { NFSERR_DQUOT,         EDQUOT          },
1026
        { NFSERR_STALE,         ESTALE          },
1027
#ifdef EWFLUSH
1028
        { NFSERR_WFLUSH,        EWFLUSH         },
1029
#endif
1030
        { -1,                   EIO             }
1031
};
1032
 
1033
static int nfs_stat_to_errno(int stat)
1034
{
1035
        int i;
1036
 
1037
        for (i = 0; nfs_errtbl[i].stat != -1; i++) {
1038
                if (nfs_errtbl[i].stat == stat)
1039
                        return nfs_errtbl[i].errno;
1040
        }
1041
        printk("nfs_stat_to_errno: bad nfs status return value: %d\n", stat);
1042
        return nfs_errtbl[i].errno;
1043
}
1044
 

powered by: WebSVN 2.1.0

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