aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jffs2
diff options
context:
space:
mode:
Diffstat (limited to 'fs/jffs2')
-rw-r--r--fs/jffs2/Kconfig188
-rw-r--r--fs/jffs2/background.c10
-rw-r--r--fs/jffs2/compr.c4
-rw-r--r--fs/jffs2/compr_lzo.c15
-rw-r--r--fs/jffs2/dir.c9
-rw-r--r--fs/jffs2/erase.c4
-rw-r--r--fs/jffs2/fs.c6
-rw-r--r--fs/jffs2/nodemgmt.c6
-rw-r--r--fs/jffs2/super.c48
-rw-r--r--fs/jffs2/wbuf.c5
10 files changed, 269 insertions, 26 deletions
diff --git a/fs/jffs2/Kconfig b/fs/jffs2/Kconfig
new file mode 100644
index 000000000000..6ae169cd8faa
--- /dev/null
+++ b/fs/jffs2/Kconfig
@@ -0,0 +1,188 @@
1config JFFS2_FS
2 tristate "Journalling Flash File System v2 (JFFS2) support"
3 select CRC32
4 depends on MTD
5 help
6 JFFS2 is the second generation of the Journalling Flash File System
7 for use on diskless embedded devices. It provides improved wear
8 levelling, compression and support for hard links. You cannot use
9 this on normal block devices, only on 'MTD' devices.
10
11 Further information on the design and implementation of JFFS2 is
12 available at <http://sources.redhat.com/jffs2/>.
13
14config JFFS2_FS_DEBUG
15 int "JFFS2 debugging verbosity (0 = quiet, 2 = noisy)"
16 depends on JFFS2_FS
17 default "0"
18 help
19 This controls the amount of debugging messages produced by the JFFS2
20 code. Set it to zero for use in production systems. For evaluation,
21 testing and debugging, it's advisable to set it to one. This will
22 enable a few assertions and will print debugging messages at the
23 KERN_DEBUG loglevel, where they won't normally be visible. Level 2
24 is unlikely to be useful - it enables extra debugging in certain
25 areas which at one point needed debugging, but when the bugs were
26 located and fixed, the detailed messages were relegated to level 2.
27
28 If reporting bugs, please try to have available a full dump of the
29 messages at debug level 1 while the misbehaviour was occurring.
30
31config JFFS2_FS_WRITEBUFFER
32 bool "JFFS2 write-buffering support"
33 depends on JFFS2_FS
34 default y
35 help
36 This enables the write-buffering support in JFFS2.
37
38 This functionality is required to support JFFS2 on the following
39 types of flash devices:
40 - NAND flash
41 - NOR flash with transparent ECC
42 - DataFlash
43
44config JFFS2_FS_WBUF_VERIFY
45 bool "Verify JFFS2 write-buffer reads"
46 depends on JFFS2_FS_WRITEBUFFER
47 default n
48 help
49 This causes JFFS2 to read back every page written through the
50 write-buffer, and check for errors.
51
52config JFFS2_SUMMARY
53 bool "JFFS2 summary support (EXPERIMENTAL)"
54 depends on JFFS2_FS && EXPERIMENTAL
55 default n
56 help
57 This feature makes it possible to use summary information
58 for faster filesystem mount.
59
60 The summary information can be inserted into a filesystem image
61 by the utility 'sumtool'.
62
63 If unsure, say 'N'.
64
65config JFFS2_FS_XATTR
66 bool "JFFS2 XATTR support (EXPERIMENTAL)"
67 depends on JFFS2_FS && EXPERIMENTAL
68 default n
69 help
70 Extended attributes are name:value pairs associated with inodes by
71 the kernel or by users (see the attr(5) manual page, or visit
72 <http://acl.bestbits.at/> for details).
73
74 If unsure, say N.
75
76config JFFS2_FS_POSIX_ACL
77 bool "JFFS2 POSIX Access Control Lists"
78 depends on JFFS2_FS_XATTR
79 default y
80 select FS_POSIX_ACL
81 help
82 Posix Access Control Lists (ACLs) support permissions for users and
83 groups beyond the owner/group/world scheme.
84
85 To learn more about Access Control Lists, visit the Posix ACLs for
86 Linux website <http://acl.bestbits.at/>.
87
88 If you don't know what Access Control Lists are, say N
89
90config JFFS2_FS_SECURITY
91 bool "JFFS2 Security Labels"
92 depends on JFFS2_FS_XATTR
93 default y
94 help
95 Security labels support alternative access control models
96 implemented by security modules like SELinux. This option
97 enables an extended attribute handler for file security
98 labels in the jffs2 filesystem.
99
100 If you are not using a security module that requires using
101 extended attributes for file security labels, say N.
102
103config JFFS2_COMPRESSION_OPTIONS
104 bool "Advanced compression options for JFFS2"
105 depends on JFFS2_FS
106 default n
107 help
108 Enabling this option allows you to explicitly choose which
109 compression modules, if any, are enabled in JFFS2. Removing
110 compressors can mean you cannot read existing file systems,
111 and enabling experimental compressors can mean that you
112 write a file system which cannot be read by a standard kernel.
113
114 If unsure, you should _definitely_ say 'N'.
115
116config JFFS2_ZLIB
117 bool "JFFS2 ZLIB compression support" if JFFS2_COMPRESSION_OPTIONS
118 select ZLIB_INFLATE
119 select ZLIB_DEFLATE
120 depends on JFFS2_FS
121 default y
122 help
123 Zlib is designed to be a free, general-purpose, legally unencumbered,
124 lossless data-compression library for use on virtually any computer
125 hardware and operating system. See <http://www.gzip.org/zlib/> for
126 further information.
127
128 Say 'Y' if unsure.
129
130config JFFS2_LZO
131 bool "JFFS2 LZO compression support" if JFFS2_COMPRESSION_OPTIONS
132 select LZO_COMPRESS
133 select LZO_DECOMPRESS
134 depends on JFFS2_FS
135 default n
136 help
137 minilzo-based compression. Generally works better than Zlib.
138
139 This feature was added in July, 2007. Say 'N' if you need
140 compatibility with older bootloaders or kernels.
141
142config JFFS2_RTIME
143 bool "JFFS2 RTIME compression support" if JFFS2_COMPRESSION_OPTIONS
144 depends on JFFS2_FS
145 default y
146 help
147 Rtime does manage to recompress already-compressed data. Say 'Y' if unsure.
148
149config JFFS2_RUBIN
150 bool "JFFS2 RUBIN compression support" if JFFS2_COMPRESSION_OPTIONS
151 depends on JFFS2_FS
152 default n
153 help
154 RUBINMIPS and DYNRUBIN compressors. Say 'N' if unsure.
155
156choice
157 prompt "JFFS2 default compression mode" if JFFS2_COMPRESSION_OPTIONS
158 default JFFS2_CMODE_PRIORITY
159 depends on JFFS2_FS
160 help
161 You can set here the default compression mode of JFFS2 from
162 the available compression modes. Don't touch if unsure.
163
164config JFFS2_CMODE_NONE
165 bool "no compression"
166 help
167 Uses no compression.
168
169config JFFS2_CMODE_PRIORITY
170 bool "priority"
171 help
172 Tries the compressors in a predefined order and chooses the first
173 successful one.
174
175config JFFS2_CMODE_SIZE
176 bool "size (EXPERIMENTAL)"
177 help
178 Tries all compressors and chooses the one which has the smallest
179 result.
180
181config JFFS2_CMODE_FAVOURLZO
182 bool "Favour LZO"
183 help
184 Tries all compressors and chooses the one which has the smallest
185 result but gives some preference to LZO (which has faster
186 decompression) at the expense of size.
187
188endchoice
diff --git a/fs/jffs2/background.c b/fs/jffs2/background.c
index 8adebd3e43c6..3cceef4ad2b7 100644
--- a/fs/jffs2/background.c
+++ b/fs/jffs2/background.c
@@ -85,15 +85,15 @@ static int jffs2_garbage_collect_thread(void *_c)
85 for (;;) { 85 for (;;) {
86 allow_signal(SIGHUP); 86 allow_signal(SIGHUP);
87 again: 87 again:
88 spin_lock(&c->erase_completion_lock);
88 if (!jffs2_thread_should_wake(c)) { 89 if (!jffs2_thread_should_wake(c)) {
89 set_current_state (TASK_INTERRUPTIBLE); 90 set_current_state (TASK_INTERRUPTIBLE);
91 spin_unlock(&c->erase_completion_lock);
90 D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread sleeping...\n")); 92 D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread sleeping...\n"));
91 /* Yes, there's a race here; we checked jffs2_thread_should_wake()
92 before setting current->state to TASK_INTERRUPTIBLE. But it doesn't
93 matter - We don't care if we miss a wakeup, because the GC thread
94 is only an optimisation anyway. */
95 schedule(); 93 schedule();
96 } 94 } else
95 spin_unlock(&c->erase_completion_lock);
96
97 97
98 /* This thread is purely an optimisation. But if it runs when 98 /* This thread is purely an optimisation. But if it runs when
99 other things could be running, it actually makes things a 99 other things could be running, it actually makes things a
diff --git a/fs/jffs2/compr.c b/fs/jffs2/compr.c
index 86739ee53b37..f25e70c1b51c 100644
--- a/fs/jffs2/compr.c
+++ b/fs/jffs2/compr.c
@@ -53,8 +53,8 @@ static int jffs2_is_best_compression(struct jffs2_compressor *this,
53} 53}
54 54
55/* jffs2_compress: 55/* jffs2_compress:
56 * @data: Pointer to uncompressed data 56 * @data_in: Pointer to uncompressed data
57 * @cdata: Pointer to returned pointer to buffer for compressed data 57 * @cpage_out: Pointer to returned pointer to buffer for compressed data
58 * @datalen: On entry, holds the amount of data available for compression. 58 * @datalen: On entry, holds the amount of data available for compression.
59 * On exit, expected to hold the amount of data actually compressed. 59 * On exit, expected to hold the amount of data actually compressed.
60 * @cdatalen: On entry, holds the amount of space available for compressed 60 * @cdatalen: On entry, holds the amount of space available for compressed
diff --git a/fs/jffs2/compr_lzo.c b/fs/jffs2/compr_lzo.c
index 47b045797e42..90cb60d09787 100644
--- a/fs/jffs2/compr_lzo.c
+++ b/fs/jffs2/compr_lzo.c
@@ -19,7 +19,7 @@
19 19
20static void *lzo_mem; 20static void *lzo_mem;
21static void *lzo_compress_buf; 21static void *lzo_compress_buf;
22static DEFINE_MUTEX(deflate_mutex); 22static DEFINE_MUTEX(deflate_mutex); /* for lzo_mem and lzo_compress_buf */
23 23
24static void free_workspace(void) 24static void free_workspace(void)
25{ 25{
@@ -49,18 +49,21 @@ static int jffs2_lzo_compress(unsigned char *data_in, unsigned char *cpage_out,
49 49
50 mutex_lock(&deflate_mutex); 50 mutex_lock(&deflate_mutex);
51 ret = lzo1x_1_compress(data_in, *sourcelen, lzo_compress_buf, &compress_size, lzo_mem); 51 ret = lzo1x_1_compress(data_in, *sourcelen, lzo_compress_buf, &compress_size, lzo_mem);
52 mutex_unlock(&deflate_mutex);
53
54 if (ret != LZO_E_OK) 52 if (ret != LZO_E_OK)
55 return -1; 53 goto fail;
56 54
57 if (compress_size > *dstlen) 55 if (compress_size > *dstlen)
58 return -1; 56 goto fail;
59 57
60 memcpy(cpage_out, lzo_compress_buf, compress_size); 58 memcpy(cpage_out, lzo_compress_buf, compress_size);
61 *dstlen = compress_size; 59 mutex_unlock(&deflate_mutex);
62 60
61 *dstlen = compress_size;
63 return 0; 62 return 0;
63
64 fail:
65 mutex_unlock(&deflate_mutex);
66 return -1;
64} 67}
65 68
66static int jffs2_lzo_decompress(unsigned char *data_in, unsigned char *cpage_out, 69static int jffs2_lzo_decompress(unsigned char *data_in, unsigned char *cpage_out,
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index cd219ef55254..6f60cc910f4c 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -39,7 +39,8 @@ const struct file_operations jffs2_dir_operations =
39 .read = generic_read_dir, 39 .read = generic_read_dir,
40 .readdir = jffs2_readdir, 40 .readdir = jffs2_readdir,
41 .unlocked_ioctl=jffs2_ioctl, 41 .unlocked_ioctl=jffs2_ioctl,
42 .fsync = jffs2_fsync 42 .fsync = jffs2_fsync,
43 .llseek = generic_file_llseek,
43}; 44};
44 45
45 46
@@ -108,9 +109,7 @@ static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target,
108 } 109 }
109 } 110 }
110 111
111 d_add(target, inode); 112 return d_splice_alias(inode, target);
112
113 return NULL;
114} 113}
115 114
116/***********************************************************************/ 115/***********************************************************************/
@@ -311,7 +310,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
311 /* FIXME: If you care. We'd need to use frags for the target 310 /* FIXME: If you care. We'd need to use frags for the target
312 if it grows much more than this */ 311 if it grows much more than this */
313 if (targetlen > 254) 312 if (targetlen > 254)
314 return -EINVAL; 313 return -ENAMETOOLONG;
315 314
316 ri = jffs2_alloc_raw_inode(); 315 ri = jffs2_alloc_raw_inode();
317 316
diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c
index dddb2a6c9e2c..259461b910af 100644
--- a/fs/jffs2/erase.c
+++ b/fs/jffs2/erase.c
@@ -68,7 +68,7 @@ static void jffs2_erase_block(struct jffs2_sb_info *c,
68 instr->len = c->sector_size; 68 instr->len = c->sector_size;
69 instr->callback = jffs2_erase_callback; 69 instr->callback = jffs2_erase_callback;
70 instr->priv = (unsigned long)(&instr[1]); 70 instr->priv = (unsigned long)(&instr[1]);
71 instr->fail_addr = 0xffffffff; 71 instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
72 72
73 ((struct erase_priv_struct *)instr->priv)->jeb = jeb; 73 ((struct erase_priv_struct *)instr->priv)->jeb = jeb;
74 ((struct erase_priv_struct *)instr->priv)->c = c; 74 ((struct erase_priv_struct *)instr->priv)->c = c;
@@ -175,7 +175,7 @@ static void jffs2_erase_failed(struct jffs2_sb_info *c, struct jffs2_eraseblock
175{ 175{
176 /* For NAND, if the failure did not occur at the device level for a 176 /* For NAND, if the failure did not occur at the device level for a
177 specific physical page, don't bother updating the bad block table. */ 177 specific physical page, don't bother updating the bad block table. */
178 if (jffs2_cleanmarker_oob(c) && (bad_offset != 0xffffffff)) { 178 if (jffs2_cleanmarker_oob(c) && (bad_offset != MTD_FAIL_ADDR_UNKNOWN)) {
179 /* We had a device-level failure to erase. Let's see if we've 179 /* We had a device-level failure to erase. Let's see if we've
180 failed too many times. */ 180 failed too many times. */
181 if (!jffs2_write_nand_badblock(c, jeb, bad_offset)) { 181 if (!jffs2_write_nand_badblock(c, jeb, bad_offset)) {
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index 086c43830221..249305d65d5b 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -207,6 +207,8 @@ int jffs2_statfs(struct dentry *dentry, struct kstatfs *buf)
207 buf->f_files = 0; 207 buf->f_files = 0;
208 buf->f_ffree = 0; 208 buf->f_ffree = 0;
209 buf->f_namelen = JFFS2_MAX_NAME_LEN; 209 buf->f_namelen = JFFS2_MAX_NAME_LEN;
210 buf->f_fsid.val[0] = JFFS2_SUPER_MAGIC;
211 buf->f_fsid.val[1] = c->mtd->index;
210 212
211 spin_lock(&c->erase_completion_lock); 213 spin_lock(&c->erase_completion_lock);
212 avail = c->dirty_size + c->free_size; 214 avail = c->dirty_size + c->free_size;
@@ -440,14 +442,14 @@ struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_i
440 442
441 memset(ri, 0, sizeof(*ri)); 443 memset(ri, 0, sizeof(*ri));
442 /* Set OS-specific defaults for new inodes */ 444 /* Set OS-specific defaults for new inodes */
443 ri->uid = cpu_to_je16(current->fsuid); 445 ri->uid = cpu_to_je16(current_fsuid());
444 446
445 if (dir_i->i_mode & S_ISGID) { 447 if (dir_i->i_mode & S_ISGID) {
446 ri->gid = cpu_to_je16(dir_i->i_gid); 448 ri->gid = cpu_to_je16(dir_i->i_gid);
447 if (S_ISDIR(mode)) 449 if (S_ISDIR(mode))
448 mode |= S_ISGID; 450 mode |= S_ISGID;
449 } else { 451 } else {
450 ri->gid = cpu_to_je16(current->fsgid); 452 ri->gid = cpu_to_je16(current_fsgid());
451 } 453 }
452 454
453 /* POSIX ACLs have to be processed now, at least partly. 455 /* POSIX ACLs have to be processed now, at least partly.
diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c
index a9bf9603c1ba..21a052915aa9 100644
--- a/fs/jffs2/nodemgmt.c
+++ b/fs/jffs2/nodemgmt.c
@@ -261,6 +261,12 @@ static int jffs2_find_nextblock(struct jffs2_sb_info *c)
261 261
262 jffs2_sum_reset_collected(c->summary); /* reset collected summary */ 262 jffs2_sum_reset_collected(c->summary); /* reset collected summary */
263 263
264#ifdef CONFIG_JFFS2_FS_WRITEBUFFER
265 /* adjust write buffer offset, else we get a non contiguous write bug */
266 if (!(c->wbuf_ofs % c->sector_size) && !c->wbuf_len)
267 c->wbuf_ofs = 0xffffffff;
268#endif
269
264 D1(printk(KERN_DEBUG "jffs2_find_nextblock(): new nextblock = 0x%08x\n", c->nextblock->offset)); 270 D1(printk(KERN_DEBUG "jffs2_find_nextblock(): new nextblock = 0x%08x\n", c->nextblock->offset));
265 271
266 return 0; 272 return 0;
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
index efd401257ed9..4c4e18c54a51 100644
--- a/fs/jffs2/super.c
+++ b/fs/jffs2/super.c
@@ -22,6 +22,7 @@
22#include <linux/mtd/super.h> 22#include <linux/mtd/super.h>
23#include <linux/ctype.h> 23#include <linux/ctype.h>
24#include <linux/namei.h> 24#include <linux/namei.h>
25#include <linux/exportfs.h>
25#include "compr.h" 26#include "compr.h"
26#include "nodelist.h" 27#include "nodelist.h"
27 28
@@ -62,6 +63,52 @@ static int jffs2_sync_fs(struct super_block *sb, int wait)
62 return 0; 63 return 0;
63} 64}
64 65
66static struct inode *jffs2_nfs_get_inode(struct super_block *sb, uint64_t ino,
67 uint32_t generation)
68{
69 /* We don't care about i_generation. We'll destroy the flash
70 before we start re-using inode numbers anyway. And even
71 if that wasn't true, we'd have other problems...*/
72 return jffs2_iget(sb, ino);
73}
74
75static struct dentry *jffs2_fh_to_dentry(struct super_block *sb, struct fid *fid,
76 int fh_len, int fh_type)
77{
78 return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
79 jffs2_nfs_get_inode);
80}
81
82static struct dentry *jffs2_fh_to_parent(struct super_block *sb, struct fid *fid,
83 int fh_len, int fh_type)
84{
85 return generic_fh_to_parent(sb, fid, fh_len, fh_type,
86 jffs2_nfs_get_inode);
87}
88
89static struct dentry *jffs2_get_parent(struct dentry *child)
90{
91 struct jffs2_inode_info *f;
92 uint32_t pino;
93
94 BUG_ON(!S_ISDIR(child->d_inode->i_mode));
95
96 f = JFFS2_INODE_INFO(child->d_inode);
97
98 pino = f->inocache->pino_nlink;
99
100 JFFS2_DEBUG("Parent of directory ino #%u is #%u\n",
101 f->inocache->ino, pino);
102
103 return d_obtain_alias(jffs2_iget(child->d_inode->i_sb, pino));
104}
105
106static struct export_operations jffs2_export_ops = {
107 .get_parent = jffs2_get_parent,
108 .fh_to_dentry = jffs2_fh_to_dentry,
109 .fh_to_parent = jffs2_fh_to_parent,
110};
111
65static const struct super_operations jffs2_super_operations = 112static const struct super_operations jffs2_super_operations =
66{ 113{
67 .alloc_inode = jffs2_alloc_inode, 114 .alloc_inode = jffs2_alloc_inode,
@@ -104,6 +151,7 @@ static int jffs2_fill_super(struct super_block *sb, void *data, int silent)
104 spin_lock_init(&c->inocache_lock); 151 spin_lock_init(&c->inocache_lock);
105 152
106 sb->s_op = &jffs2_super_operations; 153 sb->s_op = &jffs2_super_operations;
154 sb->s_export_op = &jffs2_export_ops;
107 sb->s_flags = sb->s_flags | MS_NOATIME; 155 sb->s_flags = sb->s_flags | MS_NOATIME;
108 sb->s_xattr = jffs2_xattr_handlers; 156 sb->s_xattr = jffs2_xattr_handlers;
109#ifdef CONFIG_JFFS2_FS_POSIX_ACL 157#ifdef CONFIG_JFFS2_FS_POSIX_ACL
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c
index 0e78b00035e4..d9a721e6db70 100644
--- a/fs/jffs2/wbuf.c
+++ b/fs/jffs2/wbuf.c
@@ -679,10 +679,7 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
679 679
680 memset(c->wbuf,0xff,c->wbuf_pagesize); 680 memset(c->wbuf,0xff,c->wbuf_pagesize);
681 /* adjust write buffer offset, else we get a non contiguous write bug */ 681 /* adjust write buffer offset, else we get a non contiguous write bug */
682 if (SECTOR_ADDR(c->wbuf_ofs) == SECTOR_ADDR(c->wbuf_ofs+c->wbuf_pagesize)) 682 c->wbuf_ofs += c->wbuf_pagesize;
683 c->wbuf_ofs += c->wbuf_pagesize;
684 else
685 c->wbuf_ofs = 0xffffffff;
686 c->wbuf_len = 0; 683 c->wbuf_len = 0;
687 return 0; 684 return 0;
688} 685}