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

Subversion Repositories or1k

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

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

Line No. Rev Author Line
1 1628 jcastillo
/*
2
 *  linux/fs/nfs/inode.c
3
 *
4
 *  Copyright (C) 1992  Rick Sladkey
5
 *
6
 *  nfs inode and superblock handling functions
7
 *
8
 *  Modularised by Alan Cox <Alan.Cox@linux.org>, while hacking some
9
 *  experimental NFS changes. Modularisation taken straight from SYS5 fs.
10
 *
11
 *  Change to nfs_read_super() to permit NFS mounts to multi-homed hosts.
12
 *  J.S.Peatfield@damtp.cam.ac.uk
13
 *
14
 */
15
 
16
#include <linux/module.h>
17
 
18
#include <linux/sched.h>
19
#include <linux/nfs_fs.h>
20
#include <linux/nfsiod.h>
21
#include <linux/kernel.h>
22
#include <linux/mm.h>
23
#include <linux/string.h>
24
#include <linux/stat.h>
25
#include <linux/errno.h>
26
#include <linux/locks.h>
27
#include <linux/smp.h>
28
#include <linux/smp_lock.h>
29
 
30
#include <asm/system.h>
31
#include <asm/segment.h>
32
 
33
/* This is for kernel_thread */
34
#define __KERNEL_SYSCALLS__
35
#include <linux/unistd.h>
36
 
37
extern int close_fp(struct file *filp);
38
 
39
static int nfs_notify_change(struct inode *, struct iattr *);
40
static void nfs_put_inode(struct inode *);
41
static void nfs_put_super(struct super_block *);
42
static void nfs_read_inode(struct inode *);
43
static void nfs_statfs(struct super_block *, struct statfs *, int bufsiz);
44
 
45
static struct super_operations nfs_sops = {
46
        nfs_read_inode,         /* read inode */
47
        nfs_notify_change,      /* notify change */
48
        NULL,                   /* write inode */
49
        nfs_put_inode,          /* put inode */
50
        nfs_put_super,          /* put superblock */
51
        NULL,                   /* write superblock */
52
        nfs_statfs,             /* stat filesystem */
53
        NULL
54
};
55
 
56
/*
57
 * The "read_inode" function doesn't actually do anything:
58
 * the real data is filled in later in nfs_fhget. Here we
59
 * just mark the cache times invalid, and zero out i_mode
60
 * (the latter makes "nfs_refresh_inode" do the right thing
61
 * wrt pipe inodes)
62
 */
63
static void nfs_read_inode(struct inode * inode)
64
{
65
        int rsize = inode->i_sb->u.nfs_sb.s_server.rsize;
66
        int size = inode->i_sb->u.nfs_sb.s_server.wsize;
67
 
68
        if (rsize > size)
69
                size = rsize;
70
        inode->i_blksize = size;
71
        inode->i_mode = 0;
72
        inode->i_op = NULL;
73
        NFS_CACHEINV(inode);
74
}
75
 
76
static void nfs_put_inode(struct inode * inode)
77
{
78
        if (NFS_RENAMED_DIR(inode))
79
                nfs_sillyrename_cleanup(inode);
80
        if (inode->i_pipe)
81
                clear_inode(inode);
82
}
83
 
84
void nfs_put_super(struct super_block *sb)
85
{
86
        close_fp(sb->u.nfs_sb.s_server.file);
87
        rpc_closesock(sb->u.nfs_sb.s_server.rsock);
88
        lock_super(sb);
89
        sb->s_dev = 0;
90
        unlock_super(sb);
91
        MOD_DEC_USE_COUNT;
92
}
93
 
94
/*
95
 * The way this works is that the mount process passes a structure
96
 * in the data argument which contains an open socket to the NFS
97
 * server and the root file handle obtained from the server's mount
98
 * daemon.  We stash these away in the private superblock fields.
99
 * Later we can add other mount parameters like caching values.
100
 */
101
 
102
struct super_block *nfs_read_super(struct super_block *sb, void *raw_data,
103
                                   int silent)
104
{
105
        struct nfs_mount_data *data = (struct nfs_mount_data *) raw_data;
106
        struct nfs_server *server;
107
        unsigned int fd;
108
        struct file *filp;
109
 
110
        kdev_t dev = sb->s_dev;
111
 
112
        MOD_INC_USE_COUNT;
113
        if (!data) {
114
                printk("nfs_read_super: missing data argument\n");
115
                sb->s_dev = 0;
116
                MOD_DEC_USE_COUNT;
117
                return NULL;
118
        }
119
        fd = data->fd;
120
        if (data->version != NFS_MOUNT_VERSION) {
121
                printk("nfs warning: mount version %s than kernel\n",
122
                        data->version < NFS_MOUNT_VERSION ? "older" : "newer");
123
        }
124
        if (fd >= NR_OPEN || !(filp = current->files->fd[fd])) {
125
                printk("nfs_read_super: invalid file descriptor\n");
126
                sb->s_dev = 0;
127
                MOD_DEC_USE_COUNT;
128
                return NULL;
129
        }
130
        if (!S_ISSOCK(filp->f_inode->i_mode)) {
131
                printk("nfs_read_super: not a socket\n");
132
                sb->s_dev = 0;
133
                MOD_DEC_USE_COUNT;
134
                return NULL;
135
        }
136
        filp->f_count++;
137
        lock_super(sb);
138
 
139
        sb->s_blocksize = 1024; /* XXX */
140
        sb->s_blocksize_bits = 10;
141
        sb->s_magic = NFS_SUPER_MAGIC;
142
        sb->s_dev = dev;
143
        sb->s_op = &nfs_sops;
144
        server = &sb->u.nfs_sb.s_server;
145
        server->file = filp;
146
        server->lock = 0;
147
        server->wait = NULL;
148
        server->flags = data->flags;
149
        server->rsize = data->rsize;
150
        if (server->rsize <= 0)
151
                server->rsize = NFS_DEF_FILE_IO_BUFFER_SIZE;
152
        else if (server->rsize >= NFS_MAX_FILE_IO_BUFFER_SIZE)
153
                server->rsize = NFS_MAX_FILE_IO_BUFFER_SIZE;
154
        server->wsize = data->wsize;
155
        if (server->wsize <= 0)
156
                server->wsize = NFS_DEF_FILE_IO_BUFFER_SIZE;
157
        else if (server->wsize >= NFS_MAX_FILE_IO_BUFFER_SIZE)
158
                server->wsize = NFS_MAX_FILE_IO_BUFFER_SIZE;
159
        server->timeo = data->timeo*HZ/10;
160
        server->retrans = data->retrans;
161
        server->acregmin = data->acregmin*HZ;
162
        server->acregmax = data->acregmax*HZ;
163
        server->acdirmin = data->acdirmin*HZ;
164
        server->acdirmax = data->acdirmax*HZ;
165
        strcpy(server->hostname, data->hostname);
166
 
167
        /* Start of JSP NFS patch */
168
        /* Check if passed address in data->addr */
169
        if (data->addr.sin_addr.s_addr == INADDR_ANY) {  /* No address passed */
170
          if (((struct sockaddr_in *)(&server->toaddr))->sin_addr.s_addr == INADDR_ANY) {
171
            printk("NFS: Error passed unconnected socket and no address\n") ;
172
            MOD_DEC_USE_COUNT;
173
            return NULL ;
174
          } else {
175
            /* Need access to socket internals  JSP */
176
            struct socket *sock;
177
            int dummylen ;
178
 
179
         /*   printk("NFS: using socket address\n") ;*/
180
 
181
            sock = &((filp->f_inode)->u.socket_i);
182
 
183
            /* extract the other end of the socket into server->toaddr */
184
            sock->ops->getname(sock, &(server->toaddr), &dummylen, 1) ;
185
          }
186
        } else {
187
        /*  printk("NFS: copying passed addr to server->toaddr\n") ;*/
188
          memcpy((char *)&(server->toaddr),(char *)(&data->addr),sizeof(server->toaddr));
189
        }
190
        /* End of JSP NFS patch */
191
 
192
        if ((server->rsock = rpc_makesock(filp)) == NULL) {
193
                printk("NFS: cannot create RPC socket.\n");
194
                MOD_DEC_USE_COUNT;
195
                return NULL;
196
        }
197
 
198
        sb->u.nfs_sb.s_root = data->root;
199
        unlock_super(sb);
200
        if (!(sb->s_mounted = nfs_fhget(sb, &data->root, NULL))) {
201
                sb->s_dev = 0;
202
                printk("nfs_read_super: get root inode failed\n");
203
                MOD_DEC_USE_COUNT;
204
                return NULL;
205
        }
206
        return sb;
207
}
208
 
209
void nfs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
210
{
211
        int error;
212
        struct nfs_fsinfo res;
213
        struct statfs tmp;
214
 
215
        error = nfs_proc_statfs(&sb->u.nfs_sb.s_server, &sb->u.nfs_sb.s_root,
216
                &res);
217
        if (error) {
218
                printk("nfs_statfs: statfs error = %d\n", -error);
219
                res.bsize = res.blocks = res.bfree = res.bavail = 0;
220
        }
221
        tmp.f_type = NFS_SUPER_MAGIC;
222
        tmp.f_bsize = res.bsize;
223
        tmp.f_blocks = res.blocks;
224
        tmp.f_bfree = res.bfree;
225
        tmp.f_bavail = res.bavail;
226
        tmp.f_files = 0;
227
        tmp.f_ffree = 0;
228
        tmp.f_namelen = NAME_MAX;
229
        memcpy_tofs(buf, &tmp, bufsiz);
230
}
231
 
232
/*
233
 * This is our own version of iget that looks up inodes by file handle
234
 * instead of inode number.  We use this technique instead of using
235
 * the vfs read_inode function because there is no way to pass the
236
 * file handle or current attributes into the read_inode function.
237
 * We just have to be careful not to subvert iget's special handling
238
 * of mount points.
239
 */
240
 
241
struct inode *nfs_fhget(struct super_block *sb, struct nfs_fh *fhandle,
242
                        struct nfs_fattr *fattr)
243
{
244
        struct nfs_fattr newfattr;
245
        int error;
246
        struct inode *inode;
247
 
248
        if (!sb) {
249
                printk("nfs_fhget: super block is NULL\n");
250
                return NULL;
251
        }
252
        if (!fattr) {
253
                error = nfs_proc_getattr(&sb->u.nfs_sb.s_server, fhandle,
254
                        &newfattr);
255
                if (error) {
256
                        printk("nfs_fhget: getattr error = %d\n", -error);
257
                        return NULL;
258
                }
259
                fattr = &newfattr;
260
        }
261
        if (!(inode = iget(sb, fattr->fileid))) {
262
                printk("nfs_fhget: iget failed\n");
263
                return NULL;
264
        }
265
        if (inode->i_dev == sb->s_dev) {
266
                if (inode->i_ino != fattr->fileid) {
267
                        printk("nfs_fhget: unexpected inode from iget\n");
268
                        return inode;
269
                }
270
                *NFS_FH(inode) = *fhandle;
271
                nfs_refresh_inode(inode, fattr);
272
        }
273
        return inode;
274
}
275
 
276
int nfs_notify_change(struct inode *inode, struct iattr *attr)
277
{
278
        struct nfs_sattr sattr;
279
        struct nfs_fattr fattr;
280
        int error;
281
 
282
        sattr.mode = (unsigned) -1;
283
        if (attr->ia_valid & ATTR_MODE)
284
                sattr.mode = attr->ia_mode;
285
 
286
        sattr.uid = (unsigned) -1;
287
        if (attr->ia_valid & ATTR_UID)
288
                sattr.uid = attr->ia_uid;
289
 
290
        sattr.gid = (unsigned) -1;
291
        if (attr->ia_valid & ATTR_GID)
292
                sattr.gid = attr->ia_gid;
293
 
294
 
295
        sattr.size = (unsigned) -1;
296
        if (attr->ia_valid & ATTR_SIZE)
297
                sattr.size = S_ISREG(inode->i_mode) ? attr->ia_size : -1;
298
 
299
        sattr.mtime.seconds = sattr.mtime.useconds = (unsigned) -1;
300
        if (attr->ia_valid & ATTR_MTIME) {
301
                sattr.mtime.seconds = attr->ia_mtime;
302
                sattr.mtime.useconds = 0;
303
        }
304
 
305
        sattr.atime.seconds = sattr.atime.useconds = (unsigned) -1;
306
        if (attr->ia_valid & ATTR_ATIME) {
307
                sattr.atime.seconds = attr->ia_atime;
308
                sattr.atime.useconds = 0;
309
        }
310
 
311
        error = nfs_proc_setattr(NFS_SERVER(inode), NFS_FH(inode),
312
                &sattr, &fattr);
313
        if (!error)
314
                nfs_refresh_inode(inode, &fattr);
315
        inode->i_dirt = 0;
316
        return error;
317
}
318
 
319
/* Every kernel module contains stuff like this. */
320
 
321
static struct file_system_type nfs_fs_type = {
322
        nfs_read_super, "nfs", 0, NULL
323
};
324
 
325
/*
326
 * Start up an nfsiod process. This is an awful hack, because when running
327
 * as a module, we will keep insmod's memory. Besides, the current->comm
328
 * hack won't work in this case
329
 * The best would be to have a syscall for nfs client control that (among
330
 * other things) forks biod's.
331
 * Alternatively, we might want to have the idle task spawn biod's on demand.
332
 */
333
static int run_nfsiod(void *dummy)
334
{
335
        int     ret;
336
 
337
#ifdef __SMP__
338
        lock_kernel();
339
        syscall_count++;
340
#endif
341
 
342
        MOD_INC_USE_COUNT;
343
        exit_mm(current);
344
        current->session = 1;
345
        current->pgrp = 1;
346
        sprintf(current->comm, "nfsiod");
347
#ifndef MODULE
348
        current->blocked = ~0UL;
349
#endif
350
        ret = nfsiod();
351
        MOD_DEC_USE_COUNT;
352
        return ret;
353
}
354
 
355
int init_nfs_fs(void)
356
{
357
        /* Fork four biod's */
358
        kernel_thread(run_nfsiod, NULL, 0);
359
        kernel_thread(run_nfsiod, NULL, 0);
360
        kernel_thread(run_nfsiod, NULL, 0);
361
        kernel_thread(run_nfsiod, NULL, 0);
362
        return register_filesystem(&nfs_fs_type);
363
}
364
 
365
#ifdef MODULE
366
int init_module(void)
367
{
368
        int status;
369
 
370
        if ((status = init_nfs_fs()) == 0)
371
                register_symtab(0);
372
        return status;
373
}
374
 
375
void cleanup_module(void)
376
{
377
        unregister_filesystem(&nfs_fs_type);
378
        nfs_kfree_cache();
379
}
380
 
381
#endif

powered by: WebSVN 2.1.0

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