aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jffs2
diff options
context:
space:
mode:
authorDaniel Drake <dsd@laptop.org>2012-04-10 17:22:35 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2012-05-13 23:51:29 -0400
commit8da8ba2ea6ad52ea8558384f38586b0c1a516e9d (patch)
treed11d632886c481758b51cd5b9129dc0a5b94c7bd /fs/jffs2
parent886bd33da7cfb1f6c7f3396f7146278ed02e76a7 (diff)
JFFS2: Add parameter to reserve disk space for root
Add a new rp_size= parameter which creates a "reserved pool" of disk space which can only be used by root. Other users are not permitted to write to disk when the available space is less than the pool size. Based on original code by Artem Bityutskiy in https://dev.laptop.org/ticket/5317 [dwmw2: use capable(CAP_SYS_RESOURCE) not uid/gid check, fix debug prints] Signed-off-by: Daniel Drake <dsd@laptop.org> Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@linux.intel.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
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/super.c17
3 files changed, 66 insertions, 0 deletions
diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h
index 55a0c1dceadf..0d00bf26923b 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/super.c b/fs/jffs2/super.c
index f9916f312bd8..66d44560f75d 100644
--- a/fs/jffs2/super.c
+++ b/fs/jffs2/super.c
@@ -105,6 +105,8 @@ static int jffs2_show_options(struct seq_file *s, struct dentry *root)
105 105
106 if (opts->override_compr) 106 if (opts->override_compr)
107 seq_printf(s, ",compr=%s", jffs2_compr_name(opts->compr)); 107 seq_printf(s, ",compr=%s", jffs2_compr_name(opts->compr));
108 if (opts->rp_size)
109 seq_printf(s, ",rp_size=%u", opts->rp_size / 1024);
108 110
109 return 0; 111 return 0;
110} 112}
@@ -171,15 +173,18 @@ static const struct export_operations jffs2_export_ops = {
171 * JFFS2 mount options. 173 * JFFS2 mount options.
172 * 174 *
173 * Opt_override_compr: override default compressor 175 * Opt_override_compr: override default compressor
176 * Opt_rp_size: size of reserved pool in KiB
174 * Opt_err: just end of array marker 177 * Opt_err: just end of array marker
175 */ 178 */
176enum { 179enum {
177 Opt_override_compr, 180 Opt_override_compr,
181 Opt_rp_size,
178 Opt_err, 182 Opt_err,
179}; 183};
180 184
181static const match_table_t tokens = { 185static const match_table_t tokens = {
182 {Opt_override_compr, "compr=%s"}, 186 {Opt_override_compr, "compr=%s"},
187 {Opt_rp_size, "rp_size=%u"},
183 {Opt_err, NULL}, 188 {Opt_err, NULL},
184}; 189};
185 190
@@ -187,6 +192,7 @@ static int jffs2_parse_options(struct jffs2_sb_info *c, char *data)
187{ 192{
188 substring_t args[MAX_OPT_ARGS]; 193 substring_t args[MAX_OPT_ARGS];
189 char *p, *name; 194 char *p, *name;
195 unsigned int opt;
190 196
191 if (!data) 197 if (!data)
192 return 0; 198 return 0;
@@ -224,6 +230,17 @@ static int jffs2_parse_options(struct jffs2_sb_info *c, char *data)
224 kfree(name); 230 kfree(name);
225 c->mount_opts.override_compr = true; 231 c->mount_opts.override_compr = true;
226 break; 232 break;
233 case Opt_rp_size:
234 if (match_int(&args[0], &opt))
235 return -EINVAL;
236 opt *= 1024;
237 if (opt > c->mtd->size) {
238 pr_warn("Too large reserve pool specified, max "
239 "is %llu KB\n", c->mtd->size / 1024);
240 return -EINVAL;
241 }
242 c->mount_opts.rp_size = opt;
243 break;
227 default: 244 default:
228 pr_err("Error: unrecognized mount option '%s' or missing value\n", 245 pr_err("Error: unrecognized mount option '%s' or missing value\n",
229 p); 246 p);