aboutsummaryrefslogtreecommitdiff
path: root/fs/jffs2/nodemgmt.c
diff options
context:
space:
mode:
authorDaniel Drake <dsd@laptop.org>2012-04-10 22:22:35 +0100
committerDavid Woodhouse <David.Woodhouse@intel.com>2012-05-13 22:51:29 -0500
commit8da8ba2ea6ad52ea8558384f38586b0c1a516e9d (patch)
treed11d632886c481758b51cd5b9129dc0a5b94c7bd /fs/jffs2/nodemgmt.c
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/nodemgmt.c')
-rw-r--r--fs/jffs2/nodemgmt.c42
1 files changed, 42 insertions, 0 deletions
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 @@
#include "nodelist.h"
#include "debug.h"
+/*
+ * Check whether the user is allowed to write.
+ */
+static int jffs2_rp_can_write(struct jffs2_sb_info *c)
+{
+ uint32_t avail;
+ struct jffs2_mount_opts *opts = &c->mount_opts;
+
+ avail = c->dirty_size + c->free_size + c->unchecked_size +
+ c->erasing_size - c->resv_blocks_write * c->sector_size
+ - c->nospc_dirty_size;
+
+ if (avail < 2 * opts->rp_size)
+ jffs2_dbg(1, "rpsize %u, dirty_size %u, free_size %u, "
+ "erasing_size %u, unchecked_size %u, "
+ "nr_erasing_blocks %u, avail %u, resrv %u\n",
+ opts->rp_size, c->dirty_size, c->free_size,
+ c->erasing_size, c->unchecked_size,
+ c->nr_erasing_blocks, avail, c->nospc_dirty_size);
+
+ if (avail > opts->rp_size)
+ return 1;
+
+ /* Always allow root */
+ if (capable(CAP_SYS_RESOURCE))
+ return 1;
+
+ jffs2_dbg(1, "forbid writing\n");
+ return 0;
+}
+
/**
* jffs2_reserve_space - request physical space to write nodes to flash
* @c: superblock info
@@ -55,6 +86,15 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
spin_lock(&c->erase_completion_lock);
+ /*
+ * Check if the free space is greater then size of the reserved pool.
+ * If not, only allow root to proceed with writing.
+ */
+ if (prio != ALLOC_DELETION && !jffs2_rp_can_write(c)) {
+ ret = -ENOSPC;
+ goto out;
+ }
+
/* this needs a little more thought (true <tglx> :)) */
while(ret == -EAGAIN) {
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,
jffs2_dbg(1, "%s(): ret is %d\n", __func__, ret);
}
}
+
+out:
spin_unlock(&c->erase_completion_lock);
if (!ret)
ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, 1);