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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *  linux/fs/nfs/nfs3proc.c
3
 *
4
 *  Client-side NFSv3 procedures stubs.
5
 *
6
 *  Copyright (C) 1997, Olaf Kirch
7
 */
8
 
9
#include <linux/mm.h>
10
#include <linux/utsname.h>
11
#include <linux/errno.h>
12
#include <linux/string.h>
13
#include <linux/sunrpc/clnt.h>
14
#include <linux/nfs.h>
15
#include <linux/nfs3.h>
16
#include <linux/nfs_fs.h>
17
 
18
#define NFSDBG_FACILITY         NFSDBG_PROC
19
 
20
/* A wrapper to handle the EJUKEBOX error message */
21
static int
22
nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
23
{
24
        sigset_t oldset;
25
        int res;
26
        rpc_clnt_sigmask(clnt, &oldset);
27
        do {
28
                res = rpc_call_sync(clnt, msg, flags);
29
                if (res != -EJUKEBOX)
30
                        break;
31
                set_current_state(TASK_INTERRUPTIBLE);
32
                schedule_timeout(NFS_JUKEBOX_RETRY_TIME);
33
                res = -ERESTARTSYS;
34
        } while (!signalled());
35
        rpc_clnt_sigunmask(clnt, &oldset);
36
        return res;
37
}
38
 
39
static inline int
40
nfs3_rpc_call_wrapper(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp, int flags)
41
{
42
        struct rpc_message msg = { proc, argp, resp, NULL };
43
        return nfs3_rpc_wrapper(clnt, &msg, flags);
44
}
45
 
46
#define rpc_call(clnt, proc, argp, resp, flags) \
47
                nfs3_rpc_call_wrapper(clnt, proc, argp, resp, flags)
48
#define rpc_call_sync(clnt, msg, flags) \
49
                nfs3_rpc_wrapper(clnt, msg, flags)
50
 
51
/*
52
 * Bare-bones access to getattr: this is for nfs_read_super.
53
 */
54
static int
55
nfs3_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
56
                   struct nfs_fattr *fattr)
57
{
58
        int     status;
59
 
60
        dprintk("NFS call  getroot\n");
61
        fattr->valid = 0;
62
        status = rpc_call(server->client, NFS3PROC_GETATTR, fhandle, fattr, 0);
63
        dprintk("NFS reply getroot\n");
64
        return status;
65
}
66
 
67
/*
68
 * One function for each procedure in the NFS protocol.
69
 */
70
static int
71
nfs3_proc_getattr(struct inode *inode, struct nfs_fattr *fattr)
72
{
73
        int     status;
74
 
75
        dprintk("NFS call  getattr\n");
76
        fattr->valid = 0;
77
        status = rpc_call(NFS_CLIENT(inode), NFS3PROC_GETATTR,
78
                          NFS_FH(inode), fattr, 0);
79
        dprintk("NFS reply getattr\n");
80
        return status;
81
}
82
 
83
static int
84
nfs3_proc_setattr(struct inode *inode, struct nfs_fattr *fattr,
85
                        struct iattr *sattr)
86
{
87
        struct nfs3_sattrargs   arg = { NFS_FH(inode), sattr, 0, 0 };
88
        int     status;
89
 
90
        dprintk("NFS call  setattr\n");
91
        fattr->valid = 0;
92
        status = rpc_call(NFS_CLIENT(inode), NFS3PROC_SETATTR, &arg, fattr, 0);
93
        dprintk("NFS reply setattr\n");
94
        return status;
95
}
96
 
97
static int
98
nfs3_proc_lookup(struct inode *dir, struct qstr *name,
99
                 struct nfs_fh *fhandle, struct nfs_fattr *fattr)
100
{
101
        struct nfs_fattr        dir_attr;
102
        struct nfs3_diropargs   arg = { NFS_FH(dir), name->name, name->len };
103
        struct nfs3_diropres    res = { &dir_attr, fhandle, fattr };
104
        int                     status;
105
 
106
        dprintk("NFS call  lookup %s\n", name->name);
107
        dir_attr.valid = 0;
108
        fattr->valid = 0;
109
        status = rpc_call(NFS_CLIENT(dir), NFS3PROC_LOOKUP, &arg, &res, 0);
110
        if (status >= 0 && !(fattr->valid & NFS_ATTR_FATTR))
111
                status = rpc_call(NFS_CLIENT(dir), NFS3PROC_GETATTR,
112
                         fhandle, fattr, 0);
113
        dprintk("NFS reply lookup: %d\n", status);
114
        if (status >= 0)
115
                status = nfs_refresh_inode(dir, &dir_attr);
116
        return status;
117
}
118
 
119
static int
120
nfs3_proc_access(struct inode *inode, int mode, int ruid)
121
{
122
        struct nfs_fattr        fattr;
123
        struct nfs3_accessargs  arg = { NFS_FH(inode), 0 };
124
        struct nfs3_accessres   res = { &fattr, 0 };
125
        int     status, flags;
126
 
127
        dprintk("NFS call  access\n");
128
        fattr.valid = 0;
129
 
130
        if (mode & MAY_READ)
131
                arg.access |= NFS3_ACCESS_READ;
132
        if (S_ISDIR(inode->i_mode)) {
133
                if (mode & MAY_WRITE)
134
                        arg.access |= NFS3_ACCESS_MODIFY | NFS3_ACCESS_EXTEND | NFS3_ACCESS_DELETE;
135
                if (mode & MAY_EXEC)
136
                        arg.access |= NFS3_ACCESS_LOOKUP;
137
        } else {
138
                if (mode & MAY_WRITE)
139
                        arg.access |= NFS3_ACCESS_MODIFY | NFS3_ACCESS_EXTEND;
140
                if (mode & MAY_EXEC)
141
                        arg.access |= NFS3_ACCESS_EXECUTE;
142
        }
143
        flags = (ruid) ? RPC_CALL_REALUID : 0;
144
        status = rpc_call(NFS_CLIENT(inode), NFS3PROC_ACCESS, &arg, &res, flags);
145
        nfs_refresh_inode(inode, &fattr);
146
        dprintk("NFS reply access\n");
147
 
148
        if (status == 0 && (arg.access & res.access) != arg.access)
149
                status = -EACCES;
150
        return status;
151
}
152
 
153
static int
154
nfs3_proc_readlink(struct inode *inode, struct page *page)
155
{
156
        struct nfs_fattr        fattr;
157
        struct nfs3_readlinkargs args = { NFS_FH(inode), PAGE_CACHE_SIZE, &page };
158
        int                     status;
159
 
160
        dprintk("NFS call  readlink\n");
161
        fattr.valid = 0;
162
        status = rpc_call(NFS_CLIENT(inode), NFS3PROC_READLINK,
163
                        &args, &fattr, 0);
164
        nfs_refresh_inode(inode, &fattr);
165
        dprintk("NFS reply readlink: %d\n", status);
166
        return status;
167
}
168
 
169
static int
170
nfs3_proc_read(struct inode *inode, struct rpc_cred *cred,
171
               struct nfs_fattr *fattr, int flags,
172
               unsigned int base, unsigned int count, struct page *page,
173
               int *eofp)
174
{
175
        u64                     offset = page_offset(page) + base;
176
        struct nfs_readargs     arg = { NFS_FH(inode), offset, count,
177
                                        base, &page };
178
        struct nfs_readres      res = { fattr, count, 0 };
179
        struct rpc_message      msg = { NFS3PROC_READ, &arg, &res, cred };
180
        int                     status;
181
 
182
        dprintk("NFS call  read %d @ %Ld\n", count, (long long)offset);
183
        fattr->valid = 0;
184
        status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags);
185
        dprintk("NFS reply read: %d\n", status);
186
        *eofp = res.eof;
187
        return status;
188
}
189
 
190
static int
191
nfs3_proc_write(struct inode *inode, struct rpc_cred *cred,
192
                struct nfs_fattr *fattr, int flags,
193
                unsigned int base, unsigned int count,
194
                struct page *page, struct nfs_writeverf *verf)
195
{
196
        u64                     offset = page_offset(page) + base;
197
        struct nfs_writeargs    arg = { NFS_FH(inode), offset, count,
198
                                        NFS_FILE_SYNC, base, &page };
199
        struct nfs_writeres     res = { fattr, verf, 0 };
200
        struct rpc_message      msg = { NFS3PROC_WRITE, &arg, &res, cred };
201
        int                     status, rpcflags = 0;
202
 
203
        dprintk("NFS call  write %d @ %Ld\n", count, (long long)offset);
204
        fattr->valid = 0;
205
        if (flags & NFS_RW_SWAP)
206
                rpcflags |= NFS_RPC_SWAPFLAGS;
207
        arg.stable = (flags & NFS_RW_SYNC) ? NFS_FILE_SYNC : NFS_UNSTABLE;
208
 
209
        status = rpc_call_sync(NFS_CLIENT(inode), &msg, rpcflags);
210
 
211
        dprintk("NFS reply read: %d\n", status);
212
        return status < 0? status : res.count;
213
}
214
 
215
/*
216
 * Create a regular file.
217
 * For now, we don't implement O_EXCL.
218
 */
219
static int
220
nfs3_proc_create(struct inode *dir, struct qstr *name, struct iattr *sattr,
221
                 int flags, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
222
{
223
        struct nfs_fattr        dir_attr;
224
        struct nfs3_createargs  arg = { NFS_FH(dir), name->name, name->len,
225
                                        sattr, 0, { 0, 0 } };
226
        struct nfs3_diropres    res = { &dir_attr, fhandle, fattr };
227
        int                     status;
228
 
229
        dprintk("NFS call  create %s\n", name->name);
230
        arg.createmode = NFS3_CREATE_UNCHECKED;
231
        if (flags & O_EXCL) {
232
                arg.createmode  = NFS3_CREATE_EXCLUSIVE;
233
                arg.verifier[0] = jiffies;
234
                arg.verifier[1] = current->pid;
235
        }
236
 
237
again:
238
        dir_attr.valid = 0;
239
        fattr->valid = 0;
240
        status = rpc_call(NFS_CLIENT(dir), NFS3PROC_CREATE, &arg, &res, 0);
241
        nfs_refresh_inode(dir, &dir_attr);
242
 
243
        /* If the server doesn't support the exclusive creation semantics,
244
         * try again with simple 'guarded' mode. */
245
        if (status == NFSERR_NOTSUPP) {
246
                switch (arg.createmode) {
247
                        case NFS3_CREATE_EXCLUSIVE:
248
                                arg.createmode = NFS3_CREATE_GUARDED;
249
                                break;
250
 
251
                        case NFS3_CREATE_GUARDED:
252
                                arg.createmode = NFS3_CREATE_UNCHECKED;
253
                                break;
254
 
255
                        case NFS3_CREATE_UNCHECKED:
256
                                goto exit;
257
                }
258
                goto again;
259
        }
260
 
261
exit:
262
        dprintk("NFS reply create: %d\n", status);
263
 
264
        /* When we created the file with exclusive semantics, make
265
         * sure we set the attributes afterwards. */
266
        if (status == 0 && arg.createmode == NFS3_CREATE_EXCLUSIVE) {
267
                struct nfs3_sattrargs   arg = { fhandle, sattr, 0, 0 };
268
                dprintk("NFS call  setattr (post-create)\n");
269
 
270
                /* Note: we could use a guarded setattr here, but I'm
271
                 * not sure this buys us anything (and I'd have
272
                 * to revamp the NFSv3 XDR code) */
273
                fattr->valid = 0;
274
                status = rpc_call(NFS_CLIENT(dir), NFS3PROC_SETATTR,
275
                                                &arg, fattr, 0);
276
                dprintk("NFS reply setattr (post-create): %d\n", status);
277
        }
278
 
279
        return status;
280
}
281
 
282
static int
283
nfs3_proc_remove(struct inode *dir, struct qstr *name)
284
{
285
        struct nfs_fattr        dir_attr;
286
        struct nfs3_diropargs   arg = { NFS_FH(dir), name->name, name->len };
287
        struct rpc_message      msg = { NFS3PROC_REMOVE, &arg, &dir_attr, NULL };
288
        int                     status;
289
 
290
        dprintk("NFS call  remove %s\n", name->name);
291
        dir_attr.valid = 0;
292
        status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
293
        nfs_refresh_inode(dir, &dir_attr);
294
        dprintk("NFS reply remove: %d\n", status);
295
        return status;
296
}
297
 
298
static int
299
nfs3_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir, struct qstr *name)
300
{
301
        struct nfs3_diropargs   *arg;
302
        struct nfs_fattr        *res;
303
        struct unlinkxdr {
304
                struct nfs3_diropargs arg;
305
                struct nfs_fattr res;
306
        } *ptr;
307
 
308
        ptr = (struct unlinkxdr *)kmalloc(sizeof(*ptr), GFP_KERNEL);
309
        if (!ptr)
310
                return -ENOMEM;
311
        arg = &ptr->arg;
312
        res = &ptr->res;
313
        arg->fh = NFS_FH(dir->d_inode);
314
        arg->name = name->name;
315
        arg->len = name->len;
316
        res->valid = 0;
317
        msg->rpc_proc = NFS3PROC_REMOVE;
318
        msg->rpc_argp = arg;
319
        msg->rpc_resp = res;
320
        return 0;
321
}
322
 
323
static void
324
nfs3_proc_unlink_done(struct dentry *dir, struct rpc_message *msg)
325
{
326
        struct nfs_fattr        *dir_attr;
327
 
328
        if (msg->rpc_argp) {
329
                dir_attr = (struct nfs_fattr*)msg->rpc_resp;
330
                nfs_refresh_inode(dir->d_inode, dir_attr);
331
                kfree(msg->rpc_argp);
332
        }
333
}
334
 
335
static int
336
nfs3_proc_rename(struct inode *old_dir, struct qstr *old_name,
337
                 struct inode *new_dir, struct qstr *new_name)
338
{
339
        struct nfs_fattr        old_dir_attr, new_dir_attr;
340
        struct nfs3_renameargs  arg = { NFS_FH(old_dir),
341
                                        old_name->name, old_name->len,
342
                                        NFS_FH(new_dir),
343
                                        new_name->name, new_name->len };
344
        struct nfs3_renameres   res = { &old_dir_attr, &new_dir_attr };
345
        int                     status;
346
 
347
        dprintk("NFS call  rename %s -> %s\n", old_name->name, new_name->name);
348
        old_dir_attr.valid = 0;
349
        new_dir_attr.valid = 0;
350
        status = rpc_call(NFS_CLIENT(old_dir), NFS3PROC_RENAME, &arg, &res, 0);
351
        nfs_refresh_inode(old_dir, &old_dir_attr);
352
        nfs_refresh_inode(new_dir, &new_dir_attr);
353
        dprintk("NFS reply rename: %d\n", status);
354
        return status;
355
}
356
 
357
static int
358
nfs3_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
359
{
360
        struct nfs_fattr        dir_attr, fattr;
361
        struct nfs3_linkargs    arg = { NFS_FH(inode), NFS_FH(dir),
362
                                        name->name, name->len };
363
        struct nfs3_linkres     res = { &dir_attr, &fattr };
364
        int                     status;
365
 
366
        dprintk("NFS call  link %s\n", name->name);
367
        dir_attr.valid = 0;
368
        fattr.valid = 0;
369
        status = rpc_call(NFS_CLIENT(inode), NFS3PROC_LINK, &arg, &res, 0);
370
        nfs_refresh_inode(dir, &dir_attr);
371
        nfs_refresh_inode(inode, &fattr);
372
        dprintk("NFS reply link: %d\n", status);
373
        return status;
374
}
375
 
376
static int
377
nfs3_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path,
378
                  struct iattr *sattr, struct nfs_fh *fhandle,
379
                  struct nfs_fattr *fattr)
380
{
381
        struct nfs_fattr        dir_attr;
382
        struct nfs3_symlinkargs arg = { NFS_FH(dir), name->name, name->len,
383
                                        path->name, path->len, sattr };
384
        struct nfs3_diropres    res = { &dir_attr, fhandle, fattr };
385
        int                     status;
386
 
387
        dprintk("NFS call  symlink %s -> %s\n", name->name, path->name);
388
        dir_attr.valid = 0;
389
        fattr->valid = 0;
390
        status = rpc_call(NFS_CLIENT(dir), NFS3PROC_SYMLINK, &arg, &res, 0);
391
        nfs_refresh_inode(dir, &dir_attr);
392
        dprintk("NFS reply symlink: %d\n", status);
393
        return status;
394
}
395
 
396
static int
397
nfs3_proc_mkdir(struct inode *dir, struct qstr *name, struct iattr *sattr,
398
                struct nfs_fh *fhandle, struct nfs_fattr *fattr)
399
{
400
        struct nfs_fattr        dir_attr;
401
        struct nfs3_mkdirargs   arg = { NFS_FH(dir), name->name, name->len,
402
                                        sattr };
403
        struct nfs3_diropres    res = { &dir_attr, fhandle, fattr };
404
        int                     status;
405
 
406
        dprintk("NFS call  mkdir %s\n", name->name);
407
        dir_attr.valid = 0;
408
        fattr->valid = 0;
409
        status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKDIR, &arg, &res, 0);
410
        nfs_refresh_inode(dir, &dir_attr);
411
        dprintk("NFS reply mkdir: %d\n", status);
412
        return status;
413
}
414
 
415
static int
416
nfs3_proc_rmdir(struct inode *dir, struct qstr *name)
417
{
418
        struct nfs_fattr        dir_attr;
419
        struct nfs3_diropargs   arg = { NFS_FH(dir), name->name, name->len };
420
        int                     status;
421
 
422
        dprintk("NFS call  rmdir %s\n", name->name);
423
        dir_attr.valid = 0;
424
        status = rpc_call(NFS_CLIENT(dir), NFS3PROC_RMDIR, &arg, &dir_attr, 0);
425
        nfs_refresh_inode(dir, &dir_attr);
426
        dprintk("NFS reply rmdir: %d\n", status);
427
        return status;
428
}
429
 
430
/*
431
 * The READDIR implementation is somewhat hackish - we pass the user buffer
432
 * to the encode function, which installs it in the receive iovec.
433
 * The decode function itself doesn't perform any decoding, it just makes
434
 * sure the reply is syntactically correct.
435
 *
436
 */
437
static int
438
nfs3_proc_readdir(struct inode *dir, struct rpc_cred *cred,
439
                  u64 cookie, struct page *page, unsigned int count, int plus)
440
{
441
        struct nfs_fattr        dir_attr;
442
        u32                     *verf = NFS_COOKIEVERF(dir);
443
        struct nfs3_readdirargs arg = { NFS_FH(dir), cookie, {verf[0], verf[1]},
444
                                        plus, count, &page };
445
        struct nfs3_readdirres  res = { &dir_attr, verf, plus };
446
        struct rpc_message      msg = { NFS3PROC_READDIR, &arg, &res, cred };
447
        int                     status;
448
 
449
        dprintk("NFS call  readdir %d\n", (unsigned int) cookie);
450
 
451
        dir_attr.valid = 0;
452
        status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
453
        nfs_refresh_inode(dir, &dir_attr);
454
        dprintk("NFS reply readdir: %d\n", status);
455
        return status;
456
}
457
 
458
static int
459
nfs3_proc_mknod(struct inode *dir, struct qstr *name, struct iattr *sattr,
460
                dev_t rdev, struct nfs_fh *fh, struct nfs_fattr *fattr)
461
{
462
        struct nfs_fattr        dir_attr;
463
        struct nfs3_mknodargs   arg = { NFS_FH(dir), name->name, name->len, 0,
464
                                        sattr, rdev };
465
        struct nfs3_diropres    res = { &dir_attr, fh, fattr };
466
        int                     status;
467
 
468
        switch (sattr->ia_mode & S_IFMT) {
469
        case S_IFBLK:   arg.type = NF3BLK;  break;
470
        case S_IFCHR:   arg.type = NF3CHR;  break;
471
        case S_IFIFO:   arg.type = NF3FIFO; break;
472
        case S_IFSOCK:  arg.type = NF3SOCK; break;
473
        default:        return -EINVAL;
474
        }
475
 
476
        dprintk("NFS call  mknod %s %x\n", name->name, rdev);
477
        dir_attr.valid = 0;
478
        fattr->valid = 0;
479
        status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKNOD, &arg, &res, 0);
480
        nfs_refresh_inode(dir, &dir_attr);
481
        dprintk("NFS reply mknod: %d\n", status);
482
        return status;
483
}
484
 
485
/*
486
 * This is a combo call of fsstat and fsinfo
487
 */
488
static int
489
nfs3_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
490
                 struct nfs_fsinfo *info)
491
{
492
        int     status;
493
 
494
        dprintk("NFS call  fsstat\n");
495
        memset((char *)info, 0, sizeof(*info));
496
        status = rpc_call(server->client, NFS3PROC_FSSTAT, fhandle, info, 0);
497
        if (status < 0)
498
                goto error;
499
        status = rpc_call(server->client, NFS3PROC_FSINFO, fhandle, info, 0);
500
 
501
error:
502
        dprintk("NFS reply statfs: %d\n", status);
503
        return status;
504
}
505
 
506
extern u32 *nfs3_decode_dirent(u32 *, struct nfs_entry *, int);
507
 
508
struct nfs_rpc_ops      nfs_v3_clientops = {
509
        3,                      /* protocol version */
510
        nfs3_proc_get_root,
511
        nfs3_proc_getattr,
512
        nfs3_proc_setattr,
513
        nfs3_proc_lookup,
514
        nfs3_proc_access,
515
        nfs3_proc_readlink,
516
        nfs3_proc_read,
517
        nfs3_proc_write,
518
        NULL,                   /* commit */
519
        nfs3_proc_create,
520
        nfs3_proc_remove,
521
        nfs3_proc_unlink_setup,
522
        nfs3_proc_unlink_done,
523
        nfs3_proc_rename,
524
        nfs3_proc_link,
525
        nfs3_proc_symlink,
526
        nfs3_proc_mkdir,
527
        nfs3_proc_rmdir,
528
        nfs3_proc_readdir,
529
        nfs3_proc_mknod,
530
        nfs3_proc_statfs,
531
        nfs3_decode_dirent,
532
};

powered by: WebSVN 2.1.0

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