aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jffs2
diff options
context:
space:
mode:
Diffstat (limited to 'fs/jffs2')
-rw-r--r--fs/jffs2/file.c2
-rw-r--r--fs/jffs2/readinode.c45
-rw-r--r--fs/jffs2/super.c194
-rw-r--r--fs/jffs2/xattr.c6
4 files changed, 50 insertions, 197 deletions
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index 99871279a1ed..c2530197be0c 100644
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -47,7 +47,7 @@ const struct file_operations jffs2_file_operations =
47 .ioctl = jffs2_ioctl, 47 .ioctl = jffs2_ioctl,
48 .mmap = generic_file_readonly_mmap, 48 .mmap = generic_file_readonly_mmap,
49 .fsync = jffs2_fsync, 49 .fsync = jffs2_fsync,
50 .sendfile = generic_file_sendfile 50 .splice_read = generic_file_splice_read,
51}; 51};
52 52
53/* jffs2_file_inode_operations */ 53/* jffs2_file_inode_operations */
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
index 4884d5edfe65..7b363786c2d2 100644
--- a/fs/jffs2/readinode.c
+++ b/fs/jffs2/readinode.c
@@ -210,8 +210,7 @@ static void jffs2_kill_tn(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info *
210 * offset, and the one with the smallest length will come first in the 210 * offset, and the one with the smallest length will come first in the
211 * ordering. 211 * ordering.
212 * 212 *
213 * Returns 0 if the node was inserted 213 * Returns 0 if the node was handled (including marking it obsolete)
214 * 1 if the node is obsolete (because we can't mark it so yet)
215 * < 0 an if error occurred 214 * < 0 an if error occurred
216 */ 215 */
217static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, 216static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
@@ -229,9 +228,16 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
229 check anyway. */ 228 check anyway. */
230 if (!tn->fn->size) { 229 if (!tn->fn->size) {
231 if (rii->mdata_tn) { 230 if (rii->mdata_tn) {
232 /* We had a candidate mdata node already */ 231 if (rii->mdata_tn->version < tn->version) {
233 dbg_readinode("kill old mdata with ver %d\n", rii->mdata_tn->version); 232 /* We had a candidate mdata node already */
234 jffs2_kill_tn(c, rii->mdata_tn); 233 dbg_readinode("kill old mdata with ver %d\n", rii->mdata_tn->version);
234 jffs2_kill_tn(c, rii->mdata_tn);
235 } else {
236 dbg_readinode("kill new mdata with ver %d (older than existing %d\n",
237 tn->version, rii->mdata_tn->version);
238 jffs2_kill_tn(c, tn);
239 return 0;
240 }
235 } 241 }
236 rii->mdata_tn = tn; 242 rii->mdata_tn = tn;
237 dbg_readinode("keep new mdata with ver %d\n", tn->version); 243 dbg_readinode("keep new mdata with ver %d\n", tn->version);
@@ -565,8 +571,7 @@ static struct jffs2_raw_node_ref *jffs2_first_valid_node(struct jffs2_raw_node_r
565 * Helper function for jffs2_get_inode_nodes(). 571 * Helper function for jffs2_get_inode_nodes().
566 * It is called every time an directory entry node is found. 572 * It is called every time an directory entry node is found.
567 * 573 *
568 * Returns: 0 on succes; 574 * Returns: 0 on success;
569 * 1 if the node should be marked obsolete;
570 * negative error code on failure. 575 * negative error code on failure.
571 */ 576 */
572static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, 577static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref,
@@ -673,8 +678,7 @@ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_r
673 * Helper function for jffs2_get_inode_nodes(). 678 * Helper function for jffs2_get_inode_nodes().
674 * It is called every time an inode node is found. 679 * It is called every time an inode node is found.
675 * 680 *
676 * Returns: 0 on success; 681 * Returns: 0 on success (possibly after marking a bad node obsolete);
677 * 1 if the node should be marked obsolete;
678 * negative error code on failure. 682 * negative error code on failure.
679 */ 683 */
680static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, 684static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref,
@@ -683,7 +687,7 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
683{ 687{
684 struct jffs2_tmp_dnode_info *tn; 688 struct jffs2_tmp_dnode_info *tn;
685 uint32_t len, csize; 689 uint32_t len, csize;
686 int ret = 1; 690 int ret = 0;
687 uint32_t crc; 691 uint32_t crc;
688 692
689 /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */ 693 /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */
@@ -712,8 +716,9 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
712 /* Sanity checks */ 716 /* Sanity checks */
713 if (unlikely(je32_to_cpu(rd->offset) > je32_to_cpu(rd->isize)) || 717 if (unlikely(je32_to_cpu(rd->offset) > je32_to_cpu(rd->isize)) ||
714 unlikely(PAD(je32_to_cpu(rd->csize) + sizeof(*rd)) != PAD(je32_to_cpu(rd->totlen)))) { 718 unlikely(PAD(je32_to_cpu(rd->csize) + sizeof(*rd)) != PAD(je32_to_cpu(rd->totlen)))) {
715 JFFS2_WARNING("inode node header CRC is corrupted at %#08x\n", ref_offset(ref)); 719 JFFS2_WARNING("inode node header CRC is corrupted at %#08x\n", ref_offset(ref));
716 jffs2_dbg_dump_node(c, ref_offset(ref)); 720 jffs2_dbg_dump_node(c, ref_offset(ref));
721 jffs2_mark_node_obsolete(c, ref);
717 goto free_out; 722 goto free_out;
718 } 723 }
719 724
@@ -768,6 +773,7 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
768 if (len >= csize && unlikely(tn->partial_crc != je32_to_cpu(rd->data_crc))) { 773 if (len >= csize && unlikely(tn->partial_crc != je32_to_cpu(rd->data_crc))) {
769 JFFS2_NOTICE("wrong data CRC in data node at 0x%08x: read %#08x, calculated %#08x.\n", 774 JFFS2_NOTICE("wrong data CRC in data node at 0x%08x: read %#08x, calculated %#08x.\n",
770 ref_offset(ref), tn->partial_crc, je32_to_cpu(rd->data_crc)); 775 ref_offset(ref), tn->partial_crc, je32_to_cpu(rd->data_crc));
776 jffs2_mark_node_obsolete(c, ref);
771 goto free_out; 777 goto free_out;
772 } 778 }
773 779
@@ -847,7 +853,6 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
847 * It is called every time an unknown node is found. 853 * It is called every time an unknown node is found.
848 * 854 *
849 * Returns: 0 on success; 855 * Returns: 0 on success;
850 * 1 if the node should be marked obsolete;
851 * negative error code on failure. 856 * negative error code on failure.
852 */ 857 */
853static inline int read_unknown(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, struct jffs2_unknown_node *un) 858static inline int read_unknown(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, struct jffs2_unknown_node *un)
@@ -1044,7 +1049,8 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf
1044 1049
1045 case JFFS2_NODETYPE_DIRENT: 1050 case JFFS2_NODETYPE_DIRENT:
1046 1051
1047 if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_dirent)) { 1052 if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_dirent) &&
1053 len < sizeof(struct jffs2_raw_dirent)) {
1048 err = read_more(c, ref, sizeof(struct jffs2_raw_dirent), &len, buf); 1054 err = read_more(c, ref, sizeof(struct jffs2_raw_dirent), &len, buf);
1049 if (unlikely(err)) 1055 if (unlikely(err))
1050 goto free_out; 1056 goto free_out;
@@ -1058,7 +1064,8 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf
1058 1064
1059 case JFFS2_NODETYPE_INODE: 1065 case JFFS2_NODETYPE_INODE:
1060 1066
1061 if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_inode)) { 1067 if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_inode) &&
1068 len < sizeof(struct jffs2_raw_inode)) {
1062 err = read_more(c, ref, sizeof(struct jffs2_raw_inode), &len, buf); 1069 err = read_more(c, ref, sizeof(struct jffs2_raw_inode), &len, buf);
1063 if (unlikely(err)) 1070 if (unlikely(err))
1064 goto free_out; 1071 goto free_out;
@@ -1071,17 +1078,15 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf
1071 break; 1078 break;
1072 1079
1073 default: 1080 default:
1074 if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_unknown_node)) { 1081 if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_unknown_node) &&
1082 len < sizeof(struct jffs2_unknown_node)) {
1075 err = read_more(c, ref, sizeof(struct jffs2_unknown_node), &len, buf); 1083 err = read_more(c, ref, sizeof(struct jffs2_unknown_node), &len, buf);
1076 if (unlikely(err)) 1084 if (unlikely(err))
1077 goto free_out; 1085 goto free_out;
1078 } 1086 }
1079 1087
1080 err = read_unknown(c, ref, &node->u); 1088 err = read_unknown(c, ref, &node->u);
1081 if (err == 1) { 1089 if (unlikely(err))
1082 jffs2_mark_node_obsolete(c, ref);
1083 break;
1084 } else if (unlikely(err))
1085 goto free_out; 1090 goto free_out;
1086 1091
1087 } 1092 }
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
index 6488af43bc9b..e220d3bd610d 100644
--- a/fs/jffs2/super.c
+++ b/fs/jffs2/super.c
@@ -19,7 +19,7 @@
19#include <linux/mount.h> 19#include <linux/mount.h>
20#include <linux/jffs2.h> 20#include <linux/jffs2.h>
21#include <linux/pagemap.h> 21#include <linux/pagemap.h>
22#include <linux/mtd/mtd.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 "compr.h" 25#include "compr.h"
@@ -75,69 +75,27 @@ static const struct super_operations jffs2_super_operations =
75 .sync_fs = jffs2_sync_fs, 75 .sync_fs = jffs2_sync_fs,
76}; 76};
77 77
78static int jffs2_sb_compare(struct super_block *sb, void *data) 78/*
79{ 79 * fill in the superblock
80 struct jffs2_sb_info *p = data; 80 */
81 struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); 81static int jffs2_fill_super(struct super_block *sb, void *data, int silent)
82
83 /* The superblocks are considered to be equivalent if the underlying MTD
84 device is the same one */
85 if (c->mtd == p->mtd) {
86 D1(printk(KERN_DEBUG "jffs2_sb_compare: match on device %d (\"%s\")\n", p->mtd->index, p->mtd->name));
87 return 1;
88 } else {
89 D1(printk(KERN_DEBUG "jffs2_sb_compare: No match, device %d (\"%s\"), device %d (\"%s\")\n",
90 c->mtd->index, c->mtd->name, p->mtd->index, p->mtd->name));
91 return 0;
92 }
93}
94
95static int jffs2_sb_set(struct super_block *sb, void *data)
96{
97 struct jffs2_sb_info *p = data;
98
99 /* For persistence of NFS exports etc. we use the same s_dev
100 each time we mount the device, don't just use an anonymous
101 device */
102 sb->s_fs_info = p;
103 p->os_priv = sb;
104 sb->s_dev = MKDEV(MTD_BLOCK_MAJOR, p->mtd->index);
105
106 return 0;
107}
108
109static int jffs2_get_sb_mtd(struct file_system_type *fs_type,
110 int flags, const char *dev_name,
111 void *data, struct mtd_info *mtd,
112 struct vfsmount *mnt)
113{ 82{
114 struct super_block *sb;
115 struct jffs2_sb_info *c; 83 struct jffs2_sb_info *c;
116 int ret; 84
85 D1(printk(KERN_DEBUG "jffs2_get_sb_mtd():"
86 " New superblock for device %d (\"%s\")\n",
87 sb->s_mtd->index, sb->s_mtd->name));
117 88
118 c = kzalloc(sizeof(*c), GFP_KERNEL); 89 c = kzalloc(sizeof(*c), GFP_KERNEL);
119 if (!c) 90 if (!c)
120 return -ENOMEM; 91 return -ENOMEM;
121 c->mtd = mtd;
122
123 sb = sget(fs_type, jffs2_sb_compare, jffs2_sb_set, c);
124
125 if (IS_ERR(sb))
126 goto out_error;
127
128 if (sb->s_root) {
129 /* New mountpoint for JFFS2 which is already mounted */
130 D1(printk(KERN_DEBUG "jffs2_get_sb_mtd(): Device %d (\"%s\") is already mounted\n",
131 mtd->index, mtd->name));
132 ret = simple_set_mnt(mnt, sb);
133 goto out_put;
134 }
135 92
136 D1(printk(KERN_DEBUG "jffs2_get_sb_mtd(): New superblock for device %d (\"%s\")\n", 93 c->mtd = sb->s_mtd;
137 mtd->index, mtd->name)); 94 c->os_priv = sb;
95 sb->s_fs_info = c;
138 96
139 /* Initialize JFFS2 superblock locks, the further initialization will be 97 /* Initialize JFFS2 superblock locks, the further initialization will
140 * done later */ 98 * be done later */
141 init_MUTEX(&c->alloc_sem); 99 init_MUTEX(&c->alloc_sem);
142 init_MUTEX(&c->erase_free_sem); 100 init_MUTEX(&c->erase_free_sem);
143 init_waitqueue_head(&c->erase_wait); 101 init_waitqueue_head(&c->erase_wait);
@@ -146,133 +104,20 @@ static int jffs2_get_sb_mtd(struct file_system_type *fs_type,
146 spin_lock_init(&c->inocache_lock); 104 spin_lock_init(&c->inocache_lock);
147 105
148 sb->s_op = &jffs2_super_operations; 106 sb->s_op = &jffs2_super_operations;
149 sb->s_flags = flags | MS_NOATIME; 107 sb->s_flags = sb->s_flags | MS_NOATIME;
150 sb->s_xattr = jffs2_xattr_handlers; 108 sb->s_xattr = jffs2_xattr_handlers;
151#ifdef CONFIG_JFFS2_FS_POSIX_ACL 109#ifdef CONFIG_JFFS2_FS_POSIX_ACL
152 sb->s_flags |= MS_POSIXACL; 110 sb->s_flags |= MS_POSIXACL;
153#endif 111#endif
154 ret = jffs2_do_fill_super(sb, data, flags & MS_SILENT ? 1 : 0); 112 return jffs2_do_fill_super(sb, data, silent);
155
156 if (ret) {
157 /* Failure case... */
158 up_write(&sb->s_umount);
159 deactivate_super(sb);
160 return ret;
161 }
162
163 sb->s_flags |= MS_ACTIVE;
164 return simple_set_mnt(mnt, sb);
165
166out_error:
167 ret = PTR_ERR(sb);
168 out_put:
169 kfree(c);
170 put_mtd_device(mtd);
171
172 return ret;
173}
174
175static int jffs2_get_sb_mtdnr(struct file_system_type *fs_type,
176 int flags, const char *dev_name,
177 void *data, int mtdnr,
178 struct vfsmount *mnt)
179{
180 struct mtd_info *mtd;
181
182 mtd = get_mtd_device(NULL, mtdnr);
183 if (IS_ERR(mtd)) {
184 D1(printk(KERN_DEBUG "jffs2: MTD device #%u doesn't appear to exist\n", mtdnr));
185 return PTR_ERR(mtd);
186 }
187
188 return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd, mnt);
189} 113}
190 114
191static int jffs2_get_sb(struct file_system_type *fs_type, 115static int jffs2_get_sb(struct file_system_type *fs_type,
192 int flags, const char *dev_name, 116 int flags, const char *dev_name,
193 void *data, struct vfsmount *mnt) 117 void *data, struct vfsmount *mnt)
194{ 118{
195 int err; 119 return get_sb_mtd(fs_type, flags, dev_name, data, jffs2_fill_super,
196 struct nameidata nd; 120 mnt);
197 int mtdnr;
198
199 if (!dev_name)
200 return -EINVAL;
201
202 D1(printk(KERN_DEBUG "jffs2_get_sb(): dev_name \"%s\"\n", dev_name));
203
204 /* The preferred way of mounting in future; especially when
205 CONFIG_BLK_DEV is implemented - we specify the underlying
206 MTD device by number or by name, so that we don't require
207 block device support to be present in the kernel. */
208
209 /* FIXME: How to do the root fs this way? */
210
211 if (dev_name[0] == 'm' && dev_name[1] == 't' && dev_name[2] == 'd') {
212 /* Probably mounting without the blkdev crap */
213 if (dev_name[3] == ':') {
214 struct mtd_info *mtd;
215
216 /* Mount by MTD device name */
217 D1(printk(KERN_DEBUG "jffs2_get_sb(): mtd:%%s, name \"%s\"\n", dev_name+4));
218 for (mtdnr = 0; mtdnr < MAX_MTD_DEVICES; mtdnr++) {
219 mtd = get_mtd_device(NULL, mtdnr);
220 if (!IS_ERR(mtd)) {
221 if (!strcmp(mtd->name, dev_name+4))
222 return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd, mnt);
223 put_mtd_device(mtd);
224 }
225 }
226 printk(KERN_NOTICE "jffs2_get_sb(): MTD device with name \"%s\" not found.\n", dev_name+4);
227 } else if (isdigit(dev_name[3])) {
228 /* Mount by MTD device number name */
229 char *endptr;
230
231 mtdnr = simple_strtoul(dev_name+3, &endptr, 0);
232 if (!*endptr) {
233 /* It was a valid number */
234 D1(printk(KERN_DEBUG "jffs2_get_sb(): mtd%%d, mtdnr %d\n", mtdnr));
235 return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr, mnt);
236 }
237 }
238 }
239
240 /* Try the old way - the hack where we allowed users to mount
241 /dev/mtdblock$(n) but didn't actually _use_ the blkdev */
242
243 err = path_lookup(dev_name, LOOKUP_FOLLOW, &nd);
244
245 D1(printk(KERN_DEBUG "jffs2_get_sb(): path_lookup() returned %d, inode %p\n",
246 err, nd.dentry->d_inode));
247
248 if (err)
249 return err;
250
251 err = -EINVAL;
252
253 if (!S_ISBLK(nd.dentry->d_inode->i_mode))
254 goto out;
255
256 if (nd.mnt->mnt_flags & MNT_NODEV) {
257 err = -EACCES;
258 goto out;
259 }
260
261 if (imajor(nd.dentry->d_inode) != MTD_BLOCK_MAJOR) {
262 if (!(flags & MS_SILENT))
263 printk(KERN_NOTICE "Attempt to mount non-MTD device \"%s\" as JFFS2\n",
264 dev_name);
265 goto out;
266 }
267
268 mtdnr = iminor(nd.dentry->d_inode);
269 path_release(&nd);
270
271 return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr, mnt);
272
273out:
274 path_release(&nd);
275 return err;
276} 121}
277 122
278static void jffs2_put_super (struct super_block *sb) 123static void jffs2_put_super (struct super_block *sb)
@@ -307,8 +152,7 @@ static void jffs2_kill_sb(struct super_block *sb)
307 struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); 152 struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
308 if (!(sb->s_flags & MS_RDONLY)) 153 if (!(sb->s_flags & MS_RDONLY))
309 jffs2_stop_garbage_collect_thread(c); 154 jffs2_stop_garbage_collect_thread(c);
310 generic_shutdown_super(sb); 155 kill_mtd_super(sb);
311 put_mtd_device(c->mtd);
312 kfree(c); 156 kfree(c);
313} 157}
314 158
diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c
index 78fc08893a6c..e48665984cb3 100644
--- a/fs/jffs2/xattr.c
+++ b/fs/jffs2/xattr.c
@@ -754,6 +754,10 @@ void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c)
754 list_del(&xd->xindex); 754 list_del(&xd->xindex);
755 jffs2_free_xattr_datum(xd); 755 jffs2_free_xattr_datum(xd);
756 } 756 }
757 list_for_each_entry_safe(xd, _xd, &c->xattr_unchecked, xindex) {
758 list_del(&xd->xindex);
759 jffs2_free_xattr_datum(xd);
760 }
757} 761}
758 762
759#define XREF_TMPHASH_SIZE (128) 763#define XREF_TMPHASH_SIZE (128)
@@ -825,7 +829,7 @@ void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c)
825 ref->xd and ref->ic are not valid yet. */ 829 ref->xd and ref->ic are not valid yet. */
826 xd = jffs2_find_xattr_datum(c, ref->xid); 830 xd = jffs2_find_xattr_datum(c, ref->xid);
827 ic = jffs2_get_ino_cache(c, ref->ino); 831 ic = jffs2_get_ino_cache(c, ref->ino);
828 if (!xd || !ic) { 832 if (!xd || !ic || !ic->nlink) {
829 dbg_xattr("xref(ino=%u, xid=%u, xseqno=%u) is orphan.\n", 833 dbg_xattr("xref(ino=%u, xid=%u, xseqno=%u) is orphan.\n",
830 ref->ino, ref->xid, ref->xseqno); 834 ref->ino, ref->xid, ref->xseqno);
831 ref->xseqno |= XREF_DELETE_MARKER; 835 ref->xseqno |= XREF_DELETE_MARKER;