public inbox for linux-mtd@lists.infradead.org
 help / color / mirror / Atom feed
* [PATCH/RFC] reserved pool
@ 2006-05-09 12:45 Artem B. Bityutskiy
  2006-05-10  8:29 ` Artem B. Bityutskiy
  0 siblings, 1 reply; 11+ messages in thread
From: Artem B. Bityutskiy @ 2006-05-09 12:45 UTC (permalink / raw)
  To: linux-mtd

Hello,

long time I was asked to solve a problem when users eat all the file
system free space and the system cannot boot because different programs
can't write any longer (-ENOSPC). I made a straight-forward patch and it
solved the problem.

I've adapted the patch to the newest JFFS2 and it is available here:

http://git.infradead.org/?p=users/dedekind/dedekind-mtd-2.6.git;a=commit;h=848824f86e755a4fbcf2052085b0c1a8e3e8c583

Do you have any suggestions how to better solve this problem? Objections
to let this solution go mainstream (after clean-ups/changes)?

-- 
Best Regards,
Artem B. Bityutskiy,
St.-Petersburg, Russia.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH/RFC] reserved pool
  2006-05-09 12:45 [PATCH/RFC] reserved pool Artem B. Bityutskiy
@ 2006-05-10  8:29 ` Artem B. Bityutskiy
  2006-05-10 13:35   ` Jörn Engel
  0 siblings, 1 reply; 11+ messages in thread
From: Artem B. Bityutskiy @ 2006-05-10  8:29 UTC (permalink / raw)
  To: linux-mtd

On Tue, 2006-05-09 at 16:45 +0400, Artem B. Bityutskiy wrote:
> Hello,
> 
> long time I was asked to solve a problem when users eat all the file
> system free space and the system cannot boot because different programs
> can't write any longer (-ENOSPC). I made a straight-forward patch and it
> solved the problem.

The patch is updated
(http://git.infradead.org/?p=users/dedekind/dedekind-mtd-2.6.git;a=commit;h=73229f32650fcefbcc0b0bf8b4c48fae1a70c10d).

diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index ea1f37d..f5d4319 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -348,10 +348,16 @@ void jffs2_dirty_inode(struct inode *ino
 int jffs2_remount_fs (struct super_block *sb, int *flags, char *data)
 {
 	struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
+	int ret;
 
 	if (c->flags & JFFS2_SB_FLAG_RO && !(sb->s_flags & MS_RDONLY))
 		return -EROFS;
 
+	/* Re-parse mount options */
+	ret = jffs2_parse_options(sb, data);
+	if (ret)
+		return ret;
+	
 	/* We stop if it was running, then restart if it needs to.
 	   This also catches the case where it was stopped and this
 	   is just a remount to restart it.
diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h
index 4bcfb55..9f6bc18 100644
--- a/fs/jffs2/jffs2_fs_sb.h
+++ b/fs/jffs2/jffs2_fs_sb.h
@@ -97,6 +97,11 @@ struct jffs2_sb_info {
 
 	uint32_t wbuf_pagesize; /* 0 for NOR and other flashes with no wbuf */
 
+	/* Size of the reserved pool. I.e., how many bytes of flash space are
+	 * reserved for root. Mortals cannot use it (-ENOSPC is returned). Set
+	 * up via mount options. */
+	unsigned int rp_size;
+
 #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
 	/* Write-behind buffer for NAND flash */
 	unsigned char *wbuf;
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h
index f6645af..ffe4176 100644
--- a/fs/jffs2/nodelist.h
+++ b/fs/jffs2/nodelist.h
@@ -18,6 +18,7 @@ #include <linux/config.h>
 #include <linux/fs.h>
 #include <linux/types.h>
 #include <linux/jffs2.h>
+#include <linux/capability.h>
 #include "jffs2_fs_sb.h"
 #include "jffs2_fs_i.h"
 #include "summary.h"
@@ -255,6 +256,23 @@ #endif
 	return ret;
 }
 
+/*
+ * Check whether there is enough space for a user to write.
+ */
+static inline int jffs2_user_can_write(struct jffs2_sb_info *c)
+{
+	unsigned int avail;
+	
+	if (capable(CAP_SYS_ADMIN))
+		return 1;
+
+	avail = c->dirty_size + c->free_size + c->unchecked_size +
+		c->erasing_size - c->resv_blocks_write * c->sector_size
+		- c->nospc_dirty_size;
+
+	return avail > c->rp_size;
+}
+
 #define ALLOC_NORMAL	0	/* Normal allocation */
 #define ALLOC_DELETION	1	/* Deletion node. Best to allow it */
 #define ALLOC_GC	2	/* Space requested for GC. Give it or die */
@@ -399,6 +417,9 @@ int jffs2_do_mount_fs(struct jffs2_sb_in
 
 /* erase.c */
 void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count);
+
+/* super.c */
+int jffs2_parse_options(struct super_block *sb, char *opts);
 
 #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
 /* wbuf.c */
diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c
index 49127a1..547af15 100644
--- a/fs/jffs2/nodemgmt.c
+++ b/fs/jffs2/nodemgmt.c
@@ -57,6 +57,12 @@ int jffs2_reserve_space(struct jffs2_sb_
 
 	spin_lock(&c->erase_completion_lock);
 
+        if (prio != ALLOC_DELETION && !jffs2_user_can_write(c)) {
+		spin_unlock(&c->erase_completion_lock);
+		up(&c->alloc_sem);
+		return -ENOSPC;
+	}
+
 	/* this needs a little more thought (true <tglx> :)) */
 	while(ret == -EAGAIN) {
 		while(c->nr_free_blocks + c->nr_erasing_blocks < blocksneeded) {
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
index ffd8e84..d9db0bb 100644
--- a/fs/jffs2/super.c
+++ b/fs/jffs2/super.c
@@ -24,10 +24,13 @@ #include <linux/pagemap.h>
 #include <linux/mtd/mtd.h>
 #include <linux/ctype.h>
 #include <linux/namei.h>
+#include <linux/parser.h>
+#include <linux/seq_file.h>
 #include "compr.h"
 #include "nodelist.h"
 
 static void jffs2_put_super(struct super_block *);
+static int jffs2_show_options(struct seq_file *m, struct vfsmount
*mnt);
 
 static kmem_cache_t *jffs2_inode_cachep;
 
@@ -78,6 +81,7 @@ static struct super_operations jffs2_sup
 	.clear_inode =	jffs2_clear_inode,
 	.dirty_inode =	jffs2_dirty_inode,
 	.sync_fs =	jffs2_sync_fs,
+	.show_options = jffs2_show_options,
 };
 
 static int jffs2_sb_compare(struct super_block *sb, void *data)
@@ -152,15 +156,15 @@ static struct super_block *jffs2_get_sb_
 	sb->s_op = &jffs2_super_operations;
 	sb->s_flags = flags | MS_NOATIME;
 
-	ret = jffs2_do_fill_super(sb, data, flags & MS_SILENT ? 1 : 0);
+ 	/* Parse mount options */
+ 	ret = jffs2_parse_options(sb, data);
+ 	if (ret)
+ 		goto error;
+ 	
+ 	ret = jffs2_do_fill_super(sb, data, flags & MS_SILENT ? 1 : 0);
+ 	if (ret) 
+ 		goto error;
 
-	if (ret) {
-		/* Failure case... */
-		up_write(&sb->s_umount);
-		deactivate_super(sb);
-		return ERR_PTR(ret);
-	}
-
 	sb->s_flags |= MS_ACTIVE;
 	return sb;
 
@@ -169,6 +173,12 @@ static struct super_block *jffs2_get_sb_
 	put_mtd_device(mtd);
 
 	return sb;
+
+ error:
+	/* Failure case... */
+	up_write(&sb->s_umount);
+	deactivate_super(sb);
+	return ERR_PTR(ret);
 }
 
 static struct super_block *jffs2_get_sb_mtdnr(struct file_system_type
*fs_type,
@@ -271,6 +281,70 @@ static struct super_block *jffs2_get_sb(
 out:
 	path_release(&nd);
 	return ERR_PTR(err);
+}
+
+/*
+ * Mount option identifiers.
+ */
+enum {
+	JFFS2_OPT_RP_SIZE,
+	JFFS2_OPT_LAST_FAKE
+};
+
+/*
+ * Supported mount options.
+ */
+static struct match_token tokens[] = {
+	{JFFS2_OPT_RP_SIZE, "rpsize=%u"}, /* Size of the reserved pool in KiB
*/
+	{JFFS2_OPT_LAST_FAKE, NULL}       /* End of list marker */
+};
+
+#define JFFS2_MAX_ARGS	1
+
+int jffs2_parse_options(struct super_block *sb, char *opts)
+{
+	unsigned int opt;
+	char *p;
+	substring_t args[JFFS2_MAX_ARGS];
+	struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
+
+	if (!opts)
+		return 0;
+
+	while ((p = strsep(&opts, ",")) != NULL) {
+		int token;
+
+		if (!*p)
+			continue;
+		
+		token = match_token(p, tokens, args);
+
+		switch (token) {
+			case JFFS2_OPT_RP_SIZE:
+				if (match_int(&args[0], &opt))
+					return -EINVAL;
+				c->rp_size = opt * 1024;
+				if (c->rp_size > c->mtd->size) {
+					JFFS2_WARNING("too large reserved pool size, max is %u KB\n",
+						      c->mtd->size/1024);
+					return -EINVAL;
+				}
+				break;
+			default:
+				return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+static int jffs2_show_options(struct seq_file *m, struct vfsmount *mnt)
+{
+	struct jffs2_sb_info *c = JFFS2_SB_INFO(mnt->mnt_sb);
+	
+	if (c->rp_size)
+		seq_printf(m, ",rpsize=%d", c->rp_size/1024);
+	return 0;
 }
 
 static void jffs2_put_super (struct super_block *sb)

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH/RFC] reserved pool
  2006-05-10  8:29 ` Artem B. Bityutskiy
@ 2006-05-10 13:35   ` Jörn Engel
  2006-05-10 13:54     ` Artem B. Bityutskiy
  0 siblings, 1 reply; 11+ messages in thread
From: Jörn Engel @ 2006-05-10 13:35 UTC (permalink / raw)
  To: Artem B. Bityutskiy; +Cc: linux-mtd

On Wed, 10 May 2006 12:29:02 +0400, Artem B. Bityutskiy wrote:
> +
> +int jffs2_parse_options(struct super_block *sb, char *opts)
> +{
> +	unsigned int opt;
> +	char *p;
> +	substring_t args[JFFS2_MAX_ARGS];
> +	struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
> +
> +	if (!opts)
> +		return 0;
> +
> +	while ((p = strsep(&opts, ",")) != NULL) {

" != NULL" is superfluous.

> +		int token;
> +
> +		if (!*p)
> +			continue;
> +		
> +		token = match_token(p, tokens, args);
> +
> +		switch (token) {
> +			case JFFS2_OPT_RP_SIZE:

One level of indentation can be save here.  Unlike dwmw2, I don't
participate in the terminal size arms race and still care about 80
columns. ;)

> +				if (match_int(&args[0], &opt))
> +					return -EINVAL;
> +				c->rp_size = opt * 1024;
> +				if (c->rp_size > c->mtd->size) {
> +					JFFS2_WARNING("too large reserved pool size, max is %u KB\n",
> +						      c->mtd->size/1024);
> +					return -EINVAL;
> +				}
> +				break;
> +			default:
> +				return -EINVAL;
> +		}
> +	}
> +
> +	return 0;
> +}

Rest looks fine to me.

Jörn

-- 
With a PC, I always felt limited by the software available. On Unix, 
I am limited only by my knowledge.
-- Peter J. Schoenster

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH/RFC] reserved pool
  2006-05-10 13:35   ` Jörn Engel
@ 2006-05-10 13:54     ` Artem B. Bityutskiy
  2006-05-10 13:58       ` Jörn Engel
  0 siblings, 1 reply; 11+ messages in thread
From: Artem B. Bityutskiy @ 2006-05-10 13:54 UTC (permalink / raw)
  To: Jörn Engel; +Cc: linux-mtd

On Wed, 2006-05-10 at 15:35 +0200, Jörn Engel wrote:

> > +	while ((p = strsep(&opts, ",")) != NULL) {
> " != NULL" is superfluous.
Fixed.

> > +		switch (token) {
> > +			case JFFS2_OPT_RP_SIZE:
> 
> One level of indentation can be save here.  Unlike dwmw2, I don't
> participate in the terminal size arms race and still care about 80
> columns. ;)
Fixed.

Thanks.

-- 
Best Regards,
Artem B. Bityutskiy,
St.-Petersburg, Russia.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH/RFC] reserved pool
  2006-05-10 13:54     ` Artem B. Bityutskiy
@ 2006-05-10 13:58       ` Jörn Engel
  2006-05-14 19:39         ` David Woodhouse
  0 siblings, 1 reply; 11+ messages in thread
From: Jörn Engel @ 2006-05-10 13:58 UTC (permalink / raw)
  To: Artem B. Bityutskiy; +Cc: linux-mtd

On Wed, 10 May 2006 17:54:11 +0400, Artem B. Bityutskiy wrote:
> On Wed, 2006-05-10 at 15:35 +0200, Jörn Engel wrote:
> 
> > > +	while ((p = strsep(&opts, ",")) != NULL) {
> > " != NULL" is superfluous.
> Fixed.
> 
> > > +		switch (token) {
> > > +			case JFFS2_OPT_RP_SIZE:
> > 
> > One level of indentation can be save here.  Unlike dwmw2, I don't
> > participate in the terminal size arms race and still care about 80
> > columns. ;)
> Fixed.

Then go and bug dwmw2 about merging it. ;)

Jörn

-- 
Data expands to fill the space available for storage.
-- Parkinson's Law

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH/RFC] reserved pool
  2006-05-10 13:58       ` Jörn Engel
@ 2006-05-14 19:39         ` David Woodhouse
  2006-05-15 14:19           ` Artem B. Bityutskiy
  0 siblings, 1 reply; 11+ messages in thread
From: David Woodhouse @ 2006-05-14 19:39 UTC (permalink / raw)
  To: Jörn Engel; +Cc: linux-mtd

On Wed, 2006-05-10 at 15:58 +0200, Jörn Engel wrote:
> > > One level of indentation can be save here.  Unlike dwmw2, I don't
> > > participate in the terminal size arms race and still care about 80
> > > columns. ;)

My terminals also have 80 columns, but they only have 25 lines. So while
you're fixing the 'too large reserved pool size' printk to say 'KiB',
please also make it fit on one line... if someone can't look at the
first 80 columns and work out what that printk is about, then they're
really beyond help. Don't go using up extra lines for their benefit.

> > Fixed.
> 
> Then go and bug dwmw2 about merging it. ;) 

We talked about changing the way the reserved size is actually handled
in the allocation routine.... did a new version ever show up?

-- 
dwmw2

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH/RFC] reserved pool
  2006-05-14 19:39         ` David Woodhouse
@ 2006-05-15 14:19           ` Artem B. Bityutskiy
  2006-05-16 23:30             ` David Woodhouse
  0 siblings, 1 reply; 11+ messages in thread
From: Artem B. Bityutskiy @ 2006-05-15 14:19 UTC (permalink / raw)
  To: David Woodhouse; +Cc: linux-mtd, Jörn Engel

On Sun, 2006-05-14 at 20:39 +0100, David Woodhouse wrote:
> > Then go and bug dwmw2 about merging it. ;) 
> 
> We talked about changing the way the reserved size is actually handled
> in the allocation routine.... did a new version ever show up?
> 
Please,

look/pull the '[JFFS2] add reserved pool feature' patch from
http://git.infradead.org/?p=users/dedekind/dedekind-mtd-2.6.git;a=summary

-- 
Best Regards,
Artem B. Bityutskiy,
St.-Petersburg, Russia.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH/RFC] reserved pool
  2006-05-15 14:19           ` Artem B. Bityutskiy
@ 2006-05-16 23:30             ` David Woodhouse
  2006-05-16 23:31               ` David Woodhouse
  2006-05-17  6:49               ` Artem B. Bityutskiy
  0 siblings, 2 replies; 11+ messages in thread
From: David Woodhouse @ 2006-05-16 23:30 UTC (permalink / raw)
  To: dedekind; +Cc: Jörn Engel, linux-mtd

On Mon, 2006-05-15 at 18:19 +0400, Artem B. Bityutskiy wrote:
> On Sun, 2006-05-14 at 20:39 +0100, David Woodhouse wrote:
> > > Then go and bug dwmw2 about merging it. ;) 
> > 
> > We talked about changing the way the reserved size is actually handled
> > in the allocation routine.... did a new version ever show up?
> > 
> Please,
> 
> look/pull the '[JFFS2] add reserved pool feature' patch from
> http://git.infradead.org/?p=users/dedekind/dedekind-mtd-2.6.git;a=summary

I cleaned it up so it looks like this.... and then decided not to apply
it. I don't like this kind of thing being a mount option. Make a new
node type for 'filesystem options'. Make it an RWCOMPAT_COPY node type.
Store the reserved size in it and do it through an ioctl like chattr
does on ext2 -- and make mkfs.jffs2 write it too. 

We'll want compression types stored in that node type too, I suspect.

-- 
dwmw2

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH/RFC] reserved pool
  2006-05-16 23:30             ` David Woodhouse
@ 2006-05-16 23:31               ` David Woodhouse
  2006-05-17  6:49               ` Artem B. Bityutskiy
  1 sibling, 0 replies; 11+ messages in thread
From: David Woodhouse @ 2006-05-16 23:31 UTC (permalink / raw)
  To: dedekind; +Cc: Jörn Engel, linux-mtd

On Wed, 2006-05-17 at 00:30 +0100, David Woodhouse wrote:
> I cleaned it up so it looks like this.... 

-ENOPATCH....

--- a/fs/jffs2/jffs2_fs_sb.h
+++ b/fs/jffs2/jffs2_fs_sb.h
@@ -61,6 +61,9 @@ struct jffs2_sb_info {
 	uint8_t resv_blocks_gcbad;	/* ... pick a block from the bad_list to GC */
 	uint8_t resv_blocks_gcmerge;	/* ... merge pages when garbage collecting */
 
+
+	uint32_t resv_blocks_root;	/* How many extra eraseblocks are reserved for root */
+
 	uint32_t nospc_dirty_size;
 
 	uint32_t nr_blocks;
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -191,7 +191,7 @@ int jffs2_setattr(struct dentry *dentry,
 int jffs2_statfs(struct super_block *sb, struct kstatfs *buf)
 {
 	struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
-	unsigned long avail;
+	unsigned long avail, size;
 
 	buf->f_type = JFFS2_SUPER_MAGIC;
 	buf->f_bsize = 1 << PAGE_SHIFT;
@@ -202,8 +202,9 @@ int jffs2_statfs(struct super_block *sb,
 
 	spin_lock(&c->erase_completion_lock);
 	avail = c->dirty_size + c->free_size;
-	if (avail > c->sector_size * c->resv_blocks_write)
-		avail -= c->sector_size * c->resv_blocks_write;
+	size = c->sector_size * (c->resv_blocks_write + c->resv_blocks_root);
+	if (avail > size)
+		avail -= size;
 	else
 		avail = 0;
 	spin_unlock(&c->erase_completion_lock);
@@ -348,10 +349,16 @@ void jffs2_dirty_inode(struct inode *ino
 int jffs2_remount_fs (struct super_block *sb, int *flags, char *data)
 {
 	struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
+	int ret;
 
 	if (c->flags & JFFS2_SB_FLAG_RO && !(sb->s_flags & MS_RDONLY))
 		return -EROFS;
 
+	/* Re-parse mount options */
+	ret = jffs2_parse_options(sb, data);
+	if (ret)
+		return ret;
+
 	/* We stop if it was running, then restart if it needs to.
 	   This also catches the case where it was stopped and this
 	   is just a remount to restart it.
--- a/fs/jffs2/nodelist.h
+++ b/fs/jffs2/nodelist.h
@@ -400,6 +400,9 @@ int jffs2_do_mount_fs(struct jffs2_sb_in
 /* erase.c */
 void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count);
 
+/* super.c */
+int jffs2_parse_options(struct super_block *sb, char *opts);
+
 #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
 /* wbuf.c */
 int jffs2_flush_wbuf_gc(struct jffs2_sb_info *c, uint32_t ino);
--- a/fs/jffs2/nodemgmt.c
+++ b/fs/jffs2/nodemgmt.c
@@ -15,6 +15,7 @@
 #include <linux/slab.h>
 #include <linux/mtd/mtd.h>
 #include <linux/compiler.h>
+#include <linux/capability.h>
 #include <linux/sched.h> /* For cond_resched() */
 #include "nodelist.h"
 #include "debug.h"
@@ -47,6 +48,10 @@ int jffs2_reserve_space(struct jffs2_sb_
 {
 	int ret = -EAGAIN;
 	int blocksneeded = c->resv_blocks_write;
+
+	if (prio != ALLOC_DELETION && !capable(CAP_SYS_RESOURCE))
+		blocksneeded += c->resv_blocks_root;
+
 	/* align it */
 	minsize = PAD(minsize);
 
--- a/fs/jffs2/super.c
+++ b/fs/jffs2/super.c
@@ -24,10 +24,13 @@
 #include <linux/mtd/mtd.h>
 #include <linux/ctype.h>
 #include <linux/namei.h>
+#include <linux/parser.h>
+#include <linux/seq_file.h>
 #include "compr.h"
 #include "nodelist.h"
 
 static void jffs2_put_super(struct super_block *);
+static int jffs2_show_options(struct seq_file *m, struct vfsmount *mnt);
 
 static kmem_cache_t *jffs2_inode_cachep;
 
@@ -78,6 +81,7 @@ static struct super_operations jffs2_sup
 	.clear_inode =	jffs2_clear_inode,
 	.dirty_inode =	jffs2_dirty_inode,
 	.sync_fs =	jffs2_sync_fs,
+	.show_options = jffs2_show_options,
 };
 
 static int jffs2_sb_compare(struct super_block *sb, void *data)
@@ -152,14 +156,14 @@ static struct super_block *jffs2_get_sb_
 	sb->s_op = &jffs2_super_operations;
 	sb->s_flags = flags | MS_NOATIME;
 
-	ret = jffs2_do_fill_super(sb, data, flags & MS_SILENT ? 1 : 0);
-
-	if (ret) {
-		/* Failure case... */
-		up_write(&sb->s_umount);
-		deactivate_super(sb);
-		return ERR_PTR(ret);
-	}
+	/* Parse mount options */
+	ret = jffs2_parse_options(sb, data);
+	if (ret)
+		goto error;
+
+	ret = jffs2_do_fill_super(sb, data, flags & MS_SILENT ? 1 : 0);
+	if (ret)
+		goto error;
 
 	sb->s_flags |= MS_ACTIVE;
 	return sb;
@@ -169,6 +173,12 @@ static struct super_block *jffs2_get_sb_
 	put_mtd_device(mtd);
 
 	return sb;
+
+ error:
+	/* Failure case... */
+	up_write(&sb->s_umount);
+	deactivate_super(sb);
+	return ERR_PTR(ret);
 }
 
 static struct super_block *jffs2_get_sb_mtdnr(struct file_system_type *fs_type,
@@ -273,6 +283,72 @@ out:
 	return ERR_PTR(err);
 }
 
+/*
+ * Mount option identifiers.
+ */
+enum {
+	JFFS2_OPT_RP_SIZE,
+	JFFS2_OPT_LAST_FAKE
+};
+
+/*
+ * Supported mount options.
+ */
+static struct match_token tokens[] = {
+	{JFFS2_OPT_RP_SIZE, "rpsize=%u"}, /* Size of the reserved pool in KiB */
+	{JFFS2_OPT_LAST_FAKE, NULL}       /* End of list marker */
+};
+
+#define JFFS2_MAX_ARGS	1
+
+int jffs2_parse_options(struct super_block *sb, char *opts)
+{
+	unsigned int opt;
+	char *p;
+	substring_t args[JFFS2_MAX_ARGS];
+	struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
+
+	if (!opts)
+		return 0;
+
+	while ((p = strsep(&opts, ","))) {
+		int token;
+
+		if (!*p)
+			continue;
+
+		token = match_token(p, tokens, args);
+
+		switch (token) {
+		case JFFS2_OPT_RP_SIZE:
+			if (match_int(&args[0], &opt))
+				return -EINVAL;
+			opt = (opt + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+			if (opt > c->mtd->size/c->mtd->erasesize) {
+				printk(KERN_ERR "Reserved pool too large; max is %lu %uKiB blocks\n",
+				       c->mtd->size/PAGE_CACHE_SIZE, 1 << (PAGE_CACHE_SHIFT - 10));
+				return -EINVAL;
+			}
+			c->resv_blocks_root = opt;
+			break;
+		default:
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+static int jffs2_show_options(struct seq_file *m, struct vfsmount *mnt)
+{
+	struct jffs2_sb_info *c = JFFS2_SB_INFO(mnt->mnt_sb);
+
+	if (c->resv_blocks_root)
+		seq_printf(m, ",rpsize=%u", c->resv_blocks_root/c->sector_size);
+
+	return 0;
+}
+
 static void jffs2_put_super (struct super_block *sb)
 {
 	struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);

-- 
dwmw2

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH/RFC] reserved pool
  2006-05-16 23:30             ` David Woodhouse
  2006-05-16 23:31               ` David Woodhouse
@ 2006-05-17  6:49               ` Artem B. Bityutskiy
  2006-05-17  9:19                 ` David Woodhouse
  1 sibling, 1 reply; 11+ messages in thread
From: Artem B. Bityutskiy @ 2006-05-17  6:49 UTC (permalink / raw)
  To: David Woodhouse; +Cc: Jörn Engel, linux-mtd

David Woodhouse wrote:
> I cleaned it up so it looks like this.... and then decided not to apply
> it. I don't like this kind of thing being a mount option. Make a new
> node type for 'filesystem options'. Make it an RWCOMPAT_COPY node type.
> Store the reserved size in it and do it through an ioctl like chattr
> does on ext2 -- and make mkfs.jffs2 write it too. 
> 
> We'll want compression types stored in that node type too, I suspect.
Well, looks fair.

Note: you have trickily decided to kill two birds with one stone, 
exploiting me to add a superblock node facility to JFFS2.

-- 
Best Regards,
Artem B. Bityutskiy,
St.-Petersburg, Russia.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH/RFC] reserved pool
  2006-05-17  6:49               ` Artem B. Bityutskiy
@ 2006-05-17  9:19                 ` David Woodhouse
  0 siblings, 0 replies; 11+ messages in thread
From: David Woodhouse @ 2006-05-17  9:19 UTC (permalink / raw)
  To: Artem B. Bityutskiy; +Cc: Jörn Engel, linux-mtd

On Wed, 2006-05-17 at 10:49 +0400, Artem B. Bityutskiy wrote:
> Note: you have trickily decided to kill two birds with one stone, 
> exploiting me to add a superblock node facility to JFFS2.

Yes. That's how it works. You're trying to add a feature which really
ought to use such a 'superblock node', so you get to add that
functionality.

-- 
dwmw2

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2006-05-17  9:19 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-05-09 12:45 [PATCH/RFC] reserved pool Artem B. Bityutskiy
2006-05-10  8:29 ` Artem B. Bityutskiy
2006-05-10 13:35   ` Jörn Engel
2006-05-10 13:54     ` Artem B. Bityutskiy
2006-05-10 13:58       ` Jörn Engel
2006-05-14 19:39         ` David Woodhouse
2006-05-15 14:19           ` Artem B. Bityutskiy
2006-05-16 23:30             ` David Woodhouse
2006-05-16 23:31               ` David Woodhouse
2006-05-17  6:49               ` Artem B. Bityutskiy
2006-05-17  9:19                 ` David Woodhouse

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox