blob: 5a4519e834da31131f4140f246aaa5aaf27f04e2 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * JFFS -- Journalling Flash File System, Linux implementation.
3 *
4 * Copyright (C) 1999, 2000 Axis Communications AB.
5 *
6 * Created by Finn Hakansson <finn@axis.com>.
7 *
8 * This is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * $Id: inode-v23.c,v 1.70 2001/10/02 09:16:02 dwmw2 Exp $
14 *
15 * Ported to Linux 2.3.x and MTD:
16 * Copyright (C) 2000 Alexander Larsson (alex@cendio.se), Cendio Systems AB
17 *
18 * Copyright 2000, 2001 Red Hat, Inc.
19 */
20
21/* inode.c -- Contains the code that is called from the VFS. */
22
23/* TODO-ALEX:
24 * uid and gid are just 16 bit.
25 * jffs_file_write reads from user-space pointers without xx_from_user
26 * maybe other stuff do to.
27 */
28
29#include <linux/time.h>
30
31#include <linux/module.h>
32#include <linux/init.h>
33#include <linux/types.h>
34#include <linux/errno.h>
35#include <linux/slab.h>
36#include <linux/jffs.h>
37#include <linux/fs.h>
38#include <linux/smp_lock.h>
39#include <linux/ioctl.h>
40#include <linux/stat.h>
41#include <linux/blkdev.h>
42#include <linux/quotaops.h>
43#include <linux/highmem.h>
44#include <linux/vfs.h>
Ingo Molnar1eb0d672006-03-23 03:00:40 -080045#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070046#include <asm/byteorder.h>
47#include <asm/uaccess.h>
48
49#include "jffs_fm.h"
50#include "intrep.h"
51#ifdef CONFIG_JFFS_PROC_FS
52#include "jffs_proc.h"
53#endif
54
55static int jffs_remove(struct inode *dir, struct dentry *dentry, int type);
56
57static struct super_operations jffs_ops;
58static struct file_operations jffs_file_operations;
59static struct inode_operations jffs_file_inode_operations;
60static struct file_operations jffs_dir_operations;
61static struct inode_operations jffs_dir_inode_operations;
62static struct address_space_operations jffs_address_operations;
63
64kmem_cache_t *node_cache = NULL;
65kmem_cache_t *fm_cache = NULL;
66
67/* Called by the VFS at mount time to initialize the whole file system. */
68static int jffs_fill_super(struct super_block *sb, void *data, int silent)
69{
70 struct inode *root_inode;
71 struct jffs_control *c;
72
73 sb->s_flags |= MS_NODIRATIME;
74
75 D1(printk(KERN_NOTICE "JFFS: Trying to mount device %s.\n",
76 sb->s_id));
77
78 if (MAJOR(sb->s_dev) != MTD_BLOCK_MAJOR) {
79 printk(KERN_WARNING "JFFS: Trying to mount a "
80 "non-mtd device.\n");
81 return -EINVAL;
82 }
83
84 sb->s_blocksize = PAGE_CACHE_SIZE;
85 sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
86 sb->s_fs_info = (void *) 0;
87 sb->s_maxbytes = 0xFFFFFFFF;
88
89 /* Build the file system. */
90 if (jffs_build_fs(sb) < 0) {
91 goto jffs_sb_err1;
92 }
93
94 /*
95 * set up enough so that we can read an inode
96 */
97 sb->s_magic = JFFS_MAGIC_SB_BITMASK;
98 sb->s_op = &jffs_ops;
99
100 root_inode = iget(sb, JFFS_MIN_INO);
101 if (!root_inode)
102 goto jffs_sb_err2;
103
104 /* Get the root directory of this file system. */
105 if (!(sb->s_root = d_alloc_root(root_inode))) {
106 goto jffs_sb_err3;
107 }
108
109 c = (struct jffs_control *) sb->s_fs_info;
110
111#ifdef CONFIG_JFFS_PROC_FS
112 /* Set up the jffs proc file system. */
113 if (jffs_register_jffs_proc_dir(MINOR(sb->s_dev), c) < 0) {
114 printk(KERN_WARNING "JFFS: Failed to initialize the JFFS "
115 "proc file system for device %s.\n",
116 sb->s_id);
117 }
118#endif
119
120 /* Set the Garbage Collection thresholds */
121
122 /* GC if free space goes below 5% of the total size */
123 c->gc_minfree_threshold = c->fmc->flash_size / 20;
124
125 if (c->gc_minfree_threshold < c->fmc->sector_size)
126 c->gc_minfree_threshold = c->fmc->sector_size;
127
128 /* GC if dirty space exceeds 33% of the total size. */
129 c->gc_maxdirty_threshold = c->fmc->flash_size / 3;
130
131 if (c->gc_maxdirty_threshold < c->fmc->sector_size)
132 c->gc_maxdirty_threshold = c->fmc->sector_size;
133
134
135 c->thread_pid = kernel_thread (jffs_garbage_collect_thread,
136 (void *) c,
137 CLONE_KERNEL);
138 D1(printk(KERN_NOTICE "JFFS: GC thread pid=%d.\n", (int) c->thread_pid));
139
140 D1(printk(KERN_NOTICE "JFFS: Successfully mounted device %s.\n",
141 sb->s_id));
142 return 0;
143
144jffs_sb_err3:
145 iput(root_inode);
146jffs_sb_err2:
147 jffs_cleanup_control((struct jffs_control *)sb->s_fs_info);
148jffs_sb_err1:
149 printk(KERN_WARNING "JFFS: Failed to mount device %s.\n",
150 sb->s_id);
151 return -EINVAL;
152}
153
154
155/* This function is called when the file system is umounted. */
156static void
157jffs_put_super(struct super_block *sb)
158{
159 struct jffs_control *c = (struct jffs_control *) sb->s_fs_info;
160
161 D2(printk("jffs_put_super()\n"));
162
163#ifdef CONFIG_JFFS_PROC_FS
164 jffs_unregister_jffs_proc_dir(c);
165#endif
166
167 if (c->gc_task) {
168 D1(printk (KERN_NOTICE "jffs_put_super(): Telling gc thread to die.\n"));
169 send_sig(SIGKILL, c->gc_task, 1);
170 }
171 wait_for_completion(&c->gc_thread_comp);
172
173 D1(printk (KERN_NOTICE "jffs_put_super(): Successfully waited on thread.\n"));
174
175 jffs_cleanup_control((struct jffs_control *)sb->s_fs_info);
176 D1(printk(KERN_NOTICE "JFFS: Successfully unmounted device %s.\n",
177 sb->s_id));
178}
179
180
181/* This function is called when user commands like chmod, chgrp and
182 chown are executed. System calls like trunc() results in a call
183 to this function. */
184static int
185jffs_setattr(struct dentry *dentry, struct iattr *iattr)
186{
187 struct inode *inode = dentry->d_inode;
188 struct jffs_raw_inode raw_inode;
189 struct jffs_control *c;
190 struct jffs_fmcontrol *fmc;
191 struct jffs_file *f;
192 struct jffs_node *new_node;
193 int update_all;
194 int res = 0;
195 int recoverable = 0;
196
197 lock_kernel();
198
199 if ((res = inode_change_ok(inode, iattr)))
200 goto out;
201
202 c = (struct jffs_control *)inode->i_sb->s_fs_info;
203 fmc = c->fmc;
204
205 D3(printk (KERN_NOTICE "notify_change(): down biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800206 mutex_lock(&fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207
208 f = jffs_find_file(c, inode->i_ino);
209
210 ASSERT(if (!f) {
211 printk("jffs_setattr(): Invalid inode number: %lu\n",
212 inode->i_ino);
213 D3(printk (KERN_NOTICE "notify_change(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800214 mutex_unlock(&fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215 res = -EINVAL;
216 goto out;
217 });
218
219 D1(printk("***jffs_setattr(): file: \"%s\", ino: %u\n",
220 f->name, f->ino));
221
222 update_all = iattr->ia_valid & ATTR_FORCE;
223
224 if ( (update_all || iattr->ia_valid & ATTR_SIZE)
225 && (iattr->ia_size + 128 < f->size) ) {
226 /* We're shrinking the file by more than 128 bytes.
227 We'll be able to GC and recover this space, so
228 allow it to go into the reserved space. */
229 recoverable = 1;
230 }
231
232 if (!(new_node = jffs_alloc_node())) {
233 D(printk("jffs_setattr(): Allocation failed!\n"));
234 D3(printk (KERN_NOTICE "notify_change(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800235 mutex_unlock(&fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236 res = -ENOMEM;
237 goto out;
238 }
239
240 new_node->data_offset = 0;
241 new_node->removed_size = 0;
242 raw_inode.magic = JFFS_MAGIC_BITMASK;
243 raw_inode.ino = f->ino;
244 raw_inode.pino = f->pino;
245 raw_inode.mode = f->mode;
246 raw_inode.uid = f->uid;
247 raw_inode.gid = f->gid;
248 raw_inode.atime = f->atime;
249 raw_inode.mtime = f->mtime;
250 raw_inode.ctime = f->ctime;
251 raw_inode.dsize = 0;
252 raw_inode.offset = 0;
253 raw_inode.rsize = 0;
254 raw_inode.dsize = 0;
255 raw_inode.nsize = f->nsize;
256 raw_inode.nlink = f->nlink;
257 raw_inode.spare = 0;
258 raw_inode.rename = 0;
259 raw_inode.deleted = 0;
260
261 if (update_all || iattr->ia_valid & ATTR_MODE) {
262 raw_inode.mode = iattr->ia_mode;
263 inode->i_mode = iattr->ia_mode;
264 }
265 if (update_all || iattr->ia_valid & ATTR_UID) {
266 raw_inode.uid = iattr->ia_uid;
267 inode->i_uid = iattr->ia_uid;
268 }
269 if (update_all || iattr->ia_valid & ATTR_GID) {
270 raw_inode.gid = iattr->ia_gid;
271 inode->i_gid = iattr->ia_gid;
272 }
273 if (update_all || iattr->ia_valid & ATTR_SIZE) {
274 int len;
275 D1(printk("jffs_notify_change(): Changing size "
276 "to %lu bytes!\n", (long)iattr->ia_size));
277 raw_inode.offset = iattr->ia_size;
278
279 /* Calculate how many bytes need to be removed from
280 the end. */
281 if (f->size < iattr->ia_size) {
282 len = 0;
283 }
284 else {
285 len = f->size - iattr->ia_size;
286 }
287
288 raw_inode.rsize = len;
289
290 /* The updated node will be a removal node, with
291 base at the new size and size of the nbr of bytes
292 to be removed. */
293 new_node->data_offset = iattr->ia_size;
294 new_node->removed_size = len;
295 inode->i_size = iattr->ia_size;
296 inode->i_blocks = (inode->i_size + 511) >> 9;
297
298 if (len) {
299 invalidate_inode_pages(inode->i_mapping);
300 }
301 inode->i_ctime = CURRENT_TIME_SEC;
302 inode->i_mtime = inode->i_ctime;
303 }
304 if (update_all || iattr->ia_valid & ATTR_ATIME) {
305 raw_inode.atime = iattr->ia_atime.tv_sec;
306 inode->i_atime = iattr->ia_atime;
307 }
308 if (update_all || iattr->ia_valid & ATTR_MTIME) {
309 raw_inode.mtime = iattr->ia_mtime.tv_sec;
310 inode->i_mtime = iattr->ia_mtime;
311 }
312 if (update_all || iattr->ia_valid & ATTR_CTIME) {
313 raw_inode.ctime = iattr->ia_ctime.tv_sec;
314 inode->i_ctime = iattr->ia_ctime;
315 }
316
317 /* Write this node to the flash. */
318 if ((res = jffs_write_node(c, new_node, &raw_inode, f->name, NULL, recoverable, f)) < 0) {
319 D(printk("jffs_notify_change(): The write failed!\n"));
320 jffs_free_node(new_node);
321 D3(printk (KERN_NOTICE "n_c(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800322 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323 goto out;
324 }
325
326 jffs_insert_node(c, f, &raw_inode, NULL, new_node);
327
328 mark_inode_dirty(inode);
329 D3(printk (KERN_NOTICE "n_c(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800330 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331out:
332 unlock_kernel();
333 return res;
334} /* jffs_notify_change() */
335
336
337static struct inode *
338jffs_new_inode(const struct inode * dir, struct jffs_raw_inode *raw_inode,
339 int * err)
340{
341 struct super_block * sb;
342 struct inode * inode;
343 struct jffs_control *c;
344 struct jffs_file *f;
345
346 sb = dir->i_sb;
347 inode = new_inode(sb);
348 if (!inode) {
349 *err = -ENOMEM;
350 return NULL;
351 }
352
353 c = (struct jffs_control *)sb->s_fs_info;
354
355 inode->i_ino = raw_inode->ino;
356 inode->i_mode = raw_inode->mode;
357 inode->i_nlink = raw_inode->nlink;
358 inode->i_uid = raw_inode->uid;
359 inode->i_gid = raw_inode->gid;
360 inode->i_size = raw_inode->dsize;
361 inode->i_atime.tv_sec = raw_inode->atime;
362 inode->i_mtime.tv_sec = raw_inode->mtime;
363 inode->i_ctime.tv_sec = raw_inode->ctime;
364 inode->i_ctime.tv_nsec = 0;
365 inode->i_mtime.tv_nsec = 0;
366 inode->i_atime.tv_nsec = 0;
367 inode->i_blksize = PAGE_SIZE;
368 inode->i_blocks = (inode->i_size + 511) >> 9;
369
370 f = jffs_find_file(c, raw_inode->ino);
371
372 inode->u.generic_ip = (void *)f;
373 insert_inode_hash(inode);
374
375 return inode;
376}
377
378/* Get statistics of the file system. */
379static int
380jffs_statfs(struct super_block *sb, struct kstatfs *buf)
381{
382 struct jffs_control *c = (struct jffs_control *) sb->s_fs_info;
383 struct jffs_fmcontrol *fmc;
384
385 lock_kernel();
386
387 fmc = c->fmc;
388
389 D2(printk("jffs_statfs()\n"));
390
391 buf->f_type = JFFS_MAGIC_SB_BITMASK;
392 buf->f_bsize = PAGE_CACHE_SIZE;
393 buf->f_blocks = (fmc->flash_size / PAGE_CACHE_SIZE)
394 - (fmc->min_free_size / PAGE_CACHE_SIZE);
395 buf->f_bfree = (jffs_free_size1(fmc) + jffs_free_size2(fmc) +
396 fmc->dirty_size - fmc->min_free_size)
397 >> PAGE_CACHE_SHIFT;
398 buf->f_bavail = buf->f_bfree;
399
400 /* Find out how many files there are in the filesystem. */
401 buf->f_files = jffs_foreach_file(c, jffs_file_count);
402 buf->f_ffree = buf->f_bfree;
403 /* buf->f_fsid = 0; */
404 buf->f_namelen = JFFS_MAX_NAME_LEN;
405
406 unlock_kernel();
407
408 return 0;
409}
410
411
412/* Rename a file. */
413static int
414jffs_rename(struct inode *old_dir, struct dentry *old_dentry,
415 struct inode *new_dir, struct dentry *new_dentry)
416{
417 struct jffs_raw_inode raw_inode;
418 struct jffs_control *c;
419 struct jffs_file *old_dir_f;
420 struct jffs_file *new_dir_f;
421 struct jffs_file *del_f;
422 struct jffs_file *f;
423 struct jffs_node *node;
424 struct inode *inode;
425 int result = 0;
426 __u32 rename_data = 0;
427
428 D2(printk("***jffs_rename()\n"));
429
430 D(printk("jffs_rename(): old_dir: 0x%p, old name: 0x%p, "
431 "new_dir: 0x%p, new name: 0x%p\n",
432 old_dir, old_dentry->d_name.name,
433 new_dir, new_dentry->d_name.name));
434
435 lock_kernel();
436 c = (struct jffs_control *)old_dir->i_sb->s_fs_info;
437 ASSERT(if (!c) {
438 printk(KERN_ERR "jffs_rename(): The old_dir inode "
439 "didn't have a reference to a jffs_file struct\n");
440 unlock_kernel();
441 return -EIO;
442 });
443
444 result = -ENOTDIR;
445 if (!(old_dir_f = (struct jffs_file *)old_dir->u.generic_ip)) {
446 D(printk("jffs_rename(): Old dir invalid.\n"));
447 goto jffs_rename_end;
448 }
449
450 /* Try to find the file to move. */
451 result = -ENOENT;
452 if (!(f = jffs_find_child(old_dir_f, old_dentry->d_name.name,
453 old_dentry->d_name.len))) {
454 goto jffs_rename_end;
455 }
456
457 /* Find the new directory. */
458 result = -ENOTDIR;
459 if (!(new_dir_f = (struct jffs_file *)new_dir->u.generic_ip)) {
460 D(printk("jffs_rename(): New dir invalid.\n"));
461 goto jffs_rename_end;
462 }
463 D3(printk (KERN_NOTICE "rename(): down biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800464 mutex_lock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465 /* Create a node and initialize as much as needed. */
466 result = -ENOMEM;
467 if (!(node = jffs_alloc_node())) {
468 D(printk("jffs_rename(): Allocation failed: node == 0\n"));
469 goto jffs_rename_end;
470 }
471 node->data_offset = 0;
472 node->removed_size = 0;
473
474 /* Initialize the raw inode. */
475 raw_inode.magic = JFFS_MAGIC_BITMASK;
476 raw_inode.ino = f->ino;
477 raw_inode.pino = new_dir_f->ino;
478/* raw_inode.version = f->highest_version + 1; */
479 raw_inode.mode = f->mode;
480 raw_inode.uid = current->fsuid;
481 raw_inode.gid = current->fsgid;
482#if 0
483 raw_inode.uid = f->uid;
484 raw_inode.gid = f->gid;
485#endif
486 raw_inode.atime = get_seconds();
487 raw_inode.mtime = raw_inode.atime;
488 raw_inode.ctime = f->ctime;
489 raw_inode.offset = 0;
490 raw_inode.dsize = 0;
491 raw_inode.rsize = 0;
492 raw_inode.nsize = new_dentry->d_name.len;
493 raw_inode.nlink = f->nlink;
494 raw_inode.spare = 0;
495 raw_inode.rename = 0;
496 raw_inode.deleted = 0;
497
498 /* See if there already exists a file with the same name as
499 new_name. */
500 if ((del_f = jffs_find_child(new_dir_f, new_dentry->d_name.name,
501 new_dentry->d_name.len))) {
502 raw_inode.rename = 1;
503 raw_inode.dsize = sizeof(__u32);
504 rename_data = del_f->ino;
505 }
506
507 /* Write the new node to the flash memory. */
508 if ((result = jffs_write_node(c, node, &raw_inode,
509 new_dentry->d_name.name,
510 (unsigned char*)&rename_data, 0, f)) < 0) {
511 D(printk("jffs_rename(): Failed to write node to flash.\n"));
512 jffs_free_node(node);
513 goto jffs_rename_end;
514 }
515 raw_inode.dsize = 0;
516
517 if (raw_inode.rename) {
518 /* The file with the same name must be deleted. */
519 //FIXME deadlock down(&c->fmc->gclock);
520 if ((result = jffs_remove(new_dir, new_dentry,
521 del_f->mode)) < 0) {
522 /* This is really bad. */
523 printk(KERN_ERR "JFFS: An error occurred in "
524 "rename().\n");
525 }
526 // up(&c->fmc->gclock);
527 }
528
529 if (old_dir_f != new_dir_f) {
530 /* Remove the file from its old position in the
531 filesystem tree. */
532 jffs_unlink_file_from_tree(f);
533 }
534
535 /* Insert the new node into the file system. */
536 if ((result = jffs_insert_node(c, f, &raw_inode,
537 new_dentry->d_name.name, node)) < 0) {
538 D(printk(KERN_ERR "jffs_rename(): jffs_insert_node() "
539 "failed!\n"));
540 }
541
542 if (old_dir_f != new_dir_f) {
543 /* Insert the file to its new position in the
544 file system. */
545 jffs_insert_file_into_tree(f);
546 }
547
548 /* This is a kind of update of the inode we're about to make
549 here. This is what they do in ext2fs. Kind of. */
550 if ((inode = iget(new_dir->i_sb, f->ino))) {
551 inode->i_ctime = CURRENT_TIME_SEC;
552 mark_inode_dirty(inode);
553 iput(inode);
554 }
555
556jffs_rename_end:
557 D3(printk (KERN_NOTICE "rename(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800558 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559 unlock_kernel();
560 return result;
561} /* jffs_rename() */
562
563
564/* Read the contents of a directory. Used by programs like `ls'
565 for instance. */
566static int
567jffs_readdir(struct file *filp, void *dirent, filldir_t filldir)
568{
569 struct jffs_file *f;
570 struct dentry *dentry = filp->f_dentry;
571 struct inode *inode = dentry->d_inode;
572 struct jffs_control *c = (struct jffs_control *)inode->i_sb->s_fs_info;
573 int j;
574 int ddino;
575 lock_kernel();
576 D3(printk (KERN_NOTICE "readdir(): down biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800577 mutex_lock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578
579 D2(printk("jffs_readdir(): inode: 0x%p, filp: 0x%p\n", inode, filp));
580 if (filp->f_pos == 0) {
581 D3(printk("jffs_readdir(): \".\" %lu\n", inode->i_ino));
582 if (filldir(dirent, ".", 1, filp->f_pos, inode->i_ino, DT_DIR) < 0) {
583 D3(printk (KERN_NOTICE "readdir(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800584 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585 unlock_kernel();
586 return 0;
587 }
588 filp->f_pos = 1;
589 }
590 if (filp->f_pos == 1) {
591 if (inode->i_ino == JFFS_MIN_INO) {
592 ddino = JFFS_MIN_INO;
593 }
594 else {
595 ddino = ((struct jffs_file *)
596 inode->u.generic_ip)->pino;
597 }
598 D3(printk("jffs_readdir(): \"..\" %u\n", ddino));
599 if (filldir(dirent, "..", 2, filp->f_pos, ddino, DT_DIR) < 0) {
600 D3(printk (KERN_NOTICE "readdir(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800601 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602 unlock_kernel();
603 return 0;
604 }
605 filp->f_pos++;
606 }
607 f = ((struct jffs_file *)inode->u.generic_ip)->children;
608
609 j = 2;
610 while(f && (f->deleted || j++ < filp->f_pos )) {
611 f = f->sibling_next;
612 }
613
614 while (f) {
615 D3(printk("jffs_readdir(): \"%s\" ino: %u\n",
616 (f->name ? f->name : ""), f->ino));
617 if (filldir(dirent, f->name, f->nsize,
618 filp->f_pos , f->ino, DT_UNKNOWN) < 0) {
619 D3(printk (KERN_NOTICE "readdir(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800620 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621 unlock_kernel();
622 return 0;
623 }
624 filp->f_pos++;
625 do {
626 f = f->sibling_next;
627 } while(f && f->deleted);
628 }
629 D3(printk (KERN_NOTICE "readdir(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800630 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631 unlock_kernel();
632 return filp->f_pos;
633} /* jffs_readdir() */
634
635
636/* Find a file in a directory. If the file exists, return its
637 corresponding dentry. */
638static struct dentry *
639jffs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
640{
641 struct jffs_file *d;
642 struct jffs_file *f;
643 struct jffs_control *c = (struct jffs_control *)dir->i_sb->s_fs_info;
644 int len;
645 int r = 0;
646 const char *name;
647 struct inode *inode = NULL;
648
649 len = dentry->d_name.len;
650 name = dentry->d_name.name;
651
652 lock_kernel();
653
654 D3({
655 char *s = (char *)kmalloc(len + 1, GFP_KERNEL);
656 memcpy(s, name, len);
657 s[len] = '\0';
658 printk("jffs_lookup(): dir: 0x%p, name: \"%s\"\n", dir, s);
659 kfree(s);
660 });
661
662 D3(printk (KERN_NOTICE "lookup(): down biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800663 mutex_lock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664
665 r = -ENAMETOOLONG;
666 if (len > JFFS_MAX_NAME_LEN) {
667 goto jffs_lookup_end;
668 }
669
670 r = -EACCES;
671 if (!(d = (struct jffs_file *)dir->u.generic_ip)) {
672 D(printk("jffs_lookup(): No such inode! (%lu)\n",
673 dir->i_ino));
674 goto jffs_lookup_end;
675 }
676
677 /* Get the corresponding inode to the file. */
678
679 /* iget calls jffs_read_inode, so we need to drop the biglock
680 before calling iget. Unfortunately, the GC has a tendency
681 to sneak in here, because iget sometimes calls schedule ().
682 */
683
684 if ((len == 1) && (name[0] == '.')) {
685 D3(printk (KERN_NOTICE "lookup(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800686 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687 if (!(inode = iget(dir->i_sb, d->ino))) {
688 D(printk("jffs_lookup(): . iget() ==> NULL\n"));
689 goto jffs_lookup_end_no_biglock;
690 }
691 D3(printk (KERN_NOTICE "lookup(): down biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800692 mutex_lock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693 } else if ((len == 2) && (name[0] == '.') && (name[1] == '.')) {
694 D3(printk (KERN_NOTICE "lookup(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800695 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696 if (!(inode = iget(dir->i_sb, d->pino))) {
697 D(printk("jffs_lookup(): .. iget() ==> NULL\n"));
698 goto jffs_lookup_end_no_biglock;
699 }
700 D3(printk (KERN_NOTICE "lookup(): down biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800701 mutex_lock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702 } else if ((f = jffs_find_child(d, name, len))) {
703 D3(printk (KERN_NOTICE "lookup(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800704 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705 if (!(inode = iget(dir->i_sb, f->ino))) {
706 D(printk("jffs_lookup(): iget() ==> NULL\n"));
707 goto jffs_lookup_end_no_biglock;
708 }
709 D3(printk (KERN_NOTICE "lookup(): down biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800710 mutex_lock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711 } else {
712 D3(printk("jffs_lookup(): Couldn't find the file. "
713 "f = 0x%p, name = \"%s\", d = 0x%p, d->ino = %u\n",
714 f, name, d, d->ino));
715 inode = NULL;
716 }
717
718 d_add(dentry, inode);
719 D3(printk (KERN_NOTICE "lookup(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800720 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721 unlock_kernel();
722 return NULL;
723
724jffs_lookup_end:
725 D3(printk (KERN_NOTICE "lookup(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800726 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727
728jffs_lookup_end_no_biglock:
729 unlock_kernel();
730 return ERR_PTR(r);
731} /* jffs_lookup() */
732
733
734/* Try to read a page of data from a file. */
735static int
736jffs_do_readpage_nolock(struct file *file, struct page *page)
737{
738 void *buf;
739 unsigned long read_len;
740 int result;
741 struct inode *inode = (struct inode*)page->mapping->host;
742 struct jffs_file *f = (struct jffs_file *)inode->u.generic_ip;
743 struct jffs_control *c = (struct jffs_control *)inode->i_sb->s_fs_info;
744 int r;
745 loff_t offset;
746
747 D2(printk("***jffs_readpage(): file = \"%s\", page->index = %lu\n",
748 (f->name ? f->name : ""), (long)page->index));
749
750 get_page(page);
751 /* Don't SetPageLocked(page), should be locked already */
752 ClearPageUptodate(page);
753 ClearPageError(page);
754
755 D3(printk (KERN_NOTICE "readpage(): down biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800756 mutex_lock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757
758 read_len = 0;
759 result = 0;
Andrew Morton54b21a72006-01-08 01:03:05 -0800760 offset = page_offset(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761
762 kmap(page);
763 buf = page_address(page);
764 if (offset < inode->i_size) {
765 read_len = min_t(long, inode->i_size - offset, PAGE_SIZE);
766 r = jffs_read_data(f, buf, offset, read_len);
767 if (r != read_len) {
768 result = -EIO;
769 D(
770 printk("***jffs_readpage(): Read error! "
771 "Wanted to read %lu bytes but only "
772 "read %d bytes.\n", read_len, r);
773 );
774 }
775
776 }
777
778 /* This handles the case of partial or no read in above */
779 if(read_len < PAGE_SIZE)
780 memset(buf + read_len, 0, PAGE_SIZE - read_len);
781 flush_dcache_page(page);
782 kunmap(page);
783
784 D3(printk (KERN_NOTICE "readpage(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800785 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786
787 if (result) {
788 SetPageError(page);
789 }else {
790 SetPageUptodate(page);
791 }
792
793 page_cache_release(page);
794
795 D3(printk("jffs_readpage(): Leaving...\n"));
796
797 return result;
798} /* jffs_do_readpage_nolock() */
799
800static int jffs_readpage(struct file *file, struct page *page)
801{
802 int ret = jffs_do_readpage_nolock(file, page);
803 unlock_page(page);
804 return ret;
805}
806
807/* Create a new directory. */
808static int
809jffs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
810{
811 struct jffs_raw_inode raw_inode;
812 struct jffs_control *c;
813 struct jffs_node *node;
814 struct jffs_file *dir_f;
815 struct inode *inode;
816 int dir_mode;
817 int result = 0;
818 int err;
819
820 D1({
821 int len = dentry->d_name.len;
822 char *_name = (char *) kmalloc(len + 1, GFP_KERNEL);
823 memcpy(_name, dentry->d_name.name, len);
824 _name[len] = '\0';
825 printk("***jffs_mkdir(): dir = 0x%p, name = \"%s\", "
826 "len = %d, mode = 0x%08x\n", dir, _name, len, mode);
827 kfree(_name);
828 });
829
830 lock_kernel();
831 dir_f = (struct jffs_file *)dir->u.generic_ip;
832
833 ASSERT(if (!dir_f) {
834 printk(KERN_ERR "jffs_mkdir(): No reference to a "
835 "jffs_file struct in inode.\n");
836 unlock_kernel();
837 return -EIO;
838 });
839
840 c = dir_f->c;
841 D3(printk (KERN_NOTICE "mkdir(): down biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800842 mutex_lock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843
844 dir_mode = S_IFDIR | (mode & (S_IRWXUGO|S_ISVTX)
845 & ~current->fs->umask);
846 if (dir->i_mode & S_ISGID) {
847 dir_mode |= S_ISGID;
848 }
849
850 /* Create a node and initialize it as much as needed. */
851 if (!(node = jffs_alloc_node())) {
852 D(printk("jffs_mkdir(): Allocation failed: node == 0\n"));
853 result = -ENOMEM;
854 goto jffs_mkdir_end;
855 }
856 node->data_offset = 0;
857 node->removed_size = 0;
858
859 /* Initialize the raw inode. */
860 raw_inode.magic = JFFS_MAGIC_BITMASK;
861 raw_inode.ino = c->next_ino++;
862 raw_inode.pino = dir_f->ino;
863 raw_inode.version = 1;
864 raw_inode.mode = dir_mode;
865 raw_inode.uid = current->fsuid;
866 raw_inode.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
867 /* raw_inode.gid = current->fsgid; */
868 raw_inode.atime = get_seconds();
869 raw_inode.mtime = raw_inode.atime;
870 raw_inode.ctime = raw_inode.atime;
871 raw_inode.offset = 0;
872 raw_inode.dsize = 0;
873 raw_inode.rsize = 0;
874 raw_inode.nsize = dentry->d_name.len;
875 raw_inode.nlink = 1;
876 raw_inode.spare = 0;
877 raw_inode.rename = 0;
878 raw_inode.deleted = 0;
879
880 /* Write the new node to the flash. */
881 if ((result = jffs_write_node(c, node, &raw_inode,
882 dentry->d_name.name, NULL, 0, NULL)) < 0) {
883 D(printk("jffs_mkdir(): jffs_write_node() failed.\n"));
884 jffs_free_node(node);
885 goto jffs_mkdir_end;
886 }
887
888 /* Insert the new node into the file system. */
889 if ((result = jffs_insert_node(c, NULL, &raw_inode, dentry->d_name.name,
890 node)) < 0) {
891 goto jffs_mkdir_end;
892 }
893
894 inode = jffs_new_inode(dir, &raw_inode, &err);
895 if (inode == NULL) {
896 result = err;
897 goto jffs_mkdir_end;
898 }
899
900 inode->i_op = &jffs_dir_inode_operations;
901 inode->i_fop = &jffs_dir_operations;
902
903 mark_inode_dirty(dir);
904 d_instantiate(dentry, inode);
905
906 result = 0;
907jffs_mkdir_end:
908 D3(printk (KERN_NOTICE "mkdir(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800909 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 unlock_kernel();
911 return result;
912} /* jffs_mkdir() */
913
914
915/* Remove a directory. */
916static int
917jffs_rmdir(struct inode *dir, struct dentry *dentry)
918{
919 struct jffs_control *c = (struct jffs_control *)dir->i_sb->s_fs_info;
920 int ret;
921 D3(printk("***jffs_rmdir()\n"));
922 D3(printk (KERN_NOTICE "rmdir(): down biglock\n"));
923 lock_kernel();
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800924 mutex_lock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925 ret = jffs_remove(dir, dentry, S_IFDIR);
926 D3(printk (KERN_NOTICE "rmdir(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800927 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928 unlock_kernel();
929 return ret;
930}
931
932
933/* Remove any kind of file except for directories. */
934static int
935jffs_unlink(struct inode *dir, struct dentry *dentry)
936{
937 struct jffs_control *c = (struct jffs_control *)dir->i_sb->s_fs_info;
938 int ret;
939
940 lock_kernel();
941 D3(printk("***jffs_unlink()\n"));
942 D3(printk (KERN_NOTICE "unlink(): down biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800943 mutex_lock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944 ret = jffs_remove(dir, dentry, 0);
945 D3(printk (KERN_NOTICE "unlink(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800946 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947 unlock_kernel();
948 return ret;
949}
950
951
952/* Remove a JFFS entry, i.e. plain files, directories, etc. Here we
953 shouldn't test for free space on the device. */
954static int
955jffs_remove(struct inode *dir, struct dentry *dentry, int type)
956{
957 struct jffs_raw_inode raw_inode;
958 struct jffs_control *c;
959 struct jffs_file *dir_f; /* The file-to-remove's parent. */
960 struct jffs_file *del_f; /* The file to remove. */
961 struct jffs_node *del_node;
962 struct inode *inode = NULL;
963 int result = 0;
964
965 D1({
966 int len = dentry->d_name.len;
967 const char *name = dentry->d_name.name;
968 char *_name = (char *) kmalloc(len + 1, GFP_KERNEL);
969 memcpy(_name, name, len);
970 _name[len] = '\0';
971 printk("***jffs_remove(): file = \"%s\", ino = %ld\n", _name, dentry->d_inode->i_ino);
972 kfree(_name);
973 });
974
975 dir_f = (struct jffs_file *) dir->u.generic_ip;
976 c = dir_f->c;
977
978 result = -ENOENT;
979 if (!(del_f = jffs_find_child(dir_f, dentry->d_name.name,
980 dentry->d_name.len))) {
981 D(printk("jffs_remove(): jffs_find_child() failed.\n"));
982 goto jffs_remove_end;
983 }
984
985 if (S_ISDIR(type)) {
986 struct jffs_file *child = del_f->children;
987 while(child) {
988 if( !child->deleted ) {
989 result = -ENOTEMPTY;
990 goto jffs_remove_end;
991 }
992 child = child->sibling_next;
993 }
994 }
995 else if (S_ISDIR(del_f->mode)) {
996 D(printk("jffs_remove(): node is a directory "
997 "but it shouldn't be.\n"));
998 result = -EPERM;
999 goto jffs_remove_end;
1000 }
1001
1002 inode = dentry->d_inode;
1003
1004 result = -EIO;
1005 if (del_f->ino != inode->i_ino)
1006 goto jffs_remove_end;
1007
1008 if (!inode->i_nlink) {
1009 printk("Deleting nonexistent file inode: %lu, nlink: %d\n",
1010 inode->i_ino, inode->i_nlink);
1011 inode->i_nlink=1;
1012 }
1013
1014 /* Create a node for the deletion. */
1015 result = -ENOMEM;
1016 if (!(del_node = jffs_alloc_node())) {
1017 D(printk("jffs_remove(): Allocation failed!\n"));
1018 goto jffs_remove_end;
1019 }
1020 del_node->data_offset = 0;
1021 del_node->removed_size = 0;
1022
1023 /* Initialize the raw inode. */
1024 raw_inode.magic = JFFS_MAGIC_BITMASK;
1025 raw_inode.ino = del_f->ino;
1026 raw_inode.pino = del_f->pino;
1027/* raw_inode.version = del_f->highest_version + 1; */
1028 raw_inode.mode = del_f->mode;
1029 raw_inode.uid = current->fsuid;
1030 raw_inode.gid = current->fsgid;
1031 raw_inode.atime = get_seconds();
1032 raw_inode.mtime = del_f->mtime;
1033 raw_inode.ctime = raw_inode.atime;
1034 raw_inode.offset = 0;
1035 raw_inode.dsize = 0;
1036 raw_inode.rsize = 0;
1037 raw_inode.nsize = 0;
1038 raw_inode.nlink = del_f->nlink;
1039 raw_inode.spare = 0;
1040 raw_inode.rename = 0;
1041 raw_inode.deleted = 1;
1042
1043 /* Write the new node to the flash memory. */
1044 if (jffs_write_node(c, del_node, &raw_inode, NULL, NULL, 1, del_f) < 0) {
1045 jffs_free_node(del_node);
1046 result = -EIO;
1047 goto jffs_remove_end;
1048 }
1049
1050 /* Update the file. This operation will make the file disappear
1051 from the in-memory file system structures. */
1052 jffs_insert_node(c, del_f, &raw_inode, NULL, del_node);
1053
1054 dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
1055 mark_inode_dirty(dir);
1056 inode->i_nlink--;
1057 inode->i_ctime = dir->i_ctime;
1058 mark_inode_dirty(inode);
1059
1060 d_delete(dentry); /* This also frees the inode */
1061
1062 result = 0;
1063jffs_remove_end:
1064 return result;
1065} /* jffs_remove() */
1066
1067
1068static int
1069jffs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
1070{
1071 struct jffs_raw_inode raw_inode;
1072 struct jffs_file *dir_f;
1073 struct jffs_node *node = NULL;
1074 struct jffs_control *c;
1075 struct inode *inode;
1076 int result = 0;
1077 u16 data = old_encode_dev(rdev);
1078 int err;
1079
1080 D1(printk("***jffs_mknod()\n"));
1081
1082 if (!old_valid_dev(rdev))
1083 return -EINVAL;
1084 lock_kernel();
1085 dir_f = (struct jffs_file *)dir->u.generic_ip;
1086 c = dir_f->c;
1087
1088 D3(printk (KERN_NOTICE "mknod(): down biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -08001089 mutex_lock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090
1091 /* Create and initialize a new node. */
1092 if (!(node = jffs_alloc_node())) {
1093 D(printk("jffs_mknod(): Allocation failed!\n"));
1094 result = -ENOMEM;
1095 goto jffs_mknod_err;
1096 }
1097 node->data_offset = 0;
1098 node->removed_size = 0;
1099
1100 /* Initialize the raw inode. */
1101 raw_inode.magic = JFFS_MAGIC_BITMASK;
1102 raw_inode.ino = c->next_ino++;
1103 raw_inode.pino = dir_f->ino;
1104 raw_inode.version = 1;
1105 raw_inode.mode = mode;
1106 raw_inode.uid = current->fsuid;
1107 raw_inode.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
1108 /* raw_inode.gid = current->fsgid; */
1109 raw_inode.atime = get_seconds();
1110 raw_inode.mtime = raw_inode.atime;
1111 raw_inode.ctime = raw_inode.atime;
1112 raw_inode.offset = 0;
1113 raw_inode.dsize = 2;
1114 raw_inode.rsize = 0;
1115 raw_inode.nsize = dentry->d_name.len;
1116 raw_inode.nlink = 1;
1117 raw_inode.spare = 0;
1118 raw_inode.rename = 0;
1119 raw_inode.deleted = 0;
1120
1121 /* Write the new node to the flash. */
1122 if ((err = jffs_write_node(c, node, &raw_inode, dentry->d_name.name,
1123 (unsigned char *)&data, 0, NULL)) < 0) {
1124 D(printk("jffs_mknod(): jffs_write_node() failed.\n"));
1125 result = err;
1126 goto jffs_mknod_err;
1127 }
1128
1129 /* Insert the new node into the file system. */
1130 if ((err = jffs_insert_node(c, NULL, &raw_inode, dentry->d_name.name,
1131 node)) < 0) {
1132 result = err;
1133 goto jffs_mknod_end;
1134 }
1135
1136 inode = jffs_new_inode(dir, &raw_inode, &err);
1137 if (inode == NULL) {
1138 result = err;
1139 goto jffs_mknod_end;
1140 }
1141
1142 init_special_inode(inode, mode, rdev);
1143
1144 d_instantiate(dentry, inode);
1145
1146 goto jffs_mknod_end;
1147
1148jffs_mknod_err:
1149 if (node) {
1150 jffs_free_node(node);
1151 }
1152
1153jffs_mknod_end:
1154 D3(printk (KERN_NOTICE "mknod(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -08001155 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156 unlock_kernel();
1157 return result;
1158} /* jffs_mknod() */
1159
1160
1161static int
1162jffs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
1163{
1164 struct jffs_raw_inode raw_inode;
1165 struct jffs_control *c;
1166 struct jffs_file *dir_f;
1167 struct jffs_node *node;
1168 struct inode *inode;
1169
1170 int symname_len = strlen(symname);
1171 int err;
1172
1173 lock_kernel();
1174 D1({
1175 int len = dentry->d_name.len;
1176 char *_name = (char *)kmalloc(len + 1, GFP_KERNEL);
1177 char *_symname = (char *)kmalloc(symname_len + 1, GFP_KERNEL);
1178 memcpy(_name, dentry->d_name.name, len);
1179 _name[len] = '\0';
1180 memcpy(_symname, symname, symname_len);
1181 _symname[symname_len] = '\0';
1182 printk("***jffs_symlink(): dir = 0x%p, "
1183 "dentry->dname.name = \"%s\", "
1184 "symname = \"%s\"\n", dir, _name, _symname);
1185 kfree(_name);
1186 kfree(_symname);
1187 });
1188
1189 dir_f = (struct jffs_file *)dir->u.generic_ip;
1190 ASSERT(if (!dir_f) {
1191 printk(KERN_ERR "jffs_symlink(): No reference to a "
1192 "jffs_file struct in inode.\n");
1193 unlock_kernel();
1194 return -EIO;
1195 });
1196
1197 c = dir_f->c;
1198
1199 /* Create a node and initialize it as much as needed. */
1200 if (!(node = jffs_alloc_node())) {
1201 D(printk("jffs_symlink(): Allocation failed: node = NULL\n"));
1202 unlock_kernel();
1203 return -ENOMEM;
1204 }
1205 D3(printk (KERN_NOTICE "symlink(): down biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -08001206 mutex_lock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207
1208 node->data_offset = 0;
1209 node->removed_size = 0;
1210
1211 /* Initialize the raw inode. */
1212 raw_inode.magic = JFFS_MAGIC_BITMASK;
1213 raw_inode.ino = c->next_ino++;
1214 raw_inode.pino = dir_f->ino;
1215 raw_inode.version = 1;
1216 raw_inode.mode = S_IFLNK | S_IRWXUGO;
1217 raw_inode.uid = current->fsuid;
1218 raw_inode.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
1219 raw_inode.atime = get_seconds();
1220 raw_inode.mtime = raw_inode.atime;
1221 raw_inode.ctime = raw_inode.atime;
1222 raw_inode.offset = 0;
1223 raw_inode.dsize = symname_len;
1224 raw_inode.rsize = 0;
1225 raw_inode.nsize = dentry->d_name.len;
1226 raw_inode.nlink = 1;
1227 raw_inode.spare = 0;
1228 raw_inode.rename = 0;
1229 raw_inode.deleted = 0;
1230
1231 /* Write the new node to the flash. */
1232 if ((err = jffs_write_node(c, node, &raw_inode, dentry->d_name.name,
1233 (const unsigned char *)symname, 0, NULL)) < 0) {
1234 D(printk("jffs_symlink(): jffs_write_node() failed.\n"));
1235 jffs_free_node(node);
1236 goto jffs_symlink_end;
1237 }
1238
1239 /* Insert the new node into the file system. */
1240 if ((err = jffs_insert_node(c, NULL, &raw_inode, dentry->d_name.name,
1241 node)) < 0) {
1242 goto jffs_symlink_end;
1243 }
1244
1245 inode = jffs_new_inode(dir, &raw_inode, &err);
1246 if (inode == NULL) {
1247 goto jffs_symlink_end;
1248 }
1249 err = 0;
1250 inode->i_op = &page_symlink_inode_operations;
1251 inode->i_mapping->a_ops = &jffs_address_operations;
1252
1253 d_instantiate(dentry, inode);
1254 jffs_symlink_end:
1255 D3(printk (KERN_NOTICE "symlink(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -08001256 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257 unlock_kernel();
1258 return err;
1259} /* jffs_symlink() */
1260
1261
1262/* Create an inode inside a JFFS directory (dir) and return it.
1263 *
1264 * By the time this is called, we already have created
1265 * the directory cache entry for the new file, but it
1266 * is so far negative - it has no inode.
1267 *
1268 * If the create succeeds, we fill in the inode information
1269 * with d_instantiate().
1270 */
1271static int
1272jffs_create(struct inode *dir, struct dentry *dentry, int mode,
1273 struct nameidata *nd)
1274{
1275 struct jffs_raw_inode raw_inode;
1276 struct jffs_control *c;
1277 struct jffs_node *node;
1278 struct jffs_file *dir_f; /* JFFS representation of the directory. */
1279 struct inode *inode;
1280 int err;
1281
1282 lock_kernel();
1283 D1({
1284 int len = dentry->d_name.len;
1285 char *s = (char *)kmalloc(len + 1, GFP_KERNEL);
1286 memcpy(s, dentry->d_name.name, len);
1287 s[len] = '\0';
1288 printk("jffs_create(): dir: 0x%p, name: \"%s\"\n", dir, s);
1289 kfree(s);
1290 });
1291
1292 dir_f = (struct jffs_file *)dir->u.generic_ip;
1293 ASSERT(if (!dir_f) {
1294 printk(KERN_ERR "jffs_create(): No reference to a "
1295 "jffs_file struct in inode.\n");
1296 unlock_kernel();
1297 return -EIO;
1298 });
1299
1300 c = dir_f->c;
1301
1302 /* Create a node and initialize as much as needed. */
1303 if (!(node = jffs_alloc_node())) {
1304 D(printk("jffs_create(): Allocation failed: node == 0\n"));
1305 unlock_kernel();
1306 return -ENOMEM;
1307 }
1308 D3(printk (KERN_NOTICE "create(): down biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -08001309 mutex_lock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310
1311 node->data_offset = 0;
1312 node->removed_size = 0;
1313
1314 /* Initialize the raw inode. */
1315 raw_inode.magic = JFFS_MAGIC_BITMASK;
1316 raw_inode.ino = c->next_ino++;
1317 raw_inode.pino = dir_f->ino;
1318 raw_inode.version = 1;
1319 raw_inode.mode = mode;
1320 raw_inode.uid = current->fsuid;
1321 raw_inode.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
1322 raw_inode.atime = get_seconds();
1323 raw_inode.mtime = raw_inode.atime;
1324 raw_inode.ctime = raw_inode.atime;
1325 raw_inode.offset = 0;
1326 raw_inode.dsize = 0;
1327 raw_inode.rsize = 0;
1328 raw_inode.nsize = dentry->d_name.len;
1329 raw_inode.nlink = 1;
1330 raw_inode.spare = 0;
1331 raw_inode.rename = 0;
1332 raw_inode.deleted = 0;
1333
1334 /* Write the new node to the flash. */
1335 if ((err = jffs_write_node(c, node, &raw_inode,
1336 dentry->d_name.name, NULL, 0, NULL)) < 0) {
1337 D(printk("jffs_create(): jffs_write_node() failed.\n"));
1338 jffs_free_node(node);
1339 goto jffs_create_end;
1340 }
1341
1342 /* Insert the new node into the file system. */
1343 if ((err = jffs_insert_node(c, NULL, &raw_inode, dentry->d_name.name,
1344 node)) < 0) {
1345 goto jffs_create_end;
1346 }
1347
1348 /* Initialize an inode. */
1349 inode = jffs_new_inode(dir, &raw_inode, &err);
1350 if (inode == NULL) {
1351 goto jffs_create_end;
1352 }
1353 err = 0;
1354 inode->i_op = &jffs_file_inode_operations;
1355 inode->i_fop = &jffs_file_operations;
1356 inode->i_mapping->a_ops = &jffs_address_operations;
1357 inode->i_mapping->nrpages = 0;
1358
1359 d_instantiate(dentry, inode);
1360 jffs_create_end:
1361 D3(printk (KERN_NOTICE "create(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -08001362 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363 unlock_kernel();
1364 return err;
1365} /* jffs_create() */
1366
1367
1368/* Write, append or rewrite data to an existing file. */
1369static ssize_t
1370jffs_file_write(struct file *filp, const char *buf, size_t count,
1371 loff_t *ppos)
1372{
1373 struct jffs_raw_inode raw_inode;
1374 struct jffs_control *c;
1375 struct jffs_file *f;
1376 struct jffs_node *node;
1377 struct dentry *dentry = filp->f_dentry;
1378 struct inode *inode = dentry->d_inode;
1379 int recoverable = 0;
1380 size_t written = 0;
1381 __u32 thiscount = count;
1382 loff_t pos = *ppos;
1383 int err;
1384
1385 inode = filp->f_dentry->d_inode;
1386
1387 D2(printk("***jffs_file_write(): inode: 0x%p (ino: %lu), "
1388 "filp: 0x%p, buf: 0x%p, count: %d\n",
1389 inode, inode->i_ino, filp, buf, count));
1390
1391#if 0
1392 if (inode->i_sb->s_flags & MS_RDONLY) {
1393 D(printk("jffs_file_write(): MS_RDONLY\n"));
1394 err = -EROFS;
1395 goto out_isem;
1396 }
1397#endif
1398 err = -EINVAL;
1399
1400 if (!S_ISREG(inode->i_mode)) {
1401 D(printk("jffs_file_write(): inode->i_mode == 0x%08x\n",
1402 inode->i_mode));
1403 goto out_isem;
1404 }
1405
1406 if (!(f = (struct jffs_file *)inode->u.generic_ip)) {
1407 D(printk("jffs_file_write(): inode->u.generic_ip = 0x%p\n",
1408 inode->u.generic_ip));
1409 goto out_isem;
1410 }
1411
1412 c = f->c;
1413
1414 /*
1415 * This will never trigger with sane page sizes. leave it in
1416 * anyway, since I'm thinking about how to merge larger writes
1417 * (the current idea is to poke a thread that does the actual
Jes Sorensen1b1dcc12006-01-09 15:59:24 -08001418 * I/O and starts by doing a mutex_lock(&inode->i_mutex). then we
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419 * would need to get the page cache pages and have a list of
1420 * I/O requests and do write-merging here.
1421 * -- prumpf
1422 */
1423 thiscount = min(c->fmc->max_chunk_size - sizeof(struct jffs_raw_inode), count);
1424
1425 D3(printk (KERN_NOTICE "file_write(): down biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -08001426 mutex_lock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427
1428 /* Urgh. POSIX says we can do short writes if we feel like it.
1429 * In practice, we can't. Nothing will cope. So we loop until
1430 * we're done.
1431 *
1432 * <_Anarchy_> posix and reality are not interconnected on this issue
1433 */
1434 while (count) {
1435 /* Things are going to be written so we could allocate and
1436 initialize the necessary data structures now. */
1437 if (!(node = jffs_alloc_node())) {
1438 D(printk("jffs_file_write(): node == 0\n"));
1439 err = -ENOMEM;
1440 goto out;
1441 }
1442
1443 node->data_offset = pos;
1444 node->removed_size = 0;
1445
1446 /* Initialize the raw inode. */
1447 raw_inode.magic = JFFS_MAGIC_BITMASK;
1448 raw_inode.ino = f->ino;
1449 raw_inode.pino = f->pino;
1450
1451 raw_inode.mode = f->mode;
1452
1453 raw_inode.uid = f->uid;
1454 raw_inode.gid = f->gid;
1455 raw_inode.atime = get_seconds();
1456 raw_inode.mtime = raw_inode.atime;
1457 raw_inode.ctime = f->ctime;
1458 raw_inode.offset = pos;
1459 raw_inode.dsize = thiscount;
1460 raw_inode.rsize = 0;
1461 raw_inode.nsize = f->nsize;
1462 raw_inode.nlink = f->nlink;
1463 raw_inode.spare = 0;
1464 raw_inode.rename = 0;
1465 raw_inode.deleted = 0;
1466
1467 if (pos < f->size) {
1468 node->removed_size = raw_inode.rsize = min(thiscount, (__u32)(f->size - pos));
1469
1470 /* If this node is going entirely over the top of old data,
1471 we can allow it to go into the reserved space, because
1472 we know that GC can reclaim the space later.
1473 */
1474 if (pos + thiscount < f->size) {
1475 /* If all the data we're overwriting are _real_,
1476 not just holes, then:
1477 recoverable = 1;
1478 */
1479 }
1480 }
1481
1482 /* Write the new node to the flash. */
1483 /* NOTE: We would be quite happy if jffs_write_node() wrote a
1484 smaller node than we were expecting. There's no need for it
1485 to waste the space at the end of the flash just because it's
1486 a little smaller than what we asked for. But that's a whole
1487 new can of worms which I'm not going to open this week.
1488 -- dwmw2.
1489 */
1490 if ((err = jffs_write_node(c, node, &raw_inode, f->name,
1491 (const unsigned char *)buf,
1492 recoverable, f)) < 0) {
1493 D(printk("jffs_file_write(): jffs_write_node() failed.\n"));
1494 jffs_free_node(node);
1495 goto out;
1496 }
1497
1498 written += err;
1499 buf += err;
1500 count -= err;
1501 pos += err;
1502
1503 /* Insert the new node into the file system. */
1504 if ((err = jffs_insert_node(c, f, &raw_inode, NULL, node)) < 0) {
1505 goto out;
1506 }
1507
1508 D3(printk("jffs_file_write(): new f_pos %ld.\n", (long)pos));
1509
1510 thiscount = min(c->fmc->max_chunk_size - sizeof(struct jffs_raw_inode), count);
1511 }
1512 out:
1513 D3(printk (KERN_NOTICE "file_write(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -08001514 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515
1516 /* Fix things in the real inode. */
1517 if (pos > inode->i_size) {
1518 inode->i_size = pos;
1519 inode->i_blocks = (inode->i_size + 511) >> 9;
1520 }
1521 inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
1522 mark_inode_dirty(inode);
1523 invalidate_inode_pages(inode->i_mapping);
1524
1525 out_isem:
1526 return err;
1527} /* jffs_file_write() */
1528
1529static int
1530jffs_prepare_write(struct file *filp, struct page *page,
1531 unsigned from, unsigned to)
1532{
1533 /* FIXME: we should detect some error conditions here */
1534
1535 /* Bugger that. We should make sure the page is uptodate */
1536 if (!PageUptodate(page) && (from || to < PAGE_CACHE_SIZE))
1537 return jffs_do_readpage_nolock(filp, page);
1538
1539 return 0;
1540} /* jffs_prepare_write() */
1541
1542static int
1543jffs_commit_write(struct file *filp, struct page *page,
1544 unsigned from, unsigned to)
1545{
1546 void *addr = page_address(page) + from;
1547 /* XXX: PAGE_CACHE_SHIFT or PAGE_SHIFT */
Andrew Morton54b21a72006-01-08 01:03:05 -08001548 loff_t pos = page_offset(page) + from;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549
1550 return jffs_file_write(filp, addr, to-from, &pos);
1551} /* jffs_commit_write() */
1552
1553/* This is our ioctl() routine. */
1554static int
1555jffs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
1556 unsigned long arg)
1557{
1558 struct jffs_control *c;
1559 int ret = 0;
1560
1561 D2(printk("***jffs_ioctl(): cmd = 0x%08x, arg = 0x%08lx\n",
1562 cmd, arg));
1563
1564 if (!(c = (struct jffs_control *)inode->i_sb->s_fs_info)) {
1565 printk(KERN_ERR "JFFS: Bad inode in ioctl() call. "
1566 "(cmd = 0x%08x)\n", cmd);
1567 return -EIO;
1568 }
1569 D3(printk (KERN_NOTICE "ioctl(): down biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -08001570 mutex_lock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571
1572 switch (cmd) {
1573 case JFFS_PRINT_HASH:
1574 jffs_print_hash_table(c);
1575 break;
1576 case JFFS_PRINT_TREE:
1577 jffs_print_tree(c->root, 0);
1578 break;
1579 case JFFS_GET_STATUS:
1580 {
1581 struct jffs_flash_status fst;
1582 struct jffs_fmcontrol *fmc = c->fmc;
1583 printk("Flash status -- ");
1584 if (!access_ok(VERIFY_WRITE,
1585 (struct jffs_flash_status __user *)arg,
1586 sizeof(struct jffs_flash_status))) {
1587 D(printk("jffs_ioctl(): Bad arg in "
1588 "JFFS_GET_STATUS ioctl!\n"));
1589 ret = -EFAULT;
1590 break;
1591 }
1592 fst.size = fmc->flash_size;
1593 fst.used = fmc->used_size;
1594 fst.dirty = fmc->dirty_size;
1595 fst.begin = fmc->head->offset;
1596 fst.end = fmc->tail->offset + fmc->tail->size;
1597 printk("size: %d, used: %d, dirty: %d, "
1598 "begin: %d, end: %d\n",
1599 fst.size, fst.used, fst.dirty,
1600 fst.begin, fst.end);
1601 if (copy_to_user((struct jffs_flash_status __user *)arg,
1602 &fst,
1603 sizeof(struct jffs_flash_status))) {
1604 ret = -EFAULT;
1605 }
1606 }
1607 break;
1608 default:
1609 ret = -ENOTTY;
1610 }
1611 D3(printk (KERN_NOTICE "ioctl(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -08001612 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613 return ret;
1614} /* jffs_ioctl() */
1615
1616
1617static struct address_space_operations jffs_address_operations = {
1618 .readpage = jffs_readpage,
1619 .prepare_write = jffs_prepare_write,
1620 .commit_write = jffs_commit_write,
1621};
1622
1623static int jffs_fsync(struct file *f, struct dentry *d, int datasync)
1624{
1625 /* We currently have O_SYNC operations at all times.
1626 Do nothing.
1627 */
1628 return 0;
1629}
1630
1631
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632static struct file_operations jffs_file_operations =
1633{
1634 .open = generic_file_open,
1635 .llseek = generic_file_llseek,
1636 .read = generic_file_read,
1637 .write = generic_file_write,
1638 .ioctl = jffs_ioctl,
1639 .mmap = generic_file_readonly_mmap,
1640 .fsync = jffs_fsync,
1641 .sendfile = generic_file_sendfile,
1642};
1643
1644
1645static struct inode_operations jffs_file_inode_operations =
1646{
1647 .lookup = jffs_lookup, /* lookup */
1648 .setattr = jffs_setattr,
1649};
1650
1651
1652static struct file_operations jffs_dir_operations =
1653{
1654 .readdir = jffs_readdir,
1655};
1656
1657
1658static struct inode_operations jffs_dir_inode_operations =
1659{
1660 .create = jffs_create,
1661 .lookup = jffs_lookup,
1662 .unlink = jffs_unlink,
1663 .symlink = jffs_symlink,
1664 .mkdir = jffs_mkdir,
1665 .rmdir = jffs_rmdir,
1666 .mknod = jffs_mknod,
1667 .rename = jffs_rename,
1668 .setattr = jffs_setattr,
1669};
1670
1671
1672/* Initialize an inode for the VFS. */
1673static void
1674jffs_read_inode(struct inode *inode)
1675{
1676 struct jffs_file *f;
1677 struct jffs_control *c;
1678
1679 D3(printk("jffs_read_inode(): inode->i_ino == %lu\n", inode->i_ino));
1680
1681 if (!inode->i_sb) {
1682 D(printk("jffs_read_inode(): !inode->i_sb ==> "
1683 "No super block!\n"));
1684 return;
1685 }
1686 c = (struct jffs_control *)inode->i_sb->s_fs_info;
1687 D3(printk (KERN_NOTICE "read_inode(): down biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -08001688 mutex_lock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689 if (!(f = jffs_find_file(c, inode->i_ino))) {
1690 D(printk("jffs_read_inode(): No such inode (%lu).\n",
1691 inode->i_ino));
1692 D3(printk (KERN_NOTICE "read_inode(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -08001693 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001694 return;
1695 }
1696 inode->u.generic_ip = (void *)f;
1697 inode->i_mode = f->mode;
1698 inode->i_nlink = f->nlink;
1699 inode->i_uid = f->uid;
1700 inode->i_gid = f->gid;
1701 inode->i_size = f->size;
1702 inode->i_atime.tv_sec = f->atime;
1703 inode->i_mtime.tv_sec = f->mtime;
1704 inode->i_ctime.tv_sec = f->ctime;
1705 inode->i_atime.tv_nsec =
1706 inode->i_mtime.tv_nsec =
1707 inode->i_ctime.tv_nsec = 0;
1708
1709 inode->i_blksize = PAGE_SIZE;
1710 inode->i_blocks = (inode->i_size + 511) >> 9;
1711 if (S_ISREG(inode->i_mode)) {
1712 inode->i_op = &jffs_file_inode_operations;
1713 inode->i_fop = &jffs_file_operations;
1714 inode->i_mapping->a_ops = &jffs_address_operations;
1715 }
1716 else if (S_ISDIR(inode->i_mode)) {
1717 inode->i_op = &jffs_dir_inode_operations;
1718 inode->i_fop = &jffs_dir_operations;
1719 }
1720 else if (S_ISLNK(inode->i_mode)) {
1721 inode->i_op = &page_symlink_inode_operations;
1722 inode->i_mapping->a_ops = &jffs_address_operations;
1723 }
1724 else {
1725 /* If the node is a device of some sort, then the number of
1726 the device should be read from the flash memory and then
1727 added to the inode's i_rdev member. */
1728 u16 val;
1729 jffs_read_data(f, (char *)&val, 0, 2);
1730 init_special_inode(inode, inode->i_mode,
1731 old_decode_dev(val));
1732 }
1733
1734 D3(printk (KERN_NOTICE "read_inode(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -08001735 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736}
1737
1738
1739static void
1740jffs_delete_inode(struct inode *inode)
1741{
1742 struct jffs_file *f;
1743 struct jffs_control *c;
1744 D3(printk("jffs_delete_inode(): inode->i_ino == %lu\n",
1745 inode->i_ino));
1746
Mark Fashehfef26652005-09-09 13:01:31 -07001747 truncate_inode_pages(&inode->i_data, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001748 lock_kernel();
1749 inode->i_size = 0;
1750 inode->i_blocks = 0;
1751 inode->u.generic_ip = NULL;
1752 clear_inode(inode);
1753 if (inode->i_nlink == 0) {
1754 c = (struct jffs_control *) inode->i_sb->s_fs_info;
1755 f = (struct jffs_file *) jffs_find_file (c, inode->i_ino);
1756 jffs_possibly_delete_file(f);
1757 }
1758
1759 unlock_kernel();
1760}
1761
1762
1763static void
1764jffs_write_super(struct super_block *sb)
1765{
1766 struct jffs_control *c = (struct jffs_control *)sb->s_fs_info;
1767 lock_kernel();
1768 jffs_garbage_collect_trigger(c);
1769 unlock_kernel();
1770}
1771
1772static int jffs_remount(struct super_block *sb, int *flags, char *data)
1773{
1774 *flags |= MS_NODIRATIME;
1775 return 0;
1776}
1777
1778static struct super_operations jffs_ops =
1779{
1780 .read_inode = jffs_read_inode,
1781 .delete_inode = jffs_delete_inode,
1782 .put_super = jffs_put_super,
1783 .write_super = jffs_write_super,
1784 .statfs = jffs_statfs,
1785 .remount_fs = jffs_remount,
1786};
1787
1788static struct super_block *jffs_get_sb(struct file_system_type *fs_type,
1789 int flags, const char *dev_name, void *data)
1790{
1791 return get_sb_bdev(fs_type, flags, dev_name, data, jffs_fill_super);
1792}
1793
1794static struct file_system_type jffs_fs_type = {
1795 .owner = THIS_MODULE,
1796 .name = "jffs",
1797 .get_sb = jffs_get_sb,
1798 .kill_sb = kill_block_super,
1799 .fs_flags = FS_REQUIRES_DEV,
1800};
1801
1802static int __init
1803init_jffs_fs(void)
1804{
1805 printk(KERN_INFO "JFFS version " JFFS_VERSION_STRING
1806 ", (C) 1999, 2000 Axis Communications AB\n");
1807
1808#ifdef CONFIG_JFFS_PROC_FS
1809 jffs_proc_root = proc_mkdir("jffs", proc_root_fs);
1810 if (!jffs_proc_root) {
1811 printk(KERN_WARNING "cannot create /proc/jffs entry\n");
1812 }
1813#endif
1814 fm_cache = kmem_cache_create("jffs_fm", sizeof(struct jffs_fm),
Paul Jacksonfffb60f2006-03-24 03:16:06 -08001815 0,
1816 SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD,
1817 NULL, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001818 if (!fm_cache) {
1819 return -ENOMEM;
1820 }
1821
1822 node_cache = kmem_cache_create("jffs_node",sizeof(struct jffs_node),
Paul Jacksonfffb60f2006-03-24 03:16:06 -08001823 0,
1824 SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD,
1825 NULL, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001826 if (!node_cache) {
1827 kmem_cache_destroy(fm_cache);
1828 return -ENOMEM;
1829 }
1830
1831 return register_filesystem(&jffs_fs_type);
1832}
1833
1834static void __exit
1835exit_jffs_fs(void)
1836{
1837 unregister_filesystem(&jffs_fs_type);
1838 kmem_cache_destroy(fm_cache);
1839 kmem_cache_destroy(node_cache);
1840}
1841
1842module_init(init_jffs_fs)
1843module_exit(exit_jffs_fs)
1844
1845MODULE_DESCRIPTION("The Journalling Flash File System");
1846MODULE_AUTHOR("Axis Communications AB.");
1847MODULE_LICENSE("GPL");