blob: 068ef0de8de2b63400da3a81be3e423cfc8d93ce [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;
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -080058static const struct file_operations jffs_file_operations;
Linus Torvalds1da177e2005-04-16 15:20:36 -070059static struct inode_operations jffs_file_inode_operations;
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -080060static const struct file_operations jffs_dir_operations;
Linus Torvalds1da177e2005-04-16 15:20:36 -070061static struct inode_operations jffs_dir_inode_operations;
Christoph Hellwigf5e54d62006-06-28 04:26:44 -070062static const struct address_space_operations jffs_address_operations;
Linus Torvalds1da177e2005-04-16 15:20:36 -070063
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;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367 inode->i_blocks = (inode->i_size + 511) >> 9;
368
369 f = jffs_find_file(c, raw_inode->ino);
370
Theodore Ts'o8e18e292006-09-27 01:50:46 -0700371 inode->i_private = (void *)f;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372 insert_inode_hash(inode);
373
374 return inode;
375}
376
377/* Get statistics of the file system. */
378static int
David Howells726c3342006-06-23 02:02:58 -0700379jffs_statfs(struct dentry *dentry, struct kstatfs *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380{
David Howells726c3342006-06-23 02:02:58 -0700381 struct jffs_control *c = (struct jffs_control *) dentry->d_sb->s_fs_info;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382 struct jffs_fmcontrol *fmc;
383
384 lock_kernel();
385
386 fmc = c->fmc;
387
388 D2(printk("jffs_statfs()\n"));
389
390 buf->f_type = JFFS_MAGIC_SB_BITMASK;
391 buf->f_bsize = PAGE_CACHE_SIZE;
392 buf->f_blocks = (fmc->flash_size / PAGE_CACHE_SIZE)
393 - (fmc->min_free_size / PAGE_CACHE_SIZE);
394 buf->f_bfree = (jffs_free_size1(fmc) + jffs_free_size2(fmc) +
395 fmc->dirty_size - fmc->min_free_size)
396 >> PAGE_CACHE_SHIFT;
397 buf->f_bavail = buf->f_bfree;
398
399 /* Find out how many files there are in the filesystem. */
400 buf->f_files = jffs_foreach_file(c, jffs_file_count);
401 buf->f_ffree = buf->f_bfree;
402 /* buf->f_fsid = 0; */
403 buf->f_namelen = JFFS_MAX_NAME_LEN;
404
405 unlock_kernel();
406
407 return 0;
408}
409
410
411/* Rename a file. */
412static int
413jffs_rename(struct inode *old_dir, struct dentry *old_dentry,
414 struct inode *new_dir, struct dentry *new_dentry)
415{
416 struct jffs_raw_inode raw_inode;
417 struct jffs_control *c;
418 struct jffs_file *old_dir_f;
419 struct jffs_file *new_dir_f;
420 struct jffs_file *del_f;
421 struct jffs_file *f;
422 struct jffs_node *node;
423 struct inode *inode;
424 int result = 0;
425 __u32 rename_data = 0;
426
427 D2(printk("***jffs_rename()\n"));
428
429 D(printk("jffs_rename(): old_dir: 0x%p, old name: 0x%p, "
430 "new_dir: 0x%p, new name: 0x%p\n",
431 old_dir, old_dentry->d_name.name,
432 new_dir, new_dentry->d_name.name));
433
434 lock_kernel();
435 c = (struct jffs_control *)old_dir->i_sb->s_fs_info;
436 ASSERT(if (!c) {
437 printk(KERN_ERR "jffs_rename(): The old_dir inode "
438 "didn't have a reference to a jffs_file struct\n");
439 unlock_kernel();
440 return -EIO;
441 });
442
443 result = -ENOTDIR;
Theodore Ts'o8e18e292006-09-27 01:50:46 -0700444 if (!(old_dir_f = old_dir->i_private)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445 D(printk("jffs_rename(): Old dir invalid.\n"));
446 goto jffs_rename_end;
447 }
448
449 /* Try to find the file to move. */
450 result = -ENOENT;
451 if (!(f = jffs_find_child(old_dir_f, old_dentry->d_name.name,
452 old_dentry->d_name.len))) {
453 goto jffs_rename_end;
454 }
455
456 /* Find the new directory. */
457 result = -ENOTDIR;
Theodore Ts'o8e18e292006-09-27 01:50:46 -0700458 if (!(new_dir_f = new_dir->i_private)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459 D(printk("jffs_rename(): New dir invalid.\n"));
460 goto jffs_rename_end;
461 }
462 D3(printk (KERN_NOTICE "rename(): down biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800463 mutex_lock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464 /* Create a node and initialize as much as needed. */
465 result = -ENOMEM;
466 if (!(node = jffs_alloc_node())) {
467 D(printk("jffs_rename(): Allocation failed: node == 0\n"));
468 goto jffs_rename_end;
469 }
470 node->data_offset = 0;
471 node->removed_size = 0;
472
473 /* Initialize the raw inode. */
474 raw_inode.magic = JFFS_MAGIC_BITMASK;
475 raw_inode.ino = f->ino;
476 raw_inode.pino = new_dir_f->ino;
477/* raw_inode.version = f->highest_version + 1; */
478 raw_inode.mode = f->mode;
479 raw_inode.uid = current->fsuid;
480 raw_inode.gid = current->fsgid;
481#if 0
482 raw_inode.uid = f->uid;
483 raw_inode.gid = f->gid;
484#endif
485 raw_inode.atime = get_seconds();
486 raw_inode.mtime = raw_inode.atime;
487 raw_inode.ctime = f->ctime;
488 raw_inode.offset = 0;
489 raw_inode.dsize = 0;
490 raw_inode.rsize = 0;
491 raw_inode.nsize = new_dentry->d_name.len;
492 raw_inode.nlink = f->nlink;
493 raw_inode.spare = 0;
494 raw_inode.rename = 0;
495 raw_inode.deleted = 0;
496
497 /* See if there already exists a file with the same name as
498 new_name. */
499 if ((del_f = jffs_find_child(new_dir_f, new_dentry->d_name.name,
500 new_dentry->d_name.len))) {
501 raw_inode.rename = 1;
502 raw_inode.dsize = sizeof(__u32);
503 rename_data = del_f->ino;
504 }
505
506 /* Write the new node to the flash memory. */
507 if ((result = jffs_write_node(c, node, &raw_inode,
508 new_dentry->d_name.name,
509 (unsigned char*)&rename_data, 0, f)) < 0) {
510 D(printk("jffs_rename(): Failed to write node to flash.\n"));
511 jffs_free_node(node);
512 goto jffs_rename_end;
513 }
514 raw_inode.dsize = 0;
515
516 if (raw_inode.rename) {
517 /* The file with the same name must be deleted. */
518 //FIXME deadlock down(&c->fmc->gclock);
519 if ((result = jffs_remove(new_dir, new_dentry,
520 del_f->mode)) < 0) {
521 /* This is really bad. */
522 printk(KERN_ERR "JFFS: An error occurred in "
523 "rename().\n");
524 }
525 // up(&c->fmc->gclock);
526 }
527
528 if (old_dir_f != new_dir_f) {
529 /* Remove the file from its old position in the
530 filesystem tree. */
531 jffs_unlink_file_from_tree(f);
532 }
533
534 /* Insert the new node into the file system. */
535 if ((result = jffs_insert_node(c, f, &raw_inode,
536 new_dentry->d_name.name, node)) < 0) {
537 D(printk(KERN_ERR "jffs_rename(): jffs_insert_node() "
538 "failed!\n"));
539 }
540
541 if (old_dir_f != new_dir_f) {
542 /* Insert the file to its new position in the
543 file system. */
544 jffs_insert_file_into_tree(f);
545 }
546
547 /* This is a kind of update of the inode we're about to make
548 here. This is what they do in ext2fs. Kind of. */
549 if ((inode = iget(new_dir->i_sb, f->ino))) {
550 inode->i_ctime = CURRENT_TIME_SEC;
551 mark_inode_dirty(inode);
552 iput(inode);
553 }
554
555jffs_rename_end:
556 D3(printk (KERN_NOTICE "rename(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800557 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 unlock_kernel();
559 return result;
560} /* jffs_rename() */
561
562
563/* Read the contents of a directory. Used by programs like `ls'
564 for instance. */
565static int
566jffs_readdir(struct file *filp, void *dirent, filldir_t filldir)
567{
568 struct jffs_file *f;
569 struct dentry *dentry = filp->f_dentry;
570 struct inode *inode = dentry->d_inode;
571 struct jffs_control *c = (struct jffs_control *)inode->i_sb->s_fs_info;
572 int j;
573 int ddino;
574 lock_kernel();
575 D3(printk (KERN_NOTICE "readdir(): down biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800576 mutex_lock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577
578 D2(printk("jffs_readdir(): inode: 0x%p, filp: 0x%p\n", inode, filp));
579 if (filp->f_pos == 0) {
580 D3(printk("jffs_readdir(): \".\" %lu\n", inode->i_ino));
581 if (filldir(dirent, ".", 1, filp->f_pos, inode->i_ino, DT_DIR) < 0) {
582 D3(printk (KERN_NOTICE "readdir(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800583 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584 unlock_kernel();
585 return 0;
586 }
587 filp->f_pos = 1;
588 }
589 if (filp->f_pos == 1) {
590 if (inode->i_ino == JFFS_MIN_INO) {
591 ddino = JFFS_MIN_INO;
592 }
593 else {
594 ddino = ((struct jffs_file *)
Theodore Ts'o8e18e292006-09-27 01:50:46 -0700595 inode->i_private)->pino;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596 }
597 D3(printk("jffs_readdir(): \"..\" %u\n", ddino));
598 if (filldir(dirent, "..", 2, filp->f_pos, ddino, DT_DIR) < 0) {
599 D3(printk (KERN_NOTICE "readdir(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800600 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601 unlock_kernel();
602 return 0;
603 }
604 filp->f_pos++;
605 }
Theodore Ts'o8e18e292006-09-27 01:50:46 -0700606 f = ((struct jffs_file *)inode->i_private)->children;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607
608 j = 2;
609 while(f && (f->deleted || j++ < filp->f_pos )) {
610 f = f->sibling_next;
611 }
612
613 while (f) {
614 D3(printk("jffs_readdir(): \"%s\" ino: %u\n",
615 (f->name ? f->name : ""), f->ino));
616 if (filldir(dirent, f->name, f->nsize,
617 filp->f_pos , f->ino, DT_UNKNOWN) < 0) {
618 D3(printk (KERN_NOTICE "readdir(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800619 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620 unlock_kernel();
621 return 0;
622 }
623 filp->f_pos++;
624 do {
625 f = f->sibling_next;
626 } while(f && f->deleted);
627 }
628 D3(printk (KERN_NOTICE "readdir(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800629 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630 unlock_kernel();
631 return filp->f_pos;
632} /* jffs_readdir() */
633
634
635/* Find a file in a directory. If the file exists, return its
636 corresponding dentry. */
637static struct dentry *
638jffs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
639{
640 struct jffs_file *d;
641 struct jffs_file *f;
642 struct jffs_control *c = (struct jffs_control *)dir->i_sb->s_fs_info;
643 int len;
644 int r = 0;
645 const char *name;
646 struct inode *inode = NULL;
647
648 len = dentry->d_name.len;
649 name = dentry->d_name.name;
650
651 lock_kernel();
652
653 D3({
Panagiotis Issarisf52720c2006-09-27 01:49:39 -0700654 char *s = kmalloc(len + 1, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655 memcpy(s, name, len);
656 s[len] = '\0';
657 printk("jffs_lookup(): dir: 0x%p, name: \"%s\"\n", dir, s);
658 kfree(s);
659 });
660
661 D3(printk (KERN_NOTICE "lookup(): down biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800662 mutex_lock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663
664 r = -ENAMETOOLONG;
665 if (len > JFFS_MAX_NAME_LEN) {
666 goto jffs_lookup_end;
667 }
668
669 r = -EACCES;
Theodore Ts'o8e18e292006-09-27 01:50:46 -0700670 if (!(d = (struct jffs_file *)dir->i_private)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671 D(printk("jffs_lookup(): No such inode! (%lu)\n",
672 dir->i_ino));
673 goto jffs_lookup_end;
674 }
675
676 /* Get the corresponding inode to the file. */
677
678 /* iget calls jffs_read_inode, so we need to drop the biglock
679 before calling iget. Unfortunately, the GC has a tendency
680 to sneak in here, because iget sometimes calls schedule ().
681 */
682
683 if ((len == 1) && (name[0] == '.')) {
684 D3(printk (KERN_NOTICE "lookup(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800685 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686 if (!(inode = iget(dir->i_sb, d->ino))) {
687 D(printk("jffs_lookup(): . iget() ==> NULL\n"));
688 goto jffs_lookup_end_no_biglock;
689 }
690 D3(printk (KERN_NOTICE "lookup(): down biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800691 mutex_lock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692 } else if ((len == 2) && (name[0] == '.') && (name[1] == '.')) {
693 D3(printk (KERN_NOTICE "lookup(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800694 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695 if (!(inode = iget(dir->i_sb, d->pino))) {
696 D(printk("jffs_lookup(): .. iget() ==> NULL\n"));
697 goto jffs_lookup_end_no_biglock;
698 }
699 D3(printk (KERN_NOTICE "lookup(): down biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800700 mutex_lock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701 } else if ((f = jffs_find_child(d, name, len))) {
702 D3(printk (KERN_NOTICE "lookup(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800703 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704 if (!(inode = iget(dir->i_sb, f->ino))) {
705 D(printk("jffs_lookup(): iget() ==> NULL\n"));
706 goto jffs_lookup_end_no_biglock;
707 }
708 D3(printk (KERN_NOTICE "lookup(): down biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800709 mutex_lock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710 } else {
711 D3(printk("jffs_lookup(): Couldn't find the file. "
712 "f = 0x%p, name = \"%s\", d = 0x%p, d->ino = %u\n",
713 f, name, d, d->ino));
714 inode = NULL;
715 }
716
717 d_add(dentry, inode);
718 D3(printk (KERN_NOTICE "lookup(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800719 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720 unlock_kernel();
721 return NULL;
722
723jffs_lookup_end:
724 D3(printk (KERN_NOTICE "lookup(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800725 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726
727jffs_lookup_end_no_biglock:
728 unlock_kernel();
729 return ERR_PTR(r);
730} /* jffs_lookup() */
731
732
733/* Try to read a page of data from a file. */
734static int
735jffs_do_readpage_nolock(struct file *file, struct page *page)
736{
737 void *buf;
738 unsigned long read_len;
739 int result;
740 struct inode *inode = (struct inode*)page->mapping->host;
Theodore Ts'o8e18e292006-09-27 01:50:46 -0700741 struct jffs_file *f = (struct jffs_file *)inode->i_private;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742 struct jffs_control *c = (struct jffs_control *)inode->i_sb->s_fs_info;
743 int r;
744 loff_t offset;
745
746 D2(printk("***jffs_readpage(): file = \"%s\", page->index = %lu\n",
747 (f->name ? f->name : ""), (long)page->index));
748
749 get_page(page);
750 /* Don't SetPageLocked(page), should be locked already */
751 ClearPageUptodate(page);
752 ClearPageError(page);
753
754 D3(printk (KERN_NOTICE "readpage(): down biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800755 mutex_lock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756
757 read_len = 0;
758 result = 0;
Andrew Morton54b21a72006-01-08 01:03:05 -0800759 offset = page_offset(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760
761 kmap(page);
762 buf = page_address(page);
763 if (offset < inode->i_size) {
764 read_len = min_t(long, inode->i_size - offset, PAGE_SIZE);
765 r = jffs_read_data(f, buf, offset, read_len);
766 if (r != read_len) {
767 result = -EIO;
768 D(
769 printk("***jffs_readpage(): Read error! "
770 "Wanted to read %lu bytes but only "
771 "read %d bytes.\n", read_len, r);
772 );
773 }
774
775 }
776
777 /* This handles the case of partial or no read in above */
778 if(read_len < PAGE_SIZE)
779 memset(buf + read_len, 0, PAGE_SIZE - read_len);
780 flush_dcache_page(page);
781 kunmap(page);
782
783 D3(printk (KERN_NOTICE "readpage(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800784 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785
786 if (result) {
787 SetPageError(page);
788 }else {
789 SetPageUptodate(page);
790 }
791
792 page_cache_release(page);
793
794 D3(printk("jffs_readpage(): Leaving...\n"));
795
796 return result;
797} /* jffs_do_readpage_nolock() */
798
799static int jffs_readpage(struct file *file, struct page *page)
800{
801 int ret = jffs_do_readpage_nolock(file, page);
802 unlock_page(page);
803 return ret;
804}
805
806/* Create a new directory. */
807static int
808jffs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
809{
810 struct jffs_raw_inode raw_inode;
811 struct jffs_control *c;
812 struct jffs_node *node;
813 struct jffs_file *dir_f;
814 struct inode *inode;
815 int dir_mode;
816 int result = 0;
817 int err;
818
819 D1({
820 int len = dentry->d_name.len;
821 char *_name = (char *) kmalloc(len + 1, GFP_KERNEL);
822 memcpy(_name, dentry->d_name.name, len);
823 _name[len] = '\0';
824 printk("***jffs_mkdir(): dir = 0x%p, name = \"%s\", "
825 "len = %d, mode = 0x%08x\n", dir, _name, len, mode);
826 kfree(_name);
827 });
828
829 lock_kernel();
Theodore Ts'o8e18e292006-09-27 01:50:46 -0700830 dir_f = dir->i_private;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831
832 ASSERT(if (!dir_f) {
833 printk(KERN_ERR "jffs_mkdir(): No reference to a "
834 "jffs_file struct in inode.\n");
835 unlock_kernel();
836 return -EIO;
837 });
838
839 c = dir_f->c;
840 D3(printk (KERN_NOTICE "mkdir(): down biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800841 mutex_lock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842
843 dir_mode = S_IFDIR | (mode & (S_IRWXUGO|S_ISVTX)
844 & ~current->fs->umask);
845 if (dir->i_mode & S_ISGID) {
846 dir_mode |= S_ISGID;
847 }
848
849 /* Create a node and initialize it as much as needed. */
850 if (!(node = jffs_alloc_node())) {
851 D(printk("jffs_mkdir(): Allocation failed: node == 0\n"));
852 result = -ENOMEM;
853 goto jffs_mkdir_end;
854 }
855 node->data_offset = 0;
856 node->removed_size = 0;
857
858 /* Initialize the raw inode. */
859 raw_inode.magic = JFFS_MAGIC_BITMASK;
860 raw_inode.ino = c->next_ino++;
861 raw_inode.pino = dir_f->ino;
862 raw_inode.version = 1;
863 raw_inode.mode = dir_mode;
864 raw_inode.uid = current->fsuid;
865 raw_inode.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
866 /* raw_inode.gid = current->fsgid; */
867 raw_inode.atime = get_seconds();
868 raw_inode.mtime = raw_inode.atime;
869 raw_inode.ctime = raw_inode.atime;
870 raw_inode.offset = 0;
871 raw_inode.dsize = 0;
872 raw_inode.rsize = 0;
873 raw_inode.nsize = dentry->d_name.len;
874 raw_inode.nlink = 1;
875 raw_inode.spare = 0;
876 raw_inode.rename = 0;
877 raw_inode.deleted = 0;
878
879 /* Write the new node to the flash. */
880 if ((result = jffs_write_node(c, node, &raw_inode,
881 dentry->d_name.name, NULL, 0, NULL)) < 0) {
882 D(printk("jffs_mkdir(): jffs_write_node() failed.\n"));
883 jffs_free_node(node);
884 goto jffs_mkdir_end;
885 }
886
887 /* Insert the new node into the file system. */
888 if ((result = jffs_insert_node(c, NULL, &raw_inode, dentry->d_name.name,
889 node)) < 0) {
890 goto jffs_mkdir_end;
891 }
892
893 inode = jffs_new_inode(dir, &raw_inode, &err);
894 if (inode == NULL) {
895 result = err;
896 goto jffs_mkdir_end;
897 }
898
899 inode->i_op = &jffs_dir_inode_operations;
900 inode->i_fop = &jffs_dir_operations;
901
902 mark_inode_dirty(dir);
903 d_instantiate(dentry, inode);
904
905 result = 0;
906jffs_mkdir_end:
907 D3(printk (KERN_NOTICE "mkdir(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800908 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909 unlock_kernel();
910 return result;
911} /* jffs_mkdir() */
912
913
914/* Remove a directory. */
915static int
916jffs_rmdir(struct inode *dir, struct dentry *dentry)
917{
918 struct jffs_control *c = (struct jffs_control *)dir->i_sb->s_fs_info;
919 int ret;
920 D3(printk("***jffs_rmdir()\n"));
921 D3(printk (KERN_NOTICE "rmdir(): down biglock\n"));
922 lock_kernel();
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800923 mutex_lock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924 ret = jffs_remove(dir, dentry, S_IFDIR);
925 D3(printk (KERN_NOTICE "rmdir(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800926 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927 unlock_kernel();
928 return ret;
929}
930
931
932/* Remove any kind of file except for directories. */
933static int
934jffs_unlink(struct inode *dir, struct dentry *dentry)
935{
936 struct jffs_control *c = (struct jffs_control *)dir->i_sb->s_fs_info;
937 int ret;
938
939 lock_kernel();
940 D3(printk("***jffs_unlink()\n"));
941 D3(printk (KERN_NOTICE "unlink(): down biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800942 mutex_lock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943 ret = jffs_remove(dir, dentry, 0);
944 D3(printk (KERN_NOTICE "unlink(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -0800945 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946 unlock_kernel();
947 return ret;
948}
949
950
951/* Remove a JFFS entry, i.e. plain files, directories, etc. Here we
952 shouldn't test for free space on the device. */
953static int
954jffs_remove(struct inode *dir, struct dentry *dentry, int type)
955{
956 struct jffs_raw_inode raw_inode;
957 struct jffs_control *c;
958 struct jffs_file *dir_f; /* The file-to-remove's parent. */
959 struct jffs_file *del_f; /* The file to remove. */
960 struct jffs_node *del_node;
961 struct inode *inode = NULL;
962 int result = 0;
963
964 D1({
965 int len = dentry->d_name.len;
966 const char *name = dentry->d_name.name;
967 char *_name = (char *) kmalloc(len + 1, GFP_KERNEL);
968 memcpy(_name, name, len);
969 _name[len] = '\0';
970 printk("***jffs_remove(): file = \"%s\", ino = %ld\n", _name, dentry->d_inode->i_ino);
971 kfree(_name);
972 });
973
Theodore Ts'o8e18e292006-09-27 01:50:46 -0700974 dir_f = dir->i_private;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975 c = dir_f->c;
976
977 result = -ENOENT;
978 if (!(del_f = jffs_find_child(dir_f, dentry->d_name.name,
979 dentry->d_name.len))) {
980 D(printk("jffs_remove(): jffs_find_child() failed.\n"));
981 goto jffs_remove_end;
982 }
983
984 if (S_ISDIR(type)) {
985 struct jffs_file *child = del_f->children;
986 while(child) {
987 if( !child->deleted ) {
988 result = -ENOTEMPTY;
989 goto jffs_remove_end;
990 }
991 child = child->sibling_next;
992 }
993 }
994 else if (S_ISDIR(del_f->mode)) {
995 D(printk("jffs_remove(): node is a directory "
996 "but it shouldn't be.\n"));
997 result = -EPERM;
998 goto jffs_remove_end;
999 }
1000
1001 inode = dentry->d_inode;
1002
1003 result = -EIO;
1004 if (del_f->ino != inode->i_ino)
1005 goto jffs_remove_end;
1006
1007 if (!inode->i_nlink) {
1008 printk("Deleting nonexistent file inode: %lu, nlink: %d\n",
1009 inode->i_ino, inode->i_nlink);
1010 inode->i_nlink=1;
1011 }
1012
1013 /* Create a node for the deletion. */
1014 result = -ENOMEM;
1015 if (!(del_node = jffs_alloc_node())) {
1016 D(printk("jffs_remove(): Allocation failed!\n"));
1017 goto jffs_remove_end;
1018 }
1019 del_node->data_offset = 0;
1020 del_node->removed_size = 0;
1021
1022 /* Initialize the raw inode. */
1023 raw_inode.magic = JFFS_MAGIC_BITMASK;
1024 raw_inode.ino = del_f->ino;
1025 raw_inode.pino = del_f->pino;
1026/* raw_inode.version = del_f->highest_version + 1; */
1027 raw_inode.mode = del_f->mode;
1028 raw_inode.uid = current->fsuid;
1029 raw_inode.gid = current->fsgid;
1030 raw_inode.atime = get_seconds();
1031 raw_inode.mtime = del_f->mtime;
1032 raw_inode.ctime = raw_inode.atime;
1033 raw_inode.offset = 0;
1034 raw_inode.dsize = 0;
1035 raw_inode.rsize = 0;
1036 raw_inode.nsize = 0;
1037 raw_inode.nlink = del_f->nlink;
1038 raw_inode.spare = 0;
1039 raw_inode.rename = 0;
1040 raw_inode.deleted = 1;
1041
1042 /* Write the new node to the flash memory. */
1043 if (jffs_write_node(c, del_node, &raw_inode, NULL, NULL, 1, del_f) < 0) {
1044 jffs_free_node(del_node);
1045 result = -EIO;
1046 goto jffs_remove_end;
1047 }
1048
1049 /* Update the file. This operation will make the file disappear
1050 from the in-memory file system structures. */
1051 jffs_insert_node(c, del_f, &raw_inode, NULL, del_node);
1052
1053 dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
1054 mark_inode_dirty(dir);
1055 inode->i_nlink--;
1056 inode->i_ctime = dir->i_ctime;
1057 mark_inode_dirty(inode);
1058
1059 d_delete(dentry); /* This also frees the inode */
1060
1061 result = 0;
1062jffs_remove_end:
1063 return result;
1064} /* jffs_remove() */
1065
1066
1067static int
1068jffs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
1069{
1070 struct jffs_raw_inode raw_inode;
1071 struct jffs_file *dir_f;
1072 struct jffs_node *node = NULL;
1073 struct jffs_control *c;
1074 struct inode *inode;
1075 int result = 0;
1076 u16 data = old_encode_dev(rdev);
1077 int err;
1078
1079 D1(printk("***jffs_mknod()\n"));
1080
1081 if (!old_valid_dev(rdev))
1082 return -EINVAL;
1083 lock_kernel();
Theodore Ts'o8e18e292006-09-27 01:50:46 -07001084 dir_f = dir->i_private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085 c = dir_f->c;
1086
1087 D3(printk (KERN_NOTICE "mknod(): down biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -08001088 mutex_lock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089
1090 /* Create and initialize a new node. */
1091 if (!(node = jffs_alloc_node())) {
1092 D(printk("jffs_mknod(): Allocation failed!\n"));
1093 result = -ENOMEM;
1094 goto jffs_mknod_err;
1095 }
1096 node->data_offset = 0;
1097 node->removed_size = 0;
1098
1099 /* Initialize the raw inode. */
1100 raw_inode.magic = JFFS_MAGIC_BITMASK;
1101 raw_inode.ino = c->next_ino++;
1102 raw_inode.pino = dir_f->ino;
1103 raw_inode.version = 1;
1104 raw_inode.mode = mode;
1105 raw_inode.uid = current->fsuid;
1106 raw_inode.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
1107 /* raw_inode.gid = current->fsgid; */
1108 raw_inode.atime = get_seconds();
1109 raw_inode.mtime = raw_inode.atime;
1110 raw_inode.ctime = raw_inode.atime;
1111 raw_inode.offset = 0;
1112 raw_inode.dsize = 2;
1113 raw_inode.rsize = 0;
1114 raw_inode.nsize = dentry->d_name.len;
1115 raw_inode.nlink = 1;
1116 raw_inode.spare = 0;
1117 raw_inode.rename = 0;
1118 raw_inode.deleted = 0;
1119
1120 /* Write the new node to the flash. */
1121 if ((err = jffs_write_node(c, node, &raw_inode, dentry->d_name.name,
1122 (unsigned char *)&data, 0, NULL)) < 0) {
1123 D(printk("jffs_mknod(): jffs_write_node() failed.\n"));
1124 result = err;
1125 goto jffs_mknod_err;
1126 }
1127
1128 /* Insert the new node into the file system. */
1129 if ((err = jffs_insert_node(c, NULL, &raw_inode, dentry->d_name.name,
1130 node)) < 0) {
1131 result = err;
1132 goto jffs_mknod_end;
1133 }
1134
1135 inode = jffs_new_inode(dir, &raw_inode, &err);
1136 if (inode == NULL) {
1137 result = err;
1138 goto jffs_mknod_end;
1139 }
1140
1141 init_special_inode(inode, mode, rdev);
1142
1143 d_instantiate(dentry, inode);
1144
1145 goto jffs_mknod_end;
1146
1147jffs_mknod_err:
1148 if (node) {
1149 jffs_free_node(node);
1150 }
1151
1152jffs_mknod_end:
1153 D3(printk (KERN_NOTICE "mknod(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -08001154 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155 unlock_kernel();
1156 return result;
1157} /* jffs_mknod() */
1158
1159
1160static int
1161jffs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
1162{
1163 struct jffs_raw_inode raw_inode;
1164 struct jffs_control *c;
1165 struct jffs_file *dir_f;
1166 struct jffs_node *node;
1167 struct inode *inode;
1168
1169 int symname_len = strlen(symname);
1170 int err;
1171
1172 lock_kernel();
1173 D1({
1174 int len = dentry->d_name.len;
Panagiotis Issarisf52720c2006-09-27 01:49:39 -07001175 char *_name = kmalloc(len + 1, GFP_KERNEL);
1176 char *_symname = kmalloc(symname_len + 1, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177 memcpy(_name, dentry->d_name.name, len);
1178 _name[len] = '\0';
1179 memcpy(_symname, symname, symname_len);
1180 _symname[symname_len] = '\0';
1181 printk("***jffs_symlink(): dir = 0x%p, "
1182 "dentry->dname.name = \"%s\", "
1183 "symname = \"%s\"\n", dir, _name, _symname);
1184 kfree(_name);
1185 kfree(_symname);
1186 });
1187
Theodore Ts'o8e18e292006-09-27 01:50:46 -07001188 dir_f = dir->i_private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189 ASSERT(if (!dir_f) {
1190 printk(KERN_ERR "jffs_symlink(): No reference to a "
1191 "jffs_file struct in inode.\n");
1192 unlock_kernel();
1193 return -EIO;
1194 });
1195
1196 c = dir_f->c;
1197
1198 /* Create a node and initialize it as much as needed. */
1199 if (!(node = jffs_alloc_node())) {
1200 D(printk("jffs_symlink(): Allocation failed: node = NULL\n"));
1201 unlock_kernel();
1202 return -ENOMEM;
1203 }
1204 D3(printk (KERN_NOTICE "symlink(): down biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -08001205 mutex_lock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206
1207 node->data_offset = 0;
1208 node->removed_size = 0;
1209
1210 /* Initialize the raw inode. */
1211 raw_inode.magic = JFFS_MAGIC_BITMASK;
1212 raw_inode.ino = c->next_ino++;
1213 raw_inode.pino = dir_f->ino;
1214 raw_inode.version = 1;
1215 raw_inode.mode = S_IFLNK | S_IRWXUGO;
1216 raw_inode.uid = current->fsuid;
1217 raw_inode.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
1218 raw_inode.atime = get_seconds();
1219 raw_inode.mtime = raw_inode.atime;
1220 raw_inode.ctime = raw_inode.atime;
1221 raw_inode.offset = 0;
1222 raw_inode.dsize = symname_len;
1223 raw_inode.rsize = 0;
1224 raw_inode.nsize = dentry->d_name.len;
1225 raw_inode.nlink = 1;
1226 raw_inode.spare = 0;
1227 raw_inode.rename = 0;
1228 raw_inode.deleted = 0;
1229
1230 /* Write the new node to the flash. */
1231 if ((err = jffs_write_node(c, node, &raw_inode, dentry->d_name.name,
1232 (const unsigned char *)symname, 0, NULL)) < 0) {
1233 D(printk("jffs_symlink(): jffs_write_node() failed.\n"));
1234 jffs_free_node(node);
1235 goto jffs_symlink_end;
1236 }
1237
1238 /* Insert the new node into the file system. */
1239 if ((err = jffs_insert_node(c, NULL, &raw_inode, dentry->d_name.name,
1240 node)) < 0) {
1241 goto jffs_symlink_end;
1242 }
1243
1244 inode = jffs_new_inode(dir, &raw_inode, &err);
1245 if (inode == NULL) {
1246 goto jffs_symlink_end;
1247 }
1248 err = 0;
1249 inode->i_op = &page_symlink_inode_operations;
1250 inode->i_mapping->a_ops = &jffs_address_operations;
1251
1252 d_instantiate(dentry, inode);
1253 jffs_symlink_end:
1254 D3(printk (KERN_NOTICE "symlink(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -08001255 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256 unlock_kernel();
1257 return err;
1258} /* jffs_symlink() */
1259
1260
1261/* Create an inode inside a JFFS directory (dir) and return it.
1262 *
1263 * By the time this is called, we already have created
1264 * the directory cache entry for the new file, but it
1265 * is so far negative - it has no inode.
1266 *
1267 * If the create succeeds, we fill in the inode information
1268 * with d_instantiate().
1269 */
1270static int
1271jffs_create(struct inode *dir, struct dentry *dentry, int mode,
1272 struct nameidata *nd)
1273{
1274 struct jffs_raw_inode raw_inode;
1275 struct jffs_control *c;
1276 struct jffs_node *node;
1277 struct jffs_file *dir_f; /* JFFS representation of the directory. */
1278 struct inode *inode;
1279 int err;
1280
1281 lock_kernel();
1282 D1({
1283 int len = dentry->d_name.len;
Panagiotis Issarisf52720c2006-09-27 01:49:39 -07001284 char *s = kmalloc(len + 1, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285 memcpy(s, dentry->d_name.name, len);
1286 s[len] = '\0';
1287 printk("jffs_create(): dir: 0x%p, name: \"%s\"\n", dir, s);
1288 kfree(s);
1289 });
1290
Theodore Ts'o8e18e292006-09-27 01:50:46 -07001291 dir_f = dir->i_private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292 ASSERT(if (!dir_f) {
1293 printk(KERN_ERR "jffs_create(): No reference to a "
1294 "jffs_file struct in inode.\n");
1295 unlock_kernel();
1296 return -EIO;
1297 });
1298
1299 c = dir_f->c;
1300
1301 /* Create a node and initialize as much as needed. */
1302 if (!(node = jffs_alloc_node())) {
1303 D(printk("jffs_create(): Allocation failed: node == 0\n"));
1304 unlock_kernel();
1305 return -ENOMEM;
1306 }
1307 D3(printk (KERN_NOTICE "create(): down biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -08001308 mutex_lock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309
1310 node->data_offset = 0;
1311 node->removed_size = 0;
1312
1313 /* Initialize the raw inode. */
1314 raw_inode.magic = JFFS_MAGIC_BITMASK;
1315 raw_inode.ino = c->next_ino++;
1316 raw_inode.pino = dir_f->ino;
1317 raw_inode.version = 1;
1318 raw_inode.mode = mode;
1319 raw_inode.uid = current->fsuid;
1320 raw_inode.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
1321 raw_inode.atime = get_seconds();
1322 raw_inode.mtime = raw_inode.atime;
1323 raw_inode.ctime = raw_inode.atime;
1324 raw_inode.offset = 0;
1325 raw_inode.dsize = 0;
1326 raw_inode.rsize = 0;
1327 raw_inode.nsize = dentry->d_name.len;
1328 raw_inode.nlink = 1;
1329 raw_inode.spare = 0;
1330 raw_inode.rename = 0;
1331 raw_inode.deleted = 0;
1332
1333 /* Write the new node to the flash. */
1334 if ((err = jffs_write_node(c, node, &raw_inode,
1335 dentry->d_name.name, NULL, 0, NULL)) < 0) {
1336 D(printk("jffs_create(): jffs_write_node() failed.\n"));
1337 jffs_free_node(node);
1338 goto jffs_create_end;
1339 }
1340
1341 /* Insert the new node into the file system. */
1342 if ((err = jffs_insert_node(c, NULL, &raw_inode, dentry->d_name.name,
1343 node)) < 0) {
1344 goto jffs_create_end;
1345 }
1346
1347 /* Initialize an inode. */
1348 inode = jffs_new_inode(dir, &raw_inode, &err);
1349 if (inode == NULL) {
1350 goto jffs_create_end;
1351 }
1352 err = 0;
1353 inode->i_op = &jffs_file_inode_operations;
1354 inode->i_fop = &jffs_file_operations;
1355 inode->i_mapping->a_ops = &jffs_address_operations;
1356 inode->i_mapping->nrpages = 0;
1357
1358 d_instantiate(dentry, inode);
1359 jffs_create_end:
1360 D3(printk (KERN_NOTICE "create(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -08001361 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362 unlock_kernel();
1363 return err;
1364} /* jffs_create() */
1365
1366
1367/* Write, append or rewrite data to an existing file. */
1368static ssize_t
1369jffs_file_write(struct file *filp, const char *buf, size_t count,
1370 loff_t *ppos)
1371{
1372 struct jffs_raw_inode raw_inode;
1373 struct jffs_control *c;
1374 struct jffs_file *f;
1375 struct jffs_node *node;
1376 struct dentry *dentry = filp->f_dentry;
1377 struct inode *inode = dentry->d_inode;
1378 int recoverable = 0;
1379 size_t written = 0;
1380 __u32 thiscount = count;
1381 loff_t pos = *ppos;
1382 int err;
1383
1384 inode = filp->f_dentry->d_inode;
1385
1386 D2(printk("***jffs_file_write(): inode: 0x%p (ino: %lu), "
1387 "filp: 0x%p, buf: 0x%p, count: %d\n",
1388 inode, inode->i_ino, filp, buf, count));
1389
1390#if 0
1391 if (inode->i_sb->s_flags & MS_RDONLY) {
1392 D(printk("jffs_file_write(): MS_RDONLY\n"));
1393 err = -EROFS;
1394 goto out_isem;
1395 }
1396#endif
1397 err = -EINVAL;
1398
1399 if (!S_ISREG(inode->i_mode)) {
1400 D(printk("jffs_file_write(): inode->i_mode == 0x%08x\n",
1401 inode->i_mode));
1402 goto out_isem;
1403 }
1404
Theodore Ts'o8e18e292006-09-27 01:50:46 -07001405 if (!(f = inode->i_private)) {
1406 D(printk("jffs_file_write(): inode->i_private = 0x%p\n",
1407 inode->i_private));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408 goto out_isem;
1409 }
1410
1411 c = f->c;
1412
1413 /*
1414 * This will never trigger with sane page sizes. leave it in
1415 * anyway, since I'm thinking about how to merge larger writes
1416 * (the current idea is to poke a thread that does the actual
Jes Sorensen1b1dcc12006-01-09 15:59:24 -08001417 * I/O and starts by doing a mutex_lock(&inode->i_mutex). then we
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418 * would need to get the page cache pages and have a list of
1419 * I/O requests and do write-merging here.
1420 * -- prumpf
1421 */
1422 thiscount = min(c->fmc->max_chunk_size - sizeof(struct jffs_raw_inode), count);
1423
1424 D3(printk (KERN_NOTICE "file_write(): down biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -08001425 mutex_lock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426
1427 /* Urgh. POSIX says we can do short writes if we feel like it.
1428 * In practice, we can't. Nothing will cope. So we loop until
1429 * we're done.
1430 *
1431 * <_Anarchy_> posix and reality are not interconnected on this issue
1432 */
1433 while (count) {
1434 /* Things are going to be written so we could allocate and
1435 initialize the necessary data structures now. */
1436 if (!(node = jffs_alloc_node())) {
1437 D(printk("jffs_file_write(): node == 0\n"));
1438 err = -ENOMEM;
1439 goto out;
1440 }
1441
1442 node->data_offset = pos;
1443 node->removed_size = 0;
1444
1445 /* Initialize the raw inode. */
1446 raw_inode.magic = JFFS_MAGIC_BITMASK;
1447 raw_inode.ino = f->ino;
1448 raw_inode.pino = f->pino;
1449
1450 raw_inode.mode = f->mode;
1451
1452 raw_inode.uid = f->uid;
1453 raw_inode.gid = f->gid;
1454 raw_inode.atime = get_seconds();
1455 raw_inode.mtime = raw_inode.atime;
1456 raw_inode.ctime = f->ctime;
1457 raw_inode.offset = pos;
1458 raw_inode.dsize = thiscount;
1459 raw_inode.rsize = 0;
1460 raw_inode.nsize = f->nsize;
1461 raw_inode.nlink = f->nlink;
1462 raw_inode.spare = 0;
1463 raw_inode.rename = 0;
1464 raw_inode.deleted = 0;
1465
1466 if (pos < f->size) {
1467 node->removed_size = raw_inode.rsize = min(thiscount, (__u32)(f->size - pos));
1468
1469 /* If this node is going entirely over the top of old data,
1470 we can allow it to go into the reserved space, because
1471 we know that GC can reclaim the space later.
1472 */
1473 if (pos + thiscount < f->size) {
1474 /* If all the data we're overwriting are _real_,
1475 not just holes, then:
1476 recoverable = 1;
1477 */
1478 }
1479 }
1480
1481 /* Write the new node to the flash. */
1482 /* NOTE: We would be quite happy if jffs_write_node() wrote a
1483 smaller node than we were expecting. There's no need for it
1484 to waste the space at the end of the flash just because it's
1485 a little smaller than what we asked for. But that's a whole
1486 new can of worms which I'm not going to open this week.
1487 -- dwmw2.
1488 */
1489 if ((err = jffs_write_node(c, node, &raw_inode, f->name,
1490 (const unsigned char *)buf,
1491 recoverable, f)) < 0) {
1492 D(printk("jffs_file_write(): jffs_write_node() failed.\n"));
1493 jffs_free_node(node);
1494 goto out;
1495 }
1496
1497 written += err;
1498 buf += err;
1499 count -= err;
1500 pos += err;
1501
1502 /* Insert the new node into the file system. */
1503 if ((err = jffs_insert_node(c, f, &raw_inode, NULL, node)) < 0) {
1504 goto out;
1505 }
1506
1507 D3(printk("jffs_file_write(): new f_pos %ld.\n", (long)pos));
1508
1509 thiscount = min(c->fmc->max_chunk_size - sizeof(struct jffs_raw_inode), count);
1510 }
1511 out:
1512 D3(printk (KERN_NOTICE "file_write(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -08001513 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001514
1515 /* Fix things in the real inode. */
1516 if (pos > inode->i_size) {
1517 inode->i_size = pos;
1518 inode->i_blocks = (inode->i_size + 511) >> 9;
1519 }
1520 inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
1521 mark_inode_dirty(inode);
1522 invalidate_inode_pages(inode->i_mapping);
1523
1524 out_isem:
1525 return err;
1526} /* jffs_file_write() */
1527
1528static int
1529jffs_prepare_write(struct file *filp, struct page *page,
1530 unsigned from, unsigned to)
1531{
1532 /* FIXME: we should detect some error conditions here */
1533
1534 /* Bugger that. We should make sure the page is uptodate */
1535 if (!PageUptodate(page) && (from || to < PAGE_CACHE_SIZE))
1536 return jffs_do_readpage_nolock(filp, page);
1537
1538 return 0;
1539} /* jffs_prepare_write() */
1540
1541static int
1542jffs_commit_write(struct file *filp, struct page *page,
1543 unsigned from, unsigned to)
1544{
1545 void *addr = page_address(page) + from;
1546 /* XXX: PAGE_CACHE_SHIFT or PAGE_SHIFT */
Andrew Morton54b21a72006-01-08 01:03:05 -08001547 loff_t pos = page_offset(page) + from;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548
1549 return jffs_file_write(filp, addr, to-from, &pos);
1550} /* jffs_commit_write() */
1551
1552/* This is our ioctl() routine. */
1553static int
1554jffs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
1555 unsigned long arg)
1556{
1557 struct jffs_control *c;
1558 int ret = 0;
1559
1560 D2(printk("***jffs_ioctl(): cmd = 0x%08x, arg = 0x%08lx\n",
1561 cmd, arg));
1562
1563 if (!(c = (struct jffs_control *)inode->i_sb->s_fs_info)) {
1564 printk(KERN_ERR "JFFS: Bad inode in ioctl() call. "
1565 "(cmd = 0x%08x)\n", cmd);
1566 return -EIO;
1567 }
1568 D3(printk (KERN_NOTICE "ioctl(): down biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -08001569 mutex_lock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001570
1571 switch (cmd) {
1572 case JFFS_PRINT_HASH:
1573 jffs_print_hash_table(c);
1574 break;
1575 case JFFS_PRINT_TREE:
1576 jffs_print_tree(c->root, 0);
1577 break;
1578 case JFFS_GET_STATUS:
1579 {
1580 struct jffs_flash_status fst;
1581 struct jffs_fmcontrol *fmc = c->fmc;
1582 printk("Flash status -- ");
1583 if (!access_ok(VERIFY_WRITE,
1584 (struct jffs_flash_status __user *)arg,
1585 sizeof(struct jffs_flash_status))) {
1586 D(printk("jffs_ioctl(): Bad arg in "
1587 "JFFS_GET_STATUS ioctl!\n"));
1588 ret = -EFAULT;
1589 break;
1590 }
1591 fst.size = fmc->flash_size;
1592 fst.used = fmc->used_size;
1593 fst.dirty = fmc->dirty_size;
1594 fst.begin = fmc->head->offset;
1595 fst.end = fmc->tail->offset + fmc->tail->size;
1596 printk("size: %d, used: %d, dirty: %d, "
1597 "begin: %d, end: %d\n",
1598 fst.size, fst.used, fst.dirty,
1599 fst.begin, fst.end);
1600 if (copy_to_user((struct jffs_flash_status __user *)arg,
1601 &fst,
1602 sizeof(struct jffs_flash_status))) {
1603 ret = -EFAULT;
1604 }
1605 }
1606 break;
1607 default:
1608 ret = -ENOTTY;
1609 }
1610 D3(printk (KERN_NOTICE "ioctl(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -08001611 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612 return ret;
1613} /* jffs_ioctl() */
1614
1615
Christoph Hellwigf5e54d62006-06-28 04:26:44 -07001616static const struct address_space_operations jffs_address_operations = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617 .readpage = jffs_readpage,
1618 .prepare_write = jffs_prepare_write,
1619 .commit_write = jffs_commit_write,
1620};
1621
1622static int jffs_fsync(struct file *f, struct dentry *d, int datasync)
1623{
1624 /* We currently have O_SYNC operations at all times.
1625 Do nothing.
1626 */
1627 return 0;
1628}
1629
1630
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -08001631static const struct file_operations jffs_file_operations =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632{
1633 .open = generic_file_open,
1634 .llseek = generic_file_llseek,
Badari Pulavarty543ade12006-09-30 23:28:48 -07001635 .read = do_sync_read,
1636 .aio_read = generic_file_aio_read,
1637 .write = do_sync_write,
1638 .aio_write = generic_file_aio_write,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001639 .ioctl = jffs_ioctl,
1640 .mmap = generic_file_readonly_mmap,
1641 .fsync = jffs_fsync,
1642 .sendfile = generic_file_sendfile,
1643};
1644
1645
1646static struct inode_operations jffs_file_inode_operations =
1647{
1648 .lookup = jffs_lookup, /* lookup */
1649 .setattr = jffs_setattr,
1650};
1651
1652
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -08001653static const struct file_operations jffs_dir_operations =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654{
1655 .readdir = jffs_readdir,
1656};
1657
1658
1659static struct inode_operations jffs_dir_inode_operations =
1660{
1661 .create = jffs_create,
1662 .lookup = jffs_lookup,
1663 .unlink = jffs_unlink,
1664 .symlink = jffs_symlink,
1665 .mkdir = jffs_mkdir,
1666 .rmdir = jffs_rmdir,
1667 .mknod = jffs_mknod,
1668 .rename = jffs_rename,
1669 .setattr = jffs_setattr,
1670};
1671
1672
1673/* Initialize an inode for the VFS. */
1674static void
1675jffs_read_inode(struct inode *inode)
1676{
1677 struct jffs_file *f;
1678 struct jffs_control *c;
1679
1680 D3(printk("jffs_read_inode(): inode->i_ino == %lu\n", inode->i_ino));
1681
1682 if (!inode->i_sb) {
1683 D(printk("jffs_read_inode(): !inode->i_sb ==> "
1684 "No super block!\n"));
1685 return;
1686 }
1687 c = (struct jffs_control *)inode->i_sb->s_fs_info;
1688 D3(printk (KERN_NOTICE "read_inode(): down biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -08001689 mutex_lock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001690 if (!(f = jffs_find_file(c, inode->i_ino))) {
1691 D(printk("jffs_read_inode(): No such inode (%lu).\n",
1692 inode->i_ino));
1693 D3(printk (KERN_NOTICE "read_inode(): up biglock\n"));
Ingo Molnar1eb0d672006-03-23 03:00:40 -08001694 mutex_unlock(&c->fmc->biglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695 return;
1696 }
Theodore Ts'o8e18e292006-09-27 01:50:46 -07001697 inode->i_private = f;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001698 inode->i_mode = f->mode;
1699 inode->i_nlink = f->nlink;
1700 inode->i_uid = f->uid;
1701 inode->i_gid = f->gid;
1702 inode->i_size = f->size;
1703 inode->i_atime.tv_sec = f->atime;
1704 inode->i_mtime.tv_sec = f->mtime;
1705 inode->i_ctime.tv_sec = f->ctime;
1706 inode->i_atime.tv_nsec =
1707 inode->i_mtime.tv_nsec =
1708 inode->i_ctime.tv_nsec = 0;
1709
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710 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;
Theodore Ts'o8e18e292006-09-27 01:50:46 -07001751 inode->i_private = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001752 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
David Howells454e2392006-06-23 02:02:57 -07001788static int jffs_get_sb(struct file_system_type *fs_type,
1789 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001790{
David Howells454e2392006-06-23 02:02:57 -07001791 return get_sb_bdev(fs_type, flags, dev_name, data, jffs_fill_super,
1792 mnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001793}
1794
1795static struct file_system_type jffs_fs_type = {
1796 .owner = THIS_MODULE,
1797 .name = "jffs",
1798 .get_sb = jffs_get_sb,
1799 .kill_sb = kill_block_super,
1800 .fs_flags = FS_REQUIRES_DEV,
1801};
1802
1803static int __init
1804init_jffs_fs(void)
1805{
1806 printk(KERN_INFO "JFFS version " JFFS_VERSION_STRING
1807 ", (C) 1999, 2000 Axis Communications AB\n");
1808
1809#ifdef CONFIG_JFFS_PROC_FS
1810 jffs_proc_root = proc_mkdir("jffs", proc_root_fs);
1811 if (!jffs_proc_root) {
1812 printk(KERN_WARNING "cannot create /proc/jffs entry\n");
1813 }
1814#endif
1815 fm_cache = kmem_cache_create("jffs_fm", sizeof(struct jffs_fm),
Paul Jacksonfffb60f2006-03-24 03:16:06 -08001816 0,
1817 SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD,
1818 NULL, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001819 if (!fm_cache) {
1820 return -ENOMEM;
1821 }
1822
1823 node_cache = kmem_cache_create("jffs_node",sizeof(struct jffs_node),
Paul Jacksonfffb60f2006-03-24 03:16:06 -08001824 0,
1825 SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD,
1826 NULL, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001827 if (!node_cache) {
1828 kmem_cache_destroy(fm_cache);
1829 return -ENOMEM;
1830 }
1831
1832 return register_filesystem(&jffs_fs_type);
1833}
1834
1835static void __exit
1836exit_jffs_fs(void)
1837{
1838 unregister_filesystem(&jffs_fs_type);
1839 kmem_cache_destroy(fm_cache);
1840 kmem_cache_destroy(node_cache);
1841}
1842
1843module_init(init_jffs_fs)
1844module_exit(exit_jffs_fs)
1845
1846MODULE_DESCRIPTION("The Journalling Flash File System");
1847MODULE_AUTHOR("Axis Communications AB.");
1848MODULE_LICENSE("GPL");