aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jffs2
diff options
context:
space:
mode:
Diffstat (limited to 'fs/jffs2')
-rw-r--r--fs/jffs2/jffs2_fs_sb.h7
-rw-r--r--fs/jffs2/nodemgmt.c42
-rw-r--r--fs/jffs2/readinode.c19
-rw-r--r--fs/jffs2/super.c17
-rw-r--r--fs/jffs2/xattr.c23
-rw-r--r--fs/jffs2/xattr.h2
6 files changed, 97 insertions, 13 deletions
diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h
index 44dca1f041c5..413ef89c2d1b 100644
--- a/fs/jffs2/jffs2_fs_sb.h
+++ b/fs/jffs2/jffs2_fs_sb.h
@@ -32,6 +32,13 @@ struct jffs2_inodirty;
32struct jffs2_mount_opts { 32struct jffs2_mount_opts {
33 bool override_compr; 33 bool override_compr;
34 unsigned int compr; 34 unsigned int compr;
35
36 /* The size of the reserved pool. The reserved pool is the JFFS2 flash
37 * space which may only be used by root cannot be used by the other
38 * users. This is implemented simply by means of not allowing the
39 * latter users to write to the file system if the amount if the
40 * available space is less then 'rp_size'. */
41 unsigned int rp_size;
35}; 42};
36 43
37/* A struct for the overall file system control. Pointers to 44/* A struct for the overall file system control. Pointers to
diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c
index 6784d1e7a7eb..0c96eb52c797 100644
--- a/fs/jffs2/nodemgmt.c
+++ b/fs/jffs2/nodemgmt.c
@@ -18,6 +18,37 @@
18#include "nodelist.h" 18#include "nodelist.h"
19#include "debug.h" 19#include "debug.h"
20 20
21/*
22 * Check whether the user is allowed to write.
23 */
24static int jffs2_rp_can_write(struct jffs2_sb_info *c)
25{
26 uint32_t avail;
27 struct jffs2_mount_opts *opts = &c->mount_opts;
28
29 avail = c->dirty_size + c->free_size + c->unchecked_size +
30 c->erasing_size - c->resv_blocks_write * c->sector_size
31 - c->nospc_dirty_size;
32
33 if (avail < 2 * opts->rp_size)
34 jffs2_dbg(1, "rpsize %u, dirty_size %u, free_size %u, "
35 "erasing_size %u, unchecked_size %u, "
36 "nr_erasing_blocks %u, avail %u, resrv %u\n",
37 opts->rp_size, c->dirty_size, c->free_size,
38 c->erasing_size, c->unchecked_size,
39 c->nr_erasing_blocks, avail, c->nospc_dirty_size);
40
41 if (avail > opts->rp_size)
42 return 1;
43
44 /* Always allow root */
45 if (capable(CAP_SYS_RESOURCE))
46 return 1;
47
48 jffs2_dbg(1, "forbid writing\n");
49 return 0;
50}
51
21/** 52/**
22 * jffs2_reserve_space - request physical space to write nodes to flash 53 * jffs2_reserve_space - request physical space to write nodes to flash
23 * @c: superblock info 54 * @c: superblock info
@@ -55,6 +86,15 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
55 86
56 spin_lock(&c->erase_completion_lock); 87 spin_lock(&c->erase_completion_lock);
57 88
89 /*
90 * Check if the free space is greater then size of the reserved pool.
91 * If not, only allow root to proceed with writing.
92 */
93 if (prio != ALLOC_DELETION && !jffs2_rp_can_write(c)) {
94 ret = -ENOSPC;
95 goto out;
96 }
97
58 /* this needs a little more thought (true <tglx> :)) */ 98 /* this needs a little more thought (true <tglx> :)) */
59 while(ret == -EAGAIN) { 99 while(ret == -EAGAIN) {
60 while(c->nr_free_blocks + c->nr_erasing_blocks < blocksneeded) { 100 while(c->nr_free_blocks + c->nr_erasing_blocks < blocksneeded) {
@@ -158,6 +198,8 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
158 jffs2_dbg(1, "%s(): ret is %d\n", __func__, ret); 198 jffs2_dbg(1, "%s(): ret is %d\n", __func__, ret);
159 } 199 }
160 } 200 }
201
202out:
161 spin_unlock(&c->erase_completion_lock); 203 spin_unlock(&c->erase_completion_lock);
162 if (!ret) 204 if (!ret)
163 ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, 1); 205 ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, 1);
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
index dc0437e84763..1ea349fff68b 100644
--- a/fs/jffs2/readinode.c
+++ b/fs/jffs2/readinode.c
@@ -1266,19 +1266,25 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
1266 /* Symlink's inode data is the target path. Read it and 1266 /* Symlink's inode data is the target path. Read it and
1267 * keep in RAM to facilitate quick follow symlink 1267 * keep in RAM to facilitate quick follow symlink
1268 * operation. */ 1268 * operation. */
1269 f->target = kmalloc(je32_to_cpu(latest_node->csize) + 1, GFP_KERNEL); 1269 uint32_t csize = je32_to_cpu(latest_node->csize);
1270 if (csize > JFFS2_MAX_NAME_LEN) {
1271 mutex_unlock(&f->sem);
1272 jffs2_do_clear_inode(c, f);
1273 return -ENAMETOOLONG;
1274 }
1275 f->target = kmalloc(csize + 1, GFP_KERNEL);
1270 if (!f->target) { 1276 if (!f->target) {
1271 JFFS2_ERROR("can't allocate %d bytes of memory for the symlink target path cache\n", je32_to_cpu(latest_node->csize)); 1277 JFFS2_ERROR("can't allocate %u bytes of memory for the symlink target path cache\n", csize);
1272 mutex_unlock(&f->sem); 1278 mutex_unlock(&f->sem);
1273 jffs2_do_clear_inode(c, f); 1279 jffs2_do_clear_inode(c, f);
1274 return -ENOMEM; 1280 return -ENOMEM;
1275 } 1281 }
1276 1282
1277 ret = jffs2_flash_read(c, ref_offset(rii.latest_ref) + sizeof(*latest_node), 1283 ret = jffs2_flash_read(c, ref_offset(rii.latest_ref) + sizeof(*latest_node),
1278 je32_to_cpu(latest_node->csize), &retlen, (char *)f->target); 1284 csize, &retlen, (char *)f->target);
1279 1285
1280 if (ret || retlen != je32_to_cpu(latest_node->csize)) { 1286 if (ret || retlen != csize) {
1281 if (retlen != je32_to_cpu(latest_node->csize)) 1287 if (retlen != csize)
1282 ret = -EIO; 1288 ret = -EIO;
1283 kfree(f->target); 1289 kfree(f->target);
1284 f->target = NULL; 1290 f->target = NULL;
@@ -1287,7 +1293,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
1287 return ret; 1293 return ret;
1288 } 1294 }
1289 1295
1290 f->target[je32_to_cpu(latest_node->csize)] = '\0'; 1296 f->target[csize] = '\0';
1291 dbg_readinode("symlink's target '%s' cached\n", f->target); 1297 dbg_readinode("symlink's target '%s' cached\n", f->target);
1292 } 1298 }
1293 1299
@@ -1415,6 +1421,7 @@ int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *i
1415 mutex_unlock(&f->sem); 1421 mutex_unlock(&f->sem);
1416 jffs2_do_clear_inode(c, f); 1422 jffs2_do_clear_inode(c, f);
1417 } 1423 }
1424 jffs2_xattr_do_crccheck_inode(c, ic);
1418 kfree (f); 1425 kfree (f);
1419 return ret; 1426 return ret;
1420} 1427}
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
index bc586f204228..61ea41389f90 100644
--- a/fs/jffs2/super.c
+++ b/fs/jffs2/super.c
@@ -90,6 +90,8 @@ static int jffs2_show_options(struct seq_file *s, struct dentry *root)
90 90
91 if (opts->override_compr) 91 if (opts->override_compr)
92 seq_printf(s, ",compr=%s", jffs2_compr_name(opts->compr)); 92 seq_printf(s, ",compr=%s", jffs2_compr_name(opts->compr));
93 if (opts->rp_size)
94 seq_printf(s, ",rp_size=%u", opts->rp_size / 1024);
93 95
94 return 0; 96 return 0;
95} 97}
@@ -154,15 +156,18 @@ static const struct export_operations jffs2_export_ops = {
154 * JFFS2 mount options. 156 * JFFS2 mount options.
155 * 157 *
156 * Opt_override_compr: override default compressor 158 * Opt_override_compr: override default compressor
159 * Opt_rp_size: size of reserved pool in KiB
157 * Opt_err: just end of array marker 160 * Opt_err: just end of array marker
158 */ 161 */
159enum { 162enum {
160 Opt_override_compr, 163 Opt_override_compr,
164 Opt_rp_size,
161 Opt_err, 165 Opt_err,
162}; 166};
163 167
164static const match_table_t tokens = { 168static const match_table_t tokens = {
165 {Opt_override_compr, "compr=%s"}, 169 {Opt_override_compr, "compr=%s"},
170 {Opt_rp_size, "rp_size=%u"},
166 {Opt_err, NULL}, 171 {Opt_err, NULL},
167}; 172};
168 173
@@ -170,6 +175,7 @@ static int jffs2_parse_options(struct jffs2_sb_info *c, char *data)
170{ 175{
171 substring_t args[MAX_OPT_ARGS]; 176 substring_t args[MAX_OPT_ARGS];
172 char *p, *name; 177 char *p, *name;
178 unsigned int opt;
173 179
174 if (!data) 180 if (!data)
175 return 0; 181 return 0;
@@ -207,6 +213,17 @@ static int jffs2_parse_options(struct jffs2_sb_info *c, char *data)
207 kfree(name); 213 kfree(name);
208 c->mount_opts.override_compr = true; 214 c->mount_opts.override_compr = true;
209 break; 215 break;
216 case Opt_rp_size:
217 if (match_int(&args[0], &opt))
218 return -EINVAL;
219 opt *= 1024;
220 if (opt > c->mtd->size) {
221 pr_warn("Too large reserve pool specified, max "
222 "is %llu KB\n", c->mtd->size / 1024);
223 return -EINVAL;
224 }
225 c->mount_opts.rp_size = opt;
226 break;
210 default: 227 default:
211 pr_err("Error: unrecognized mount option '%s' or missing value\n", 228 pr_err("Error: unrecognized mount option '%s' or missing value\n",
212 p); 229 p);
diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c
index b55b803eddcb..3034e970eb9a 100644
--- a/fs/jffs2/xattr.c
+++ b/fs/jffs2/xattr.c
@@ -11,6 +11,8 @@
11 11
12#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 12#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13 13
14#define JFFS2_XATTR_IS_CORRUPTED 1
15
14#include <linux/kernel.h> 16#include <linux/kernel.h>
15#include <linux/slab.h> 17#include <linux/slab.h>
16#include <linux/fs.h> 18#include <linux/fs.h>
@@ -153,7 +155,7 @@ static int do_verify_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_dat
153 JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n", 155 JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
154 offset, je32_to_cpu(rx.hdr_crc), crc); 156 offset, je32_to_cpu(rx.hdr_crc), crc);
155 xd->flags |= JFFS2_XFLAGS_INVALID; 157 xd->flags |= JFFS2_XFLAGS_INVALID;
156 return -EIO; 158 return JFFS2_XATTR_IS_CORRUPTED;
157 } 159 }
158 totlen = PAD(sizeof(rx) + rx.name_len + 1 + je16_to_cpu(rx.value_len)); 160 totlen = PAD(sizeof(rx) + rx.name_len + 1 + je16_to_cpu(rx.value_len));
159 if (je16_to_cpu(rx.magic) != JFFS2_MAGIC_BITMASK 161 if (je16_to_cpu(rx.magic) != JFFS2_MAGIC_BITMASK
@@ -169,7 +171,7 @@ static int do_verify_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_dat
169 je32_to_cpu(rx.xid), xd->xid, 171 je32_to_cpu(rx.xid), xd->xid,
170 je32_to_cpu(rx.version), xd->version); 172 je32_to_cpu(rx.version), xd->version);
171 xd->flags |= JFFS2_XFLAGS_INVALID; 173 xd->flags |= JFFS2_XFLAGS_INVALID;
172 return -EIO; 174 return JFFS2_XATTR_IS_CORRUPTED;
173 } 175 }
174 xd->xprefix = rx.xprefix; 176 xd->xprefix = rx.xprefix;
175 xd->name_len = rx.name_len; 177 xd->name_len = rx.name_len;
@@ -227,12 +229,12 @@ static int do_load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum
227 data[xd->name_len] = '\0'; 229 data[xd->name_len] = '\0';
228 crc = crc32(0, data, length); 230 crc = crc32(0, data, length);
229 if (crc != xd->data_crc) { 231 if (crc != xd->data_crc) {
230 JFFS2_WARNING("node CRC failed (JFFS2_NODETYPE_XREF)" 232 JFFS2_WARNING("node CRC failed (JFFS2_NODETYPE_XATTR)"
231 " at %#08x, read: 0x%08x calculated: 0x%08x\n", 233 " at %#08x, read: 0x%08x calculated: 0x%08x\n",
232 ref_offset(xd->node), xd->data_crc, crc); 234 ref_offset(xd->node), xd->data_crc, crc);
233 kfree(data); 235 kfree(data);
234 xd->flags |= JFFS2_XFLAGS_INVALID; 236 xd->flags |= JFFS2_XFLAGS_INVALID;
235 return -EIO; 237 return JFFS2_XATTR_IS_CORRUPTED;
236 } 238 }
237 239
238 xd->flags |= JFFS2_XFLAGS_HOT; 240 xd->flags |= JFFS2_XFLAGS_HOT;
@@ -270,7 +272,7 @@ static int load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x
270 if (xd->xname) 272 if (xd->xname)
271 return 0; 273 return 0;
272 if (xd->flags & JFFS2_XFLAGS_INVALID) 274 if (xd->flags & JFFS2_XFLAGS_INVALID)
273 return -EIO; 275 return JFFS2_XATTR_IS_CORRUPTED;
274 if (unlikely(is_xattr_datum_unchecked(c, xd))) 276 if (unlikely(is_xattr_datum_unchecked(c, xd)))
275 rc = do_verify_xattr_datum(c, xd); 277 rc = do_verify_xattr_datum(c, xd);
276 if (!rc) 278 if (!rc)
@@ -435,6 +437,8 @@ static void unrefer_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datu
435 * is called to release xattr related objects when unmounting. 437 * is called to release xattr related objects when unmounting.
436 * check_xattr_ref_inode(c, ic) 438 * check_xattr_ref_inode(c, ic)
437 * is used to confirm inode does not have duplicate xattr name/value pair. 439 * is used to confirm inode does not have duplicate xattr name/value pair.
440 * jffs2_xattr_do_crccheck_inode(c, ic)
441 * is used to force xattr data integrity check during the initial gc scan.
438 * -------------------------------------------------- */ 442 * -------------------------------------------------- */
439static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) 443static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
440{ 444{
@@ -462,7 +466,7 @@ static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref
462 if (crc != je32_to_cpu(rr.node_crc)) { 466 if (crc != je32_to_cpu(rr.node_crc)) {
463 JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n", 467 JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
464 offset, je32_to_cpu(rr.node_crc), crc); 468 offset, je32_to_cpu(rr.node_crc), crc);
465 return -EIO; 469 return JFFS2_XATTR_IS_CORRUPTED;
466 } 470 }
467 if (je16_to_cpu(rr.magic) != JFFS2_MAGIC_BITMASK 471 if (je16_to_cpu(rr.magic) != JFFS2_MAGIC_BITMASK
468 || je16_to_cpu(rr.nodetype) != JFFS2_NODETYPE_XREF 472 || je16_to_cpu(rr.nodetype) != JFFS2_NODETYPE_XREF
@@ -472,7 +476,7 @@ static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref
472 offset, je16_to_cpu(rr.magic), JFFS2_MAGIC_BITMASK, 476 offset, je16_to_cpu(rr.magic), JFFS2_MAGIC_BITMASK,
473 je16_to_cpu(rr.nodetype), JFFS2_NODETYPE_XREF, 477 je16_to_cpu(rr.nodetype), JFFS2_NODETYPE_XREF,
474 je32_to_cpu(rr.totlen), PAD(sizeof(rr))); 478 je32_to_cpu(rr.totlen), PAD(sizeof(rr)));
475 return -EIO; 479 return JFFS2_XATTR_IS_CORRUPTED;
476 } 480 }
477 ref->ino = je32_to_cpu(rr.ino); 481 ref->ino = je32_to_cpu(rr.ino);
478 ref->xid = je32_to_cpu(rr.xid); 482 ref->xid = je32_to_cpu(rr.xid);
@@ -682,6 +686,11 @@ static int check_xattr_ref_inode(struct jffs2_sb_info *c, struct jffs2_inode_cac
682 return rc; 686 return rc;
683} 687}
684 688
689void jffs2_xattr_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
690{
691 check_xattr_ref_inode(c, ic);
692}
693
685/* -------- xattr subsystem functions --------------- 694/* -------- xattr subsystem functions ---------------
686 * jffs2_init_xattr_subsystem(c) 695 * jffs2_init_xattr_subsystem(c)
687 * is used to initialize semaphore and list_head, and some variables. 696 * is used to initialize semaphore and list_head, and some variables.
diff --git a/fs/jffs2/xattr.h b/fs/jffs2/xattr.h
index 7be4beb306f3..467ff376ee26 100644
--- a/fs/jffs2/xattr.h
+++ b/fs/jffs2/xattr.h
@@ -77,6 +77,7 @@ extern void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c);
77extern struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c, 77extern struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c,
78 uint32_t xid, uint32_t version); 78 uint32_t xid, uint32_t version);
79 79
80extern void jffs2_xattr_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic);
80extern void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic); 81extern void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic);
81extern void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic); 82extern void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic);
82 83
@@ -108,6 +109,7 @@ extern ssize_t jffs2_listxattr(struct dentry *, char *, size_t);
108#define jffs2_build_xattr_subsystem(c) 109#define jffs2_build_xattr_subsystem(c)
109#define jffs2_clear_xattr_subsystem(c) 110#define jffs2_clear_xattr_subsystem(c)
110 111
112#define jffs2_xattr_do_crccheck_inode(c, ic)
111#define jffs2_xattr_delete_inode(c, ic) 113#define jffs2_xattr_delete_inode(c, ic)
112#define jffs2_xattr_free_inode(c, ic) 114#define jffs2_xattr_free_inode(c, ic)
113#define jffs2_verify_xattr(c) (1) 115#define jffs2_verify_xattr(c) (1)