diff options
Diffstat (limited to 'fs/jffs2/nodemgmt.c')
-rw-r--r-- | fs/jffs2/nodemgmt.c | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c index 6784d1e7a7e..0c96eb52c79 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 | */ | ||
24 | static 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 | |||
202 | out: | ||
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); |