Merge with Linu 2.4.0-test6-pre6.
[linux-2.6/linux-mips.git] / fs / jffs / inode-v23.c
blob06ac42709dc41a34647a857d005ff388ea25e7aa
1 /*
2 * JFFS -- Journalling Flash File System, Linux implementation.
4 * Copyright (C) 1999, 2000 Finn Hakansson, Axis Communications, Inc.
6 * This is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * $Id: inode-v23.c,v 1.17 2000/07/06 20:35:19 prumpf Exp $
14 * Ported to Linux 2.3.x and MTD:
15 * Copyright (C) 2000 Alexander Larsson (alex@cendio.se), Cendio Systems AB
19 /* inode.c -- Contains the code that is called from the VFS. */
21 /* TODO-ALEX:
22 * uid and gid are just 16 bit.
23 * jffs_file_write reads from user-space pointers without xx_from_user
24 * maybe other stuff do to.
27 #include <linux/config.h>
28 #include <linux/module.h>
29 #include <linux/init.h>
30 #include <linux/types.h>
31 #include <linux/errno.h>
32 #include <linux/malloc.h>
33 #include <linux/jffs.h>
34 #include <linux/fs.h>
35 #include <linux/locks.h>
36 #include <linux/smp_lock.h>
37 #include <linux/sched.h>
38 #include <linux/ioctl.h>
39 #include <linux/stat.h>
40 #include <linux/blkdev.h>
41 #include <linux/quotaops.h>
42 #include <asm/semaphore.h>
43 #include <asm/byteorder.h>
44 #include <asm/uaccess.h>
45 #include "jffs_fm.h"
46 #include "intrep.h"
48 #if defined(CONFIG_JFFS_FS_VERBOSE) && CONFIG_JFFS_FS_VERBOSE
49 #define D(x) x
50 #else
51 #define D(x)
52 #endif
53 #define D1(x) D(x)
54 #define D2(x)
55 #define D3(x)
56 #define ASSERT(x) x
58 static int jffs_remove(struct inode *dir, struct dentry *dentry, int type);
60 static struct super_operations jffs_ops;
61 static struct file_operations jffs_file_operations;
62 static struct inode_operations jffs_file_inode_operations;
63 static struct file_operations jffs_dir_operations;
64 static struct inode_operations jffs_dir_inode_operations;
65 static struct address_space_operations jffs_address_operations;
67 /* Called by the VFS at mount time to initialize the whole file system. */
68 static struct super_block *
69 jffs_read_super(struct super_block *sb, void *data, int silent)
71 kdev_t dev = sb->s_dev;
72 struct inode *root_inode;
74 printk(KERN_NOTICE "JFFS: Trying to mount device %s.\n",
75 kdevname(dev));
77 if (MAJOR(dev)!=MTD_BLOCK_MAJOR) {
78 printk(KERN_WARNING "JFFS: Trying to mount non-mtd device.\n");
79 return 0;
82 set_blocksize(dev, PAGE_CACHE_SIZE);
83 sb->s_blocksize = PAGE_CACHE_SIZE;
84 sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
85 sb->u.generic_sbp = (void *) 0;
87 /* Build the file system. */
88 if (jffs_build_fs(sb) < 0) {
89 goto jffs_sb_err1;
93 * set up enough so that we can read an inode
95 sb->s_magic = JFFS_MAGIC_SB_BITMASK;
96 sb->s_op = &jffs_ops;
98 root_inode = iget(sb, JFFS_MIN_INO);
99 if (!root_inode)
100 goto jffs_sb_err2;
102 /* Get the root directory of this file system. */
103 if (!(sb->s_root = d_alloc_root(root_inode))) {
104 goto jffs_sb_err3;
107 #ifdef USE_GC
108 /* Do a garbage collect every time we mount. */
109 jffs_garbage_collect((struct jffs_control *)sb->u.generic_sbp);
110 #endif
112 printk(KERN_NOTICE "JFFS: Successfully mounted device %s.\n",
113 kdevname(dev));
114 return sb;
116 jffs_sb_err3:
117 iput(root_inode);
118 jffs_sb_err2:
119 jffs_cleanup_control((struct jffs_control *)sb->u.generic_sbp);
120 jffs_sb_err1:
122 printk(KERN_WARNING "JFFS: Failed to mount device %s.\n",
123 kdevname(dev));
124 return 0;
128 /* This function is called when the file system is umounted. */
129 static void
130 jffs_put_super(struct super_block *sb)
132 kdev_t dev = sb->s_dev;
133 D2(printk("jffs_put_super()\n"));
134 sb->s_dev = 0;
135 jffs_cleanup_control((struct jffs_control *)sb->u.generic_sbp);
136 printk(KERN_NOTICE "JFFS: Successfully unmounted device %s.\n",
137 kdevname(dev));
140 /* This function is called when user commands like chmod, chgrp and
141 chown are executed. System calls like trunc() results in a call
142 to this function. */
143 static int
144 jffs_setattr(struct dentry *dentry, struct iattr *iattr)
146 struct inode *inode = dentry->d_inode;
147 struct jffs_raw_inode raw_inode;
148 struct jffs_control *c;
149 struct jffs_fmcontrol *fmc;
150 struct jffs_file *f;
151 struct jffs_node *new_node;
152 char *name = 0;
153 int update_all;
154 int res;
156 f = (struct jffs_file *)inode->u.generic_ip;
157 ASSERT(if (!f) {
158 printk("jffs_setattr(): Invalid inode number: %lu\n",
159 inode->i_ino);
160 return -1;
163 D1(printk("***jffs_setattr(): file: \"%s\", ino: %u\n",
164 f->name, f->ino));
166 c = f->c;
167 fmc = c->fmc;
168 update_all = iattr->ia_valid & ATTR_FORCE;
170 if (!JFFS_ENOUGH_SPACE(fmc)) {
171 if ( (update_all || iattr->ia_valid & ATTR_SIZE)
172 && (iattr->ia_size < f->size) ) {
173 /* See this case where someone is trying to
174 shrink the size of a file as an exception.
175 Accept it. */
176 /* TODO: Might just shrink it a bit?
177 check f->size - ia_size */
178 } else {
179 D1(printk("jffs_setattr(): Free size = %u\n",
180 jffs_free_size1(fmc)
181 + jffs_free_size2(fmc)));
182 D(printk(KERN_NOTICE "JFFS: No space left on "
183 "device\n"));
184 return -ENOSPC;
188 if (!(new_node = (struct jffs_node *)
189 kmalloc(sizeof(struct jffs_node), GFP_KERNEL))) {
190 D(printk("jffs_setattr(): Allocation failed!\n"));
191 return -ENOMEM;
193 DJM(no_jffs_node++);
194 new_node->data_offset = 0;
195 new_node->removed_size = 0;
196 raw_inode.magic = JFFS_MAGIC_BITMASK;
197 raw_inode.ino = f->ino;
198 raw_inode.pino = f->pino;
199 raw_inode.version = f->highest_version + 1;
200 raw_inode.mode = f->mode;
201 raw_inode.uid = f->uid;
202 raw_inode.gid = f->gid;
203 raw_inode.atime = f->atime;
204 raw_inode.mtime = f->mtime;
205 raw_inode.ctime = f->ctime;
206 raw_inode.dsize = 0;
207 raw_inode.offset = 0;
208 raw_inode.rsize = 0;
209 raw_inode.dsize = 0;
210 raw_inode.nsize = 0;
211 raw_inode.nlink = f->nlink;
212 raw_inode.spare = 0;
213 raw_inode.rename = 0;
214 raw_inode.deleted = 0;
216 if (update_all || iattr->ia_valid & ATTR_MODE) {
217 raw_inode.mode = iattr->ia_mode;
218 inode->i_mode = iattr->ia_mode;
220 if (update_all || iattr->ia_valid & ATTR_UID) {
221 raw_inode.uid = iattr->ia_uid;
222 inode->i_uid = iattr->ia_uid;
224 if (update_all || iattr->ia_valid & ATTR_GID) {
225 raw_inode.gid = iattr->ia_gid;
226 inode->i_gid = iattr->ia_gid;
228 if (update_all || iattr->ia_valid & ATTR_SIZE) {
229 int len;
230 D1(printk("jffs_notify_change(): Changing size "
231 "to %lu bytes!\n", (long)iattr->ia_size));
232 raw_inode.offset = iattr->ia_size;
234 /* Calculate how many bytes need to be removed from
235 the end. */
236 if (f->size < iattr->ia_size) {
237 len = 0;
239 else {
240 len = f->size - iattr->ia_size;
243 raw_inode.rsize = len;
245 /* The updated node will be a removal node, with
246 base at the new size and size of the nbr of bytes
247 to be removed. */
248 new_node->data_offset = iattr->ia_size;
249 new_node->removed_size = len;
250 inode->i_size = iattr->ia_size;
252 /* If we truncate a file we want to add the name. If we
253 always do that, we could perhaps free more space on
254 the flash (and besides it doesn't hurt). */
255 name = f->name;
256 raw_inode.nsize = f->nsize;
257 if (len) {
258 invalidate_inode_pages(inode);
260 inode->i_ctime = CURRENT_TIME;
261 inode->i_mtime = inode->i_ctime;
263 if (update_all || iattr->ia_valid & ATTR_ATIME) {
264 raw_inode.atime = iattr->ia_atime;
265 inode->i_atime = iattr->ia_atime;
267 if (update_all || iattr->ia_valid & ATTR_MTIME) {
268 raw_inode.mtime = iattr->ia_mtime;
269 inode->i_mtime = iattr->ia_mtime;
271 if (update_all || iattr->ia_valid & ATTR_CTIME) {
272 raw_inode.ctime = iattr->ia_ctime;
273 inode->i_ctime = iattr->ia_ctime;
276 /* Write this node to the flash. */
277 if ((res = jffs_write_node(c, new_node, &raw_inode, name, 0)) < 0) {
278 D(printk("jffs_notify_change(): The write failed!\n"));
279 kfree(new_node);
280 DJM(no_jffs_node--);
281 return res;
284 jffs_insert_node(c, f, &raw_inode, 0, new_node);
286 mark_inode_dirty(inode);
288 return 0;
289 } /* jffs_notify_change() */
291 struct inode * jffs_new_inode(const struct inode * dir, struct jffs_raw_inode *raw_inode, int * err)
293 struct super_block * sb;
294 struct inode * inode;
295 struct jffs_control *c;
297 inode = get_empty_inode();
298 if (!inode) {
299 *err = -ENOMEM;
300 return NULL;
303 sb = dir->i_sb;
304 c = (struct jffs_control *)sb->u.generic_sbp;
306 inode->i_sb = sb;
307 inode->i_dev = sb->s_dev;
308 inode->i_ino = raw_inode->ino;
309 inode->i_mode = raw_inode->mode;
310 inode->i_nlink = raw_inode->nlink;
311 inode->i_uid = raw_inode->uid;
312 inode->i_gid = raw_inode->gid;
313 inode->i_rdev = 0;
314 inode->i_size = raw_inode->dsize;
315 inode->i_atime = raw_inode->atime;
316 inode->i_mtime = raw_inode->mtime;
317 inode->i_ctime = raw_inode->ctime;
318 inode->i_blksize = PAGE_SIZE; /* This is the optimal IO size (for stat), not the fs block size */
319 inode->i_blocks = 0;
320 inode->i_version = 0;
321 inode->i_flags = sb->s_flags;
322 inode->u.generic_ip = (void *)jffs_find_file(c, raw_inode->ino);
324 insert_inode_hash(inode);
326 return inode;
329 /* Get statistics of the file system. */
331 jffs_statfs(struct super_block *sb, struct statfs *buf)
333 struct jffs_control *c = (struct jffs_control *) sb->u.generic_sbp;
334 struct jffs_fmcontrol *fmc = c->fmc;
336 D2(printk("jffs_statfs()\n"));
338 buf->f_type = JFFS_MAGIC_SB_BITMASK;
339 buf->f_bsize = PAGE_CACHE_SIZE;
340 buf->f_blocks = (fmc->flash_size / PAGE_CACHE_SIZE)
341 - (fmc->min_free_size / PAGE_CACHE_SIZE);
342 buf->f_bfree = (jffs_free_size1(fmc) / PAGE_CACHE_SIZE
343 + jffs_free_size2(fmc) / PAGE_CACHE_SIZE)
344 - (fmc->min_free_size / PAGE_CACHE_SIZE);
345 buf->f_bavail = buf->f_bfree;
347 /* Find out how many files there are in the filesystem. */
348 buf->f_files = jffs_foreach_file(c, jffs_file_count);
349 buf->f_ffree = buf->f_bfree;
350 /* buf->f_fsid = 0; */
351 buf->f_namelen = JFFS_MAX_NAME_LEN;
352 return 0;
355 /* Rename a file. */
357 jffs_rename(struct inode *old_dir, struct dentry *old_dentry,
358 struct inode *new_dir, struct dentry *new_dentry)
360 struct jffs_raw_inode raw_inode;
361 struct jffs_control *c;
362 struct jffs_file *old_dir_f;
363 struct jffs_file *new_dir_f;
364 struct jffs_file *del_f;
365 struct jffs_file *f;
366 struct jffs_node *node;
367 struct inode *inode;
368 int result = 0;
369 __u32 rename_data = 0;
371 D2(printk("***jffs_rename()\n"));
373 D(printk("jffs_rename(): old_dir: 0x%p, old name: 0x%p, "
374 "new_dir: 0x%p, new name: 0x%p\n",
375 old_dir, old_dentry->d_name.name,
376 new_dir, new_dentry->d_name.name));
378 c = (struct jffs_control *)old_dir->i_sb->u.generic_sbp;
379 ASSERT(if (!c) {
380 printk(KERN_ERR "jffs_rename(): The old_dir inode "
381 "didn't have a reference to a jffs_file struct\n");
382 return -1;
385 if (!JFFS_ENOUGH_SPACE(c->fmc)) {
386 D1(printk("jffs_rename(): Free size = %u\n",
387 jffs_free_size1(c->fmc) + jffs_free_size2(c->fmc)));
388 D(printk(KERN_NOTICE "JFFS: No space left on device\n"));
389 return -ENOSPC;
392 /* Find the the old directory. */
393 result = -ENOTDIR;
394 if (!(old_dir_f = (struct jffs_file *)old_dir->u.generic_ip)) {
395 D(printk("jffs_rename(): Old dir invalid.\n"));
396 goto jffs_rename_end;
399 /* Try to find the file to move. */
400 result = -ENOENT;
401 if (!(f = jffs_find_child(old_dir_f, old_dentry->d_name.name,
402 old_dentry->d_name.len))) {
403 goto jffs_rename_end;
406 /* Try to find the new directory's node. */
407 result = -ENOTDIR;
408 if (!(new_dir_f = (struct jffs_file *)new_dir->u.generic_ip)) {
409 D(printk("jffs_rename(): New dir invalid.\n"));
410 goto jffs_rename_end;
413 /* Create a node and initialize as much as needed. */
414 result = -ENOMEM;
415 if (!(node = (struct jffs_node *) kmalloc(sizeof(struct jffs_node),
416 GFP_KERNEL))) {
417 D(printk("jffs_rename(): Allocation failed: node == 0\n"));
418 goto jffs_rename_end;
420 DJM(no_jffs_node++);
421 node->data_offset = 0;
422 node->removed_size = 0;
424 /* Initialize the raw inode. */
425 raw_inode.magic = JFFS_MAGIC_BITMASK;
426 raw_inode.ino = f->ino;
427 raw_inode.pino = new_dir_f->ino;
428 raw_inode.version = f->highest_version + 1;
429 raw_inode.mode = f->mode;
430 raw_inode.uid = current->fsuid;
431 raw_inode.gid = current->fsgid;
432 #if 0
433 raw_inode.uid = f->uid;
434 raw_inode.gid = f->gid;
435 #endif
436 raw_inode.atime = CURRENT_TIME;
437 raw_inode.mtime = raw_inode.atime;
438 raw_inode.ctime = f->ctime;
439 raw_inode.offset = 0;
440 raw_inode.dsize = 0;
441 raw_inode.rsize = 0;
442 raw_inode.nsize = new_dentry->d_name.len;
443 raw_inode.nlink = f->nlink;
444 raw_inode.spare = 0;
445 raw_inode.rename = 0;
446 raw_inode.deleted = 0;
448 /* See if there already exists a file with the same name as
449 new_name. */
450 if ((del_f = jffs_find_child(new_dir_f, new_dentry->d_name.name,
451 new_dentry->d_name.len))) {
452 raw_inode.rename = 1;
453 /*raw_inode.mode = del_f->ino;*/
456 /* Write the new node to the flash memory. */
457 if ((result = jffs_write_node(c, node, &raw_inode, new_dentry->d_name.name,
458 (unsigned char*)&rename_data)) < 0) {
459 D(printk("jffs_rename(): Failed to write node to flash.\n"));
460 kfree(node);
461 DJM(no_jffs_node--);
462 goto jffs_rename_end;
465 if (raw_inode.rename) {
466 /* The file with the same name must be deleted. */
467 c->fmc->no_call_gc = 1; /* TODO: What kind of locking is this? */
468 if ((result = jffs_remove(new_dir, new_dentry, del_f->mode)) < 0) {
469 /* This is really bad. */
470 printk(KERN_ERR "JFFS: An error occurred in "
471 "rename().\n");
473 c->fmc->no_call_gc = 0;
476 if (old_dir_f != new_dir_f) {
477 /* Remove the file from its old position in the
478 filesystem tree. */
479 jffs_unlink_file_from_tree(f);
482 /* Insert the new node into the file system. */
483 if ((result = jffs_insert_node(c, f, &raw_inode,
484 new_dentry->d_name.name, node)) < 0) {
485 D(printk(KERN_ERR "jffs_rename(): jffs_insert_node() "
486 "failed!\n"));
489 if (old_dir_f != new_dir_f) {
490 /* Insert the file to its new position in the
491 file system. */
492 jffs_insert_file_into_tree(f);
495 /* This is a kind of update of the inode we're about to make
496 here. This is what they do in ext2fs. Kind of. */
497 if ((inode = iget(new_dir->i_sb, f->ino))) {
498 inode->i_ctime = CURRENT_TIME;
499 mark_inode_dirty(inode);
500 iput(inode);
503 jffs_rename_end:
505 return result;
506 } /* jffs_rename() */
509 /* Read the contents of a directory. Used by programs like `ls'
510 for instance. */
511 static int
512 jffs_readdir(struct file *filp, void *dirent, filldir_t filldir)
514 struct jffs_file *f;
515 struct dentry *dentry = filp->f_dentry;
516 struct inode *inode = dentry->d_inode;
517 int j;
518 int ddino;
520 D2(printk("jffs_readdir(): inode: 0x%p, filp: 0x%p\n", inode, filp));
521 if (filp->f_pos == 0) {
522 D3(printk("jffs_readdir(): \".\" %lu\n", inode->i_ino));
523 if (filldir(dirent, ".", 1, filp->f_pos, inode->i_ino) < 0) {
524 return 0;
526 filp->f_pos = 1;
528 if (filp->f_pos == 1) {
529 if (inode->i_ino == JFFS_MIN_INO) {
530 ddino = JFFS_MIN_INO;
532 else {
533 ddino = ((struct jffs_file *)inode->u.generic_ip)->pino;
535 D3(printk("jffs_readdir(): \"..\" %u\n", ddino));
536 if (filldir(dirent, "..", 2, filp->f_pos, ddino) < 0)
537 return 0;
538 filp->f_pos++;
540 f = ((struct jffs_file *)inode->u.generic_ip)->children;
541 for (j = 2; (j < filp->f_pos) && f; j++) {
542 f = f->sibling_next;
544 for (; f ; f = f->sibling_next) {
545 D3(printk("jffs_readdir(): \"%s\" ino: %u\n",
546 (f->name ? f->name : ""), f->ino));
547 if (filldir(dirent, f->name, f->nsize,
548 filp->f_pos , f->ino) < 0)
549 return 0;
550 filp->f_pos++;
553 return filp->f_pos;
554 } /* jffs_readdir() */
557 /* Find a file in a directory. If the file exists, return its
558 corresponding dentry. */
559 static struct dentry *
560 jffs_lookup(struct inode *dir, struct dentry *dentry)
562 struct jffs_file *d;
563 struct jffs_file *f;
564 int len;
565 int r = 0;
566 const char *name;
567 struct inode *inode = NULL;
569 len = dentry->d_name.len;
570 name = dentry->d_name.name;
572 D3({
573 char *s = (char *)kmalloc(len + 1, GFP_KERNEL);
574 memcpy(s, name, len);
575 s[len] = '\0';
576 printk("jffs_lookup(): dir: 0x%p, name: \"%s\"\n", dir, s);
577 kfree(s);
580 r = -ENAMETOOLONG;
581 if (len > JFFS_MAX_NAME_LEN) {
582 goto jffs_lookup_end;
585 r = -EACCES;
586 if (!(d = (struct jffs_file *)dir->u.generic_ip)) {
587 D(printk("jffs_lookup(): No such inode! (%lu)\n", dir->i_ino));
588 goto jffs_lookup_end;
591 /* Get the corresponding inode to the file. */
592 if ((len == 1) && (name[0] == '.')) {
593 if (!(inode = iget(dir->i_sb, d->ino))) {
594 D(printk("jffs_lookup(): . iget() ==> NULL\n"));
595 goto jffs_lookup_end;
597 } else if ((len == 2) && (name[0] == '.') && (name[1] == '.')) {
598 if (!(inode = iget(dir->i_sb, d->pino))) {
599 D(printk("jffs_lookup(): .. iget() ==> NULL\n"));
600 goto jffs_lookup_end;
602 } else if ((f = jffs_find_child(d, name, len))) {
603 if (!(inode = iget(dir->i_sb, f->ino))) {
604 D(printk("jffs_lookup(): iget() ==> NULL\n"));
605 goto jffs_lookup_end;
607 } else {
608 D3(printk("jffs_lookup(): Couldn't find the file. "
609 "f = 0x%p, name = \"%s\", d = 0x%p, d->ino = %u\n",
610 f, name, d, d->ino));
611 inode = NULL;
614 d_add(dentry, inode);
615 return NULL;
617 jffs_lookup_end:
618 return ERR_PTR(r);
619 } /* jffs_lookup() */
622 /* Try to read a page of data from a file. */
623 static int
624 jffs_readpage(struct file *file, struct page *page)
626 void *buf;
627 unsigned long read_len;
628 int result = -EIO;
629 struct inode *inode = (struct inode*)page->mapping->host;
630 struct jffs_file *f = (struct jffs_file *)inode->u.generic_ip;
631 int r;
632 loff_t offset;
634 D2(printk("***jffs_readpage(): file = \"%s\", page->index = %lu\n",
635 (f->name ? f->name : ""), (long)page->index));
637 get_page(page);
638 /* Don't LockPage(page), should be locked already */
639 buf = page_address(page);
640 ClearPageUptodate(page);
641 ClearPageError(page);
643 offset = page->index << PAGE_CACHE_SHIFT;
644 if (offset < inode->i_size) {
645 read_len = jffs_min(inode->i_size - offset, PAGE_SIZE);
646 r = jffs_read_data(f, buf, offset, read_len);
647 if (r == read_len) {
648 if (read_len < PAGE_SIZE) {
649 memset(buf + read_len, 0,
650 PAGE_SIZE - read_len);
652 SetPageUptodate(page);
653 result = 0;
655 D(else {
656 printk("***jffs_readpage(): Read error! "
657 "Wanted to read %lu bytes but only "
658 "read %d bytes.\n", read_len, r);
661 if (result) {
662 memset(buf, 0, PAGE_SIZE);
663 SetPageError(page);
665 flush_dcache_page(page);
667 UnlockPage(page);
669 put_page(page);
671 D3(printk("jffs_readpage(): Leaving...\n"));
673 return result;
674 } /* jffs_readpage() */
677 /* Create a new directory. */
678 static int
679 jffs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
681 struct jffs_raw_inode raw_inode;
682 struct jffs_control *c;
683 struct jffs_node *node;
684 struct jffs_file *dir_f;
685 struct inode *inode;
686 int dir_mode;
687 int result = 0;
688 int err;
690 D1({
691 int len = dentry->d_name.len;
692 char *_name = (char *) kmalloc(len + 1, GFP_KERNEL);
693 memcpy(_name, dentry->d_name.name, len);
694 _name[len] = '\0';
695 printk("***jffs_mkdir(): dir = 0x%p, name = \"%s\", "
696 "len = %d, mode = 0x%08x\n", dir, _name, len, mode);
697 kfree(_name);
700 dir_f = (struct jffs_file *)dir->u.generic_ip;
701 ASSERT(if (!dir_f) {
702 printk(KERN_ERR "jffs_mkdir(): No reference to a "
703 "jffs_file struct in inode.\n");
704 result = -1;
705 goto jffs_mkdir_end;
708 c = dir_f->c;
710 if (!JFFS_ENOUGH_SPACE(c->fmc)) {
711 D1(printk("jffs_mkdir(): Free size = %u\n",
712 jffs_free_size1(c->fmc) + jffs_free_size2(c->fmc)));
713 D(printk(KERN_NOTICE "JFFS: No space left on device\n"));
714 result = -ENOSPC;
715 goto jffs_mkdir_end;
718 dir_mode = S_IFDIR | (mode & (S_IRWXUGO|S_ISVTX)
719 & ~current->fs->umask);
720 if (dir->i_mode & S_ISGID) {
721 dir_mode |= S_ISGID;
724 /* Create a node and initialize it as much as needed. */
725 if (!(node = (struct jffs_node *) kmalloc(sizeof(struct jffs_node),
726 GFP_KERNEL))) {
727 D(printk("jffs_mkdir(): Allocation failed: node == 0\n"));
728 result = -ENOMEM;
729 goto jffs_mkdir_end;
731 DJM(no_jffs_node++);
732 node->data_offset = 0;
733 node->removed_size = 0;
735 /* Initialize the raw inode. */
736 raw_inode.magic = JFFS_MAGIC_BITMASK;
737 raw_inode.ino = c->next_ino++;
738 raw_inode.pino = dir_f->ino;
739 raw_inode.version = 1;
740 raw_inode.mode = dir_mode;
741 raw_inode.uid = current->fsuid;
742 raw_inode.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
743 /* raw_inode.gid = current->fsgid; */
744 raw_inode.atime = CURRENT_TIME;
745 raw_inode.mtime = raw_inode.atime;
746 raw_inode.ctime = raw_inode.atime;
747 raw_inode.offset = 0;
748 raw_inode.dsize = 0;
749 raw_inode.rsize = 0;
750 raw_inode.nsize = dentry->d_name.len;
751 raw_inode.nlink = 1;
752 raw_inode.spare = 0;
753 raw_inode.rename = 0;
754 raw_inode.deleted = 0;
756 /* Write the new node to the flash. */
757 if ((result = jffs_write_node(c, node, &raw_inode, dentry->d_name.name, 0)) < 0) {
758 D(printk("jffs_mkdir(): jffs_write_node() failed.\n"));
759 kfree(node);
760 DJM(no_jffs_node--);
761 goto jffs_mkdir_end;
764 /* Insert the new node into the file system. */
765 if ((result = jffs_insert_node(c, 0, &raw_inode, dentry->d_name.name, node))<0)
766 goto jffs_mkdir_end;
768 inode = jffs_new_inode(dir, &raw_inode, &err);
769 if (inode == NULL) {
770 result = err;
771 goto jffs_mkdir_end;
774 inode->i_op = &jffs_dir_inode_operations;
775 inode->i_fop = &jffs_dir_operations;
777 mark_inode_dirty(dir);
778 d_instantiate(dentry, inode);
780 result = 0;
781 jffs_mkdir_end:
782 return result;
783 } /* jffs_mkdir() */
786 /* Remove a directory. */
787 static int
788 jffs_rmdir(struct inode *dir, struct dentry *dentry)
790 D3(printk("***jffs_rmdir()\n"));
791 return jffs_remove(dir, dentry, S_IFDIR);
795 /* Remove any kind of file except for directories. */
796 static int
797 jffs_unlink(struct inode *dir, struct dentry *dentry)
799 D3(printk("***jffs_unlink()\n"));
800 return jffs_remove(dir, dentry, 0);
804 /* Remove a JFFS entry, i.e. plain files, directories, etc. Here we
805 shouldn't test for free space on the device. */
806 static int
807 jffs_remove(struct inode *dir, struct dentry *dentry, int type)
809 struct jffs_raw_inode raw_inode;
810 struct jffs_control *c;
811 struct jffs_file *dir_f; /* The file-to-remove's parent. */
812 struct jffs_file *del_f; /* The file to remove. */
813 struct jffs_node *del_node;
814 struct inode *inode = 0;
815 int result = 0;
817 D1({
818 int len = dentry->d_name.len;
819 const char *name = dentry->d_name.name;
820 char *_name = (char *) kmalloc(len + 1, GFP_KERNEL);
821 memcpy(_name, name, len);
822 _name[len] = '\0';
823 printk("***jffs_remove(): file = \"%s\"\n", _name);
824 kfree(_name);
827 dir_f = (struct jffs_file *) dir->u.generic_ip;
828 c = dir_f->c;
830 result = -ENOENT;
831 if (!(del_f = jffs_find_child(dir_f, dentry->d_name.name,
832 dentry->d_name.len))) {
833 D(printk("jffs_remove(): jffs_find_child() failed.\n"));
834 goto jffs_remove_end;
837 if (S_ISDIR(type)) {
838 if (del_f->children) {
839 result = -ENOTEMPTY;
840 goto jffs_remove_end;
842 } else if (S_ISDIR(del_f->mode)) {
843 D(printk("jffs_remove(): node is a directory "
844 "but it shouldn't be.\n"));
845 result = -EPERM;
846 goto jffs_remove_end;
849 inode = dentry->d_inode;
851 result = -EIO;
852 if (del_f->ino != inode->i_ino)
853 goto jffs_remove_end;
855 if (!inode->i_nlink) {
856 printk("Deleting nonexistent file inode: %lu, nlink: %d\n",
857 inode->i_ino, inode->i_nlink);
858 inode->i_nlink=1;
861 /* Create a node for the deletion. */
862 result = -ENOMEM;
863 if (!(del_node = (struct jffs_node *)
864 kmalloc(sizeof(struct jffs_node), GFP_KERNEL))) {
865 D(printk("jffs_remove(): Allocation failed!\n"));
866 goto jffs_remove_end;
868 DJM(no_jffs_node++);
869 del_node->data_offset = 0;
870 del_node->removed_size = 0;
872 /* Initialize the raw inode. */
873 raw_inode.magic = JFFS_MAGIC_BITMASK;
874 raw_inode.ino = del_f->ino;
875 raw_inode.pino = del_f->pino;
876 raw_inode.version = del_f->highest_version + 1;
877 raw_inode.mode = del_f->mode;
878 raw_inode.uid = current->fsuid;
879 raw_inode.gid = current->fsgid;
880 raw_inode.atime = CURRENT_TIME;
881 raw_inode.mtime = del_f->mtime;
882 raw_inode.ctime = raw_inode.atime;
883 raw_inode.offset = 0;
884 raw_inode.dsize = 0;
885 raw_inode.rsize = 0;
886 raw_inode.nsize = 0;
887 raw_inode.nlink = del_f->nlink;
888 raw_inode.spare = 0;
889 raw_inode.rename = 0;
890 raw_inode.deleted = 1;
892 /* Write the new node to the flash memory. */
893 if (jffs_write_node(c, del_node, &raw_inode, 0, 0) < 0) {
894 kfree(del_node);
895 DJM(no_jffs_node--);
896 result = -EIO;
897 goto jffs_remove_end;
900 /* Update the file. This operation will make the file disappear
901 from the in-memory file system structures. */
902 jffs_insert_node(c, del_f, &raw_inode, 0, del_node);
904 dir->i_version = ++event;
905 dir->i_ctime = dir->i_mtime = CURRENT_TIME;
906 mark_inode_dirty(dir);
907 inode->i_nlink--;
908 if (inode->i_nlink == 0) {
909 inode->u.generic_ip = 0;
911 inode->i_ctime = dir->i_ctime;
912 mark_inode_dirty(inode);
914 d_delete(dentry); /* This also frees the inode */
916 result = 0;
917 jffs_remove_end:
918 return result;
919 } /* jffs_remove() */
922 static int
923 jffs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rdev)
925 struct jffs_raw_inode raw_inode;
926 struct jffs_file *dir_f;
927 struct jffs_node *node = 0;
928 struct jffs_control *c;
929 struct inode *inode;
930 int result = 0;
931 kdev_t dev = to_kdev_t(rdev);
932 int err;
934 D1(printk("***jffs_mknod()\n"));
936 dir_f = (struct jffs_file *)dir->u.generic_ip;
937 c = dir_f->c;
939 if (!JFFS_ENOUGH_SPACE(c->fmc)) {
940 D1(printk("jffs_mknod(): Free size = %u\n",
941 jffs_free_size1(c->fmc) + jffs_free_size2(c->fmc)));
942 D(printk(KERN_NOTICE "JFFS: No space left on device\n"));
943 result = -ENOSPC;
944 goto jffs_mknod_end;
947 /* Create and initialize a new node. */
948 if (!(node = (struct jffs_node *) kmalloc(sizeof(struct jffs_node),
949 GFP_KERNEL))) {
950 D(printk("jffs_mknod(): Allocation failed!\n"));
951 result = -ENOMEM;
952 goto jffs_mknod_err;
954 DJM(no_jffs_node++);
955 node->data_offset = 0;
956 node->removed_size = 0;
958 /* Initialize the raw inode. */
959 raw_inode.magic = JFFS_MAGIC_BITMASK;
960 raw_inode.ino = c->next_ino++;
961 raw_inode.pino = dir_f->ino;
962 raw_inode.version = 1;
963 raw_inode.mode = mode;
964 raw_inode.uid = current->fsuid;
965 raw_inode.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
966 /* raw_inode.gid = current->fsgid; */
967 raw_inode.atime = CURRENT_TIME;
968 raw_inode.mtime = raw_inode.atime;
969 raw_inode.ctime = raw_inode.atime;
970 raw_inode.offset = 0;
971 raw_inode.dsize = sizeof(kdev_t);
972 raw_inode.rsize = 0;
973 raw_inode.nsize = dentry->d_name.len;
974 raw_inode.nlink = 1;
975 raw_inode.spare = 0;
976 raw_inode.rename = 0;
977 raw_inode.deleted = 0;
979 /* Write the new node to the flash. */
980 if ((err = jffs_write_node(c, node, &raw_inode, dentry->d_name.name,
981 (unsigned char *)&dev)) < 0) {
982 D(printk("jffs_mknod(): jffs_write_node() failed.\n"));
983 result = err;
984 goto jffs_mknod_err;
987 /* Insert the new node into the file system. */
988 if ((err = jffs_insert_node(c, 0, &raw_inode, dentry->d_name.name, node)) < 0) {
989 result = err;
990 goto jffs_mknod_end;
993 inode = jffs_new_inode(dir, &raw_inode, &err);
994 if (inode == NULL) {
995 result = err;
996 goto jffs_mknod_end;
999 init_special_inode(inode, mode, rdev);
1001 d_instantiate(dentry, inode);
1003 goto jffs_mknod_end;
1005 jffs_mknod_err:
1006 if (node) {
1007 kfree(node);
1008 DJM(no_jffs_node--);
1011 jffs_mknod_end:
1012 return result;
1013 } /* jffs_mknod() */
1016 static int
1017 jffs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
1019 struct jffs_raw_inode raw_inode;
1020 struct jffs_control *c;
1021 struct jffs_file *dir_f;
1022 struct jffs_node *node;
1023 struct inode *inode;
1025 int symname_len = strlen(symname);
1026 int err;
1028 D1({
1029 int len = dentry->d_name.len;
1030 char *_name = (char *)kmalloc(len + 1, GFP_KERNEL);
1031 char *_symname = (char *)kmalloc(symname_len + 1, GFP_KERNEL);
1032 memcpy(_name, dentry->d_name.name, len);
1033 _name[len] = '\0';
1034 memcpy(_symname, symname, symname_len);
1035 _symname[symname_len] = '\0';
1036 printk("***jffs_symlink(): dir = 0x%p, dentry->dname.name = \"%s\", "
1037 "symname = \"%s\"\n", dir, _name, _symname);
1038 kfree(_name);
1039 kfree(_symname);
1042 dir_f = (struct jffs_file *)dir->u.generic_ip;
1043 ASSERT(if (!dir_f) {
1044 printk(KERN_ERR "jffs_symlink(): No reference to a "
1045 "jffs_file struct in inode.\n");
1046 return -1;
1049 c = dir_f->c;
1051 if (!JFFS_ENOUGH_SPACE(c->fmc)) {
1052 D1(printk("jffs_symlink(): Free size = %u\n",
1053 jffs_free_size1(c->fmc) + jffs_free_size2(c->fmc)));
1054 D(printk(KERN_NOTICE "JFFS: No space left on device\n"));
1055 return -ENOSPC;
1058 /* Create a node and initialize it as much as needed. */
1059 if (!(node = (struct jffs_node *) kmalloc(sizeof(struct jffs_node),
1060 GFP_KERNEL))) {
1061 D(printk("jffs_symlink(): Allocation failed: node == NULL\n"));
1062 return -ENOMEM;
1064 DJM(no_jffs_node++);
1065 node->data_offset = 0;
1066 node->removed_size = 0;
1068 /* Initialize the raw inode. */
1069 raw_inode.magic = JFFS_MAGIC_BITMASK;
1070 raw_inode.ino = c->next_ino++;
1071 raw_inode.pino = dir_f->ino;
1072 raw_inode.version = 1;
1073 raw_inode.mode = S_IFLNK | S_IRWXUGO;
1074 raw_inode.uid = current->fsuid;
1075 raw_inode.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
1076 raw_inode.atime = CURRENT_TIME;
1077 raw_inode.mtime = raw_inode.atime;
1078 raw_inode.ctime = raw_inode.atime;
1079 raw_inode.offset = 0;
1080 raw_inode.dsize = symname_len;
1081 raw_inode.rsize = 0;
1082 raw_inode.nsize = dentry->d_name.len;
1083 raw_inode.nlink = 1;
1084 raw_inode.spare = 0;
1085 raw_inode.rename = 0;
1086 raw_inode.deleted = 0;
1088 /* Write the new node to the flash. */
1089 if ((err = jffs_write_node(c, node, &raw_inode, dentry->d_name.name,
1090 (const unsigned char *)symname)) < 0) {
1091 D(printk("jffs_symlink(): jffs_write_node() failed.\n"));
1092 kfree(node);
1093 DJM(no_jffs_node--);
1094 return err;
1097 /* Insert the new node into the file system. */
1098 if ((err = jffs_insert_node(c, 0, &raw_inode, dentry->d_name.name, node)) < 0) {
1099 return err;
1102 inode = jffs_new_inode(dir, &raw_inode, &err);
1103 if (inode == NULL) {
1104 return err;
1107 inode->i_op = &page_symlink_inode_operations;
1108 inode->i_mapping->a_ops = &jffs_address_operations;
1110 d_instantiate(dentry, inode);
1112 return 0;
1113 } /* jffs_symlink() */
1115 /* Create an inode inside a JFFS directory (dir) and return it.
1117 * By the time this is called, we already have created
1118 * the directory cache entry for the new file, but it
1119 * is so far negative - it has no inode.
1121 * If the create succeeds, we fill in the inode information
1122 * with d_instantiate().
1124 static int
1125 jffs_create(struct inode *dir, struct dentry *dentry, int mode)
1127 struct jffs_raw_inode raw_inode;
1128 struct jffs_control *c;
1129 struct jffs_node *node;
1130 struct jffs_file *dir_f; /* JFFS representation of the directory. */
1131 struct inode *inode;
1132 int err;
1134 D1({
1135 int len = dentry->d_name.len;
1136 char *s = (char *)kmalloc(len + 1, GFP_KERNEL);
1137 memcpy(s, dentry->d_name.name, len);
1138 s[len] = '\0';
1139 printk("jffs_create(): dir: 0x%p, name: \"%s\"\n", dir, s);
1140 kfree(s);
1143 dir_f = (struct jffs_file *)dir->u.generic_ip;
1144 ASSERT(if (!dir_f) {
1145 printk(KERN_ERR "jffs_create(): No reference to a "
1146 "jffs_file struct in inode.\n");
1147 return -1;
1150 c = dir_f->c;
1152 if (!JFFS_ENOUGH_SPACE(c->fmc)) {
1153 D1(printk("jffs_create(): Free size = %u\n",
1154 jffs_free_size1(c->fmc) + jffs_free_size2(c->fmc)));
1155 D(printk(KERN_NOTICE "JFFS: No space left on device\n"));
1156 return -ENOSPC;
1159 /* Create a node and initialize as much as needed. */
1160 if (!(node = (struct jffs_node *) kmalloc(sizeof(struct jffs_node),
1161 GFP_KERNEL))) {
1162 D(printk("jffs_create(): Allocation failed: node == 0\n"));
1163 return -ENOMEM;
1165 DJM(no_jffs_node++);
1166 node->data_offset = 0;
1167 node->removed_size = 0;
1169 /* Initialize the raw inode. */
1170 raw_inode.magic = JFFS_MAGIC_BITMASK;
1171 raw_inode.ino = c->next_ino++;
1172 raw_inode.pino = dir_f->ino;
1173 raw_inode.version = 1;
1174 raw_inode.mode = mode;
1175 raw_inode.uid = current->fsuid;
1176 raw_inode.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
1177 raw_inode.atime = CURRENT_TIME;
1178 raw_inode.mtime = raw_inode.atime;
1179 raw_inode.ctime = raw_inode.atime;
1180 raw_inode.offset = 0;
1181 raw_inode.dsize = 0;
1182 raw_inode.rsize = 0;
1183 raw_inode.nsize = dentry->d_name.len;
1184 raw_inode.nlink = 1;
1185 raw_inode.spare = 0;
1186 raw_inode.rename = 0;
1187 raw_inode.deleted = 0;
1189 /* Write the new node to the flash. */
1190 if ((err = jffs_write_node(c, node, &raw_inode, dentry->d_name.name, 0)) < 0) {
1191 D(printk("jffs_create(): jffs_write_node() failed.\n"));
1192 kfree(node);
1193 DJM(no_jffs_node--);
1194 return err;
1197 /* Insert the new node into the file system. */
1198 if ((err = jffs_insert_node(c, 0, &raw_inode, dentry->d_name.name, node)) < 0) {
1199 return err;
1202 /* Initialize an inode. */
1203 inode = jffs_new_inode(dir, &raw_inode, &err);
1204 if (inode == NULL) {
1205 return err;
1208 inode->i_op = &jffs_file_inode_operations;
1209 inode->i_fop = &jffs_file_operations;
1210 inode->i_mapping->a_ops = &jffs_address_operations;
1211 inode->i_mapping->nrpages = 0;
1213 d_instantiate(dentry, inode);
1215 return 0;
1216 } /* jffs_create() */
1219 /* Write, append or rewrite data to an existing file. */
1220 static ssize_t
1221 jffs_file_write(struct file *filp, const char *buf, size_t count, loff_t *ppos)
1223 struct jffs_raw_inode raw_inode;
1224 struct jffs_control *c;
1225 struct jffs_file *f;
1226 struct jffs_node *node;
1227 struct dentry *dentry = filp->f_dentry;
1228 struct inode *inode = dentry->d_inode;
1229 int written = 0;
1230 loff_t pos;
1231 int err;
1233 inode = filp->f_dentry->d_inode;
1235 D2(printk("***jffs_file_write(): inode: 0x%p (ino: %lu), "
1236 "filp: 0x%p, buf: 0x%p, count: %d\n",
1237 inode, inode->i_ino, filp, buf, count));
1239 down(&inode->i_sem);
1241 pos = *ppos;
1242 err = -EINVAL;
1243 if (pos < 0)
1244 goto out;
1246 err = filp->f_error;
1247 if (err) {
1248 filp->f_error = 0;
1249 goto out;
1252 if (inode->i_sb->s_flags & MS_RDONLY) {
1253 D(printk("jffs_file_write(): MS_RDONLY\n"));
1254 err = -ENOSPC;
1255 goto out;
1258 if (!S_ISREG(inode->i_mode)) {
1259 D(printk("jffs_file_write(): inode->i_mode == 0x%08x\n",
1260 inode->i_mode));
1261 err = -EINVAL;
1262 goto out;
1265 if (!(f = (struct jffs_file *)inode->u.generic_ip)) {
1266 D(printk("jffs_file_write(): inode->u.generic_ip = 0x%p\n",
1267 inode->u.generic_ip));
1268 err = -EINVAL;
1269 goto out;
1272 c = f->c;
1274 if (!JFFS_ENOUGH_SPACE(c->fmc)) {
1275 D1(printk("jffs_file_write(): Free size = %u\n",
1276 jffs_free_size1(c->fmc) + jffs_free_size2(c->fmc)));
1277 D(printk(KERN_NOTICE "JFFS: No space left on device\n"));
1278 err = -ENOSPC;
1279 goto out;
1282 if (filp->f_flags & O_APPEND)
1283 pos = inode->i_size;
1285 /* Things are going to be written so we could allocate and
1286 initialize the necessary data structures now. */
1287 if (!(node = (struct jffs_node *) kmalloc(sizeof(struct jffs_node),
1288 GFP_KERNEL))) {
1289 D(printk("jffs_file_write(): node == 0\n"));
1290 err = -ENOMEM;
1291 goto out;
1293 DJM(no_jffs_node++);
1294 node->data_offset = f->size;
1295 node->removed_size = 0;
1297 /* Initialize the raw inode. */
1298 raw_inode.magic = JFFS_MAGIC_BITMASK;
1299 raw_inode.ino = f->ino;
1300 raw_inode.pino = f->pino;
1301 raw_inode.version = f->highest_version + 1;
1302 raw_inode.mode = f->mode;
1304 raw_inode.uid = f->uid;
1305 raw_inode.gid = f->gid;
1307 raw_inode.uid = current->fsuid;
1308 raw_inode.gid = current->fsgid;
1310 raw_inode.atime = CURRENT_TIME;
1311 raw_inode.mtime = raw_inode.atime;
1312 raw_inode.ctime = f->ctime;
1313 raw_inode.offset = f->size;
1314 raw_inode.dsize = count;
1315 raw_inode.rsize = 0;
1316 raw_inode.nsize = 0;
1317 raw_inode.nlink = f->nlink;
1318 raw_inode.spare = 0;
1319 raw_inode.rename = 0;
1320 raw_inode.deleted = 0;
1323 /* TODO: BAAAAAAAAD! buf is a userspace-pointer, and should be
1324 treated as such, with copy_from_user etc...
1326 /* Write the new node to the flash. */
1327 if ((written = jffs_write_node(c, node, &raw_inode, 0,
1328 (const unsigned char *)buf)) < 0) {
1329 D(printk("jffs_file_write(): jffs_write_node() failed.\n"));
1330 kfree(node);
1331 DJM(no_jffs_node--);
1332 err = written;
1333 goto out;
1336 /* Insert the new node into the file system. */
1337 if ((err = jffs_insert_node(c, f, &raw_inode, 0, node)) < 0) {
1338 goto out;
1341 pos += written;
1342 *ppos = pos;
1344 D3(printk("jffs_file_write(): new f_pos %ld.\n", (long)pos));
1346 /* Fix things in the real inode. */
1347 if (pos > inode->i_size) {
1348 inode->i_size = pos;
1350 inode->i_ctime = inode->i_mtime = CURRENT_TIME;
1351 mark_inode_dirty(inode);
1352 invalidate_inode_pages(inode);
1354 err = written;
1355 out:
1356 up(&inode->i_sem);
1357 return err;
1358 } /* jffs_file_write() */
1361 /* This is our ioctl() routine. */
1362 static int
1363 jffs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
1364 unsigned long arg)
1366 struct jffs_control *c;
1368 D2(printk("***jffs_ioctl(): cmd = 0x%08x, arg = 0x%08lx\n", cmd, arg));
1370 if (!(c = (struct jffs_control *)inode->i_sb->u.generic_sbp)) {
1371 printk(KERN_ERR "JFFS: Bad inode in ioctl() call. "
1372 "(cmd = 0x%08x)\n", cmd);
1373 return -EIO;
1376 switch (cmd) {
1377 case JFFS_PRINT_HASH:
1378 jffs_print_hash_table(c);
1379 break;
1380 case JFFS_PRINT_TREE:
1381 jffs_print_tree(c->root, 0);
1382 break;
1383 case JFFS_GET_STATUS:
1385 struct jffs_flash_status fst;
1386 struct jffs_fmcontrol *fmc = c->fmc;
1387 printk("Flash status -- ");
1388 if (!access_ok(VERIFY_WRITE,
1389 (struct jffs_flash_status *)arg,
1390 sizeof(struct jffs_flash_status))) {
1391 D(printk("jffs_ioctl(): Bad arg in "
1392 "JFFS_GET_STATUS ioctl!\n"));
1393 return -EFAULT;
1395 fst.size = fmc->flash_size;
1396 fst.used = fmc->used_size;
1397 fst.dirty = fmc->dirty_size;
1398 fst.begin = fmc->head->offset;
1399 fst.end = fmc->tail->offset + fmc->tail->size;
1400 printk("size: %d, used: %d, dirty: %d, "
1401 "begin: %d, end: %d\n",
1402 fst.size, fst.used, fst.dirty,
1403 fst.begin, fst.end);
1404 if (copy_to_user((struct jffs_flash_status *)arg,
1405 &fst, sizeof(struct jffs_flash_status))) {
1406 return -EFAULT;
1410 break;
1411 default:
1412 return -ENOTTY;
1415 return 0;
1416 } /* jffs_ioctl() */
1419 static struct address_space_operations jffs_address_operations = {
1420 readpage: jffs_readpage,
1424 static struct file_operations jffs_file_operations =
1426 read: generic_file_read, /* read */
1427 write: jffs_file_write, /* write */
1428 ioctl: jffs_ioctl, /* ioctl */
1429 mmap: generic_file_mmap, /* mmap */
1432 static struct inode_operations jffs_file_inode_operations =
1434 lookup: jffs_lookup, /* lookup */
1435 setattr: jffs_setattr,
1438 static struct file_operations jffs_dir_operations =
1440 readdir: jffs_readdir,
1443 static struct inode_operations jffs_dir_inode_operations =
1445 create: jffs_create,
1446 lookup: jffs_lookup,
1447 unlink: jffs_unlink,
1448 symlink: jffs_symlink,
1449 mkdir: jffs_mkdir,
1450 rmdir: jffs_rmdir,
1451 mknod: jffs_mknod,
1452 rename: jffs_rename,
1453 setattr: jffs_setattr,
1456 /* Initialize an inode for the VFS. */
1457 static void
1458 jffs_read_inode(struct inode *inode)
1460 struct jffs_file *f;
1461 struct jffs_control *c;
1463 D3(printk("jffs_read_inode(): inode->i_ino == %lu\n", inode->i_ino));
1465 if (!inode->i_sb) {
1466 D(printk("jffs_read_inode(): !inode->i_sb ==> "
1467 "No super block!\n"));
1468 return;
1470 c = (struct jffs_control *)inode->i_sb->u.generic_sbp;
1471 if (!(f = jffs_find_file(c, inode->i_ino))) {
1472 D(printk("jffs_read_inode(): No such inode (%lu).\n",
1473 inode->i_ino));
1474 return;
1476 inode->u.generic_ip = (void *)f;
1477 inode->i_mode = f->mode;
1478 inode->i_nlink = f->nlink;
1479 inode->i_uid = f->uid;
1480 inode->i_gid = f->gid;
1481 inode->i_size = f->size;
1482 inode->i_atime = f->atime;
1483 inode->i_mtime = f->mtime;
1484 inode->i_ctime = f->ctime;
1485 inode->i_blksize = PAGE_SIZE;
1486 inode->i_blocks = 0;
1487 if (S_ISREG(inode->i_mode)) {
1488 inode->i_op = &jffs_file_inode_operations;
1489 inode->i_fop = &jffs_file_operations;
1490 inode->i_mapping->a_ops = &jffs_address_operations;
1492 else if (S_ISDIR(inode->i_mode)) {
1493 inode->i_op = &jffs_dir_inode_operations;
1494 inode->i_fop = &jffs_dir_operations;
1496 else if (S_ISLNK(inode->i_mode)) {
1497 inode->i_op = &page_symlink_inode_operations;
1498 inode->i_mapping->a_ops = &jffs_address_operations;
1499 } else {
1500 /* If the node is a device of some sort, then the number of the
1501 device should be read from the flash memory and then added
1502 to the inode's i_rdev member. */
1503 kdev_t rdev;
1504 jffs_read_data(f, (char *)&rdev, 0, sizeof(kdev_t));
1505 init_special_inode(inode, inode->i_mode, kdev_t_to_nr(rdev));
1509 void
1510 jffs_delete_inode(struct inode *inode)
1513 D3(printk("jffs_delete_inode(): inode->i_ino == %lu\n", inode->i_ino));
1515 lock_kernel();
1517 inode->i_size = 0;
1519 clear_inode(inode);
1521 unlock_kernel();
1524 void
1525 jffs_write_super(struct super_block *sb)
1527 #ifdef USE_GC
1528 struct jffs_control *c = (struct jffs_control *)sb->u.generic_sbp;
1530 if(!c->fmc->no_call_gc)
1531 jffs_garbage_collect(c);
1532 #endif
1535 static struct super_operations jffs_ops =
1537 read_inode: jffs_read_inode,
1538 delete_inode: jffs_delete_inode,
1539 put_super: jffs_put_super,
1540 write_super: jffs_write_super,
1541 statfs: jffs_statfs,
1544 static DECLARE_FSTYPE_DEV(jffs_fs_type, "jffs", jffs_read_super);
1546 static int __init
1547 init_jffs_fs(void)
1549 printk("JFFS version " JFFS_VERSION_STRING ", (C) 1999, 2000 Axis Communications AB\n");
1550 return register_filesystem(&jffs_fs_type);
1553 static void __exit
1554 exit_jffs_fs(void)
1556 unregister_filesystem(&jffs_fs_type);
1559 EXPORT_NO_SYMBOLS;
1561 module_init(init_jffs_fs)
1562 module_exit(exit_jffs_fs)