linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/7] affs: stop using write_supers and s_dirt
@ 2012-06-06 15:56 Artem Bityutskiy
  2012-06-06 15:56 ` [PATCH v2 1/7] affs: stop setting bm_flags Artem Bityutskiy
                   ` (6 more replies)
  0 siblings, 7 replies; 11+ messages in thread
From: Artem Bityutskiy @ 2012-06-06 15:56 UTC (permalink / raw)
  To: Al Viro, Jan Kara; +Cc: Linux FS Maling List, Linux Kernel Maling List

This is v2 of the patch-set. Please, see v1 for the high-level description.

v1->v2:
 Address review comments from Jan Kara:
 * use BH lock for locking the superblock while calculating its checksum;
 * stop setting bm_flags

v1: http://lkml.org/lkml/2012/6/5/162

 fs/affs/affs.h   |    7 +++++
 fs/affs/bitmap.c |    4 +-
 fs/affs/super.c  |   68 +++++++++++++++++++++++++++++++++++-------------------
 3 files changed, 53 insertions(+), 26 deletions(-)

Thanks,
Artem.

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

* [PATCH v2 1/7] affs: stop setting bm_flags
  2012-06-06 15:56 [PATCH v2 0/7] affs: stop using write_supers and s_dirt Artem Bityutskiy
@ 2012-06-06 15:56 ` Artem Bityutskiy
  2012-06-16 18:49   ` Geert Uytterhoeven
  2012-06-06 15:56 ` [PATCH v2 2/7] affs: remove useless superblock writeout on unmount Artem Bityutskiy
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 11+ messages in thread
From: Artem Bityutskiy @ 2012-06-06 15:56 UTC (permalink / raw)
  To: Al Viro, Jan Kara; +Cc: Linux FS Maling List, Linux Kernel Maling List

From: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>

AFFS stores values '1' and '2' in 'bm_flags', and I fail to see any logic when
it prefers one or another. AFFS writes '1' only from '->put_super()', while
'->sync_fs()' and '->write_super()' store value '2'.  So on the first glance,
it looks like we want to have '1' if we unmount.  However, this does not really
happen in these cases:
  1. superblock is written via 'write_super()' then we unmount;
  2. we re-mount R/O, then unmount.
which are quite typical.

I could not find good documentation describing this field, except of one random
piece of documentation in the internet which says that -1 means that the root
block is valid, which is not consistent with what we have in the Linux AFFS
driver.

Jan Kara commented on this: "I have some vague recollection that on Amiga
boolean was usually encoded as: 0 == false, ~0 == -1 == true. But it has been
ages..."

Thus, my conclusion is that value of '1' is as good as value of '2' and we can
just always use '2'. An Jan Kara suggested to go further: "generally bm_flags
handling looks strange. If they are 0, we mount fs read only and thus cannot
change them.  If they are != 0, we write 2 there. So IMHO if you just removed
bm_flags setting, nothing will really happen."

So this patch removes the bm_flags setting completely. This makes the "clean"
argument of the 'affs_commit_super()' function unneeded, so it is also removed.

Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
---
 fs/affs/super.c |    9 ++++-----
 1 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/fs/affs/super.c b/fs/affs/super.c
index 0782653..1d42e46 100644
--- a/fs/affs/super.c
+++ b/fs/affs/super.c
@@ -25,13 +25,12 @@ static int affs_statfs(struct dentry *dentry, struct kstatfs *buf);
 static int affs_remount (struct super_block *sb, int *flags, char *data);
 
 static void
-affs_commit_super(struct super_block *sb, int wait, int clean)
+affs_commit_super(struct super_block *sb, int wait)
 {
 	struct affs_sb_info *sbi = AFFS_SB(sb);
 	struct buffer_head *bh = sbi->s_root_bh;
 	struct affs_root_tail *tail = AFFS_ROOT_TAIL(sb, bh);
 
-	tail->bm_flag = cpu_to_be32(clean);
 	secs_to_datestamp(get_seconds(), &tail->disk_change);
 	affs_fix_checksum(sb, bh);
 	mark_buffer_dirty(bh);
@@ -46,7 +45,7 @@ affs_put_super(struct super_block *sb)
 	pr_debug("AFFS: put_super()\n");
 
 	if (!(sb->s_flags & MS_RDONLY) && sb->s_dirt)
-		affs_commit_super(sb, 1, 1);
+		affs_commit_super(sb, 1);
 
 	kfree(sbi->s_prefix);
 	affs_free_bitmap(sb);
@@ -60,7 +59,7 @@ affs_write_super(struct super_block *sb)
 {
 	lock_super(sb);
 	if (!(sb->s_flags & MS_RDONLY))
-		affs_commit_super(sb, 1, 2);
+		affs_commit_super(sb, 1);
 	sb->s_dirt = 0;
 	unlock_super(sb);
 
@@ -71,7 +70,7 @@ static int
 affs_sync_fs(struct super_block *sb, int wait)
 {
 	lock_super(sb);
-	affs_commit_super(sb, wait, 2);
+	affs_commit_super(sb, wait);
 	sb->s_dirt = 0;
 	unlock_super(sb);
 	return 0;
-- 
1.7.7.6


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

* [PATCH v2 2/7] affs: remove useless superblock writeout on unmount
  2012-06-06 15:56 [PATCH v2 0/7] affs: stop using write_supers and s_dirt Artem Bityutskiy
  2012-06-06 15:56 ` [PATCH v2 1/7] affs: stop setting bm_flags Artem Bityutskiy
@ 2012-06-06 15:56 ` Artem Bityutskiy
  2012-06-06 15:56 ` [PATCH v2 3/7] affs: remove useless superblock writeout on remount Artem Bityutskiy
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 11+ messages in thread
From: Artem Bityutskiy @ 2012-06-06 15:56 UTC (permalink / raw)
  To: Al Viro, Jan Kara; +Cc: Linux FS Maling List, Linux Kernel Maling List

From: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>

We do not need to write out the superblock from '->put_super()' because VFS has
already called '->sync_fs()' by this time and the superblock has already been
written out. Thus, remove the 'affs_commit_super()' infocation from
'affs_put_super()'.

Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
---
 fs/affs/super.c |    3 ---
 1 files changed, 0 insertions(+), 3 deletions(-)

diff --git a/fs/affs/super.c b/fs/affs/super.c
index 1d42e46..12b4f58 100644
--- a/fs/affs/super.c
+++ b/fs/affs/super.c
@@ -44,9 +44,6 @@ affs_put_super(struct super_block *sb)
 	struct affs_sb_info *sbi = AFFS_SB(sb);
 	pr_debug("AFFS: put_super()\n");
 
-	if (!(sb->s_flags & MS_RDONLY) && sb->s_dirt)
-		affs_commit_super(sb, 1);
-
 	kfree(sbi->s_prefix);
 	affs_free_bitmap(sb);
 	affs_brelse(sbi->s_root_bh);
-- 
1.7.7.6


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

* [PATCH v2 3/7] affs: remove useless superblock writeout on remount
  2012-06-06 15:56 [PATCH v2 0/7] affs: stop using write_supers and s_dirt Artem Bityutskiy
  2012-06-06 15:56 ` [PATCH v2 1/7] affs: stop setting bm_flags Artem Bityutskiy
  2012-06-06 15:56 ` [PATCH v2 2/7] affs: remove useless superblock writeout on unmount Artem Bityutskiy
@ 2012-06-06 15:56 ` Artem Bityutskiy
  2012-06-06 15:56 ` [PATCH v2 4/7] affs: re-structure superblock locking a bit Artem Bityutskiy
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 11+ messages in thread
From: Artem Bityutskiy @ 2012-06-06 15:56 UTC (permalink / raw)
  To: Al Viro, Jan Kara; +Cc: Linux FS Maling List, Linux Kernel Maling List

From: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>

We do not need to write out the superblock from '->remount_fs()' because
VFS has already called '->sync_fs()' by this time and the superblock has
already been written out. Thus, remove the 'affs_write_super()'
infocation from 'affs_remount()'.

Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
---
 fs/affs/super.c |    5 ++---
 1 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/fs/affs/super.c b/fs/affs/super.c
index 12b4f58..c837e43 100644
--- a/fs/affs/super.c
+++ b/fs/affs/super.c
@@ -545,10 +545,9 @@ affs_remount(struct super_block *sb, int *flags, char *data)
 	if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
 		return 0;
 
-	if (*flags & MS_RDONLY) {
-		affs_write_super(sb);
+	if (*flags & MS_RDONLY)
 		affs_free_bitmap(sb);
-	} else
+	else
 		res = affs_init_bitmap(sb, flags);
 
 	return res;
-- 
1.7.7.6


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

* [PATCH v2 4/7] affs: re-structure superblock locking a bit
  2012-06-06 15:56 [PATCH v2 0/7] affs: stop using write_supers and s_dirt Artem Bityutskiy
                   ` (2 preceding siblings ...)
  2012-06-06 15:56 ` [PATCH v2 3/7] affs: remove useless superblock writeout on remount Artem Bityutskiy
@ 2012-06-06 15:56 ` Artem Bityutskiy
  2012-06-06 15:56 ` [PATCH v2 5/7] affs: stop using lock_super Artem Bityutskiy
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 11+ messages in thread
From: Artem Bityutskiy @ 2012-06-06 15:56 UTC (permalink / raw)
  To: Al Viro, Jan Kara; +Cc: Linux FS Maling List, Linux Kernel Maling List

From: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>

AFFS wants to serialize the superblock (the root block in AFFS terms) updates
and uses 'lock_super()/unlock_super()' for these purposes. This patch pushes the
locking down to the 'affs_commit_super()' from the callers.

Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
---
 fs/affs/super.c |    7 ++-----
 1 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/fs/affs/super.c b/fs/affs/super.c
index c837e43..4ceec56 100644
--- a/fs/affs/super.c
+++ b/fs/affs/super.c
@@ -31,11 +31,13 @@ affs_commit_super(struct super_block *sb, int wait)
 	struct buffer_head *bh = sbi->s_root_bh;
 	struct affs_root_tail *tail = AFFS_ROOT_TAIL(sb, bh);
 
+	lock_super(sb);
 	secs_to_datestamp(get_seconds(), &tail->disk_change);
 	affs_fix_checksum(sb, bh);
 	mark_buffer_dirty(bh);
 	if (wait)
 		sync_dirty_buffer(bh);
+	unlock_super(sb);
 }
 
 static void
@@ -54,22 +56,17 @@ affs_put_super(struct super_block *sb)
 static void
 affs_write_super(struct super_block *sb)
 {
-	lock_super(sb);
 	if (!(sb->s_flags & MS_RDONLY))
 		affs_commit_super(sb, 1);
 	sb->s_dirt = 0;
-	unlock_super(sb);
-
 	pr_debug("AFFS: write_super() at %lu, clean=2\n", get_seconds());
 }
 
 static int
 affs_sync_fs(struct super_block *sb, int wait)
 {
-	lock_super(sb);
 	affs_commit_super(sb, wait);
 	sb->s_dirt = 0;
-	unlock_super(sb);
 	return 0;
 }
 
-- 
1.7.7.6


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

* [PATCH v2 5/7] affs: stop using lock_super
  2012-06-06 15:56 [PATCH v2 0/7] affs: stop using write_supers and s_dirt Artem Bityutskiy
                   ` (3 preceding siblings ...)
  2012-06-06 15:56 ` [PATCH v2 4/7] affs: re-structure superblock locking a bit Artem Bityutskiy
@ 2012-06-06 15:56 ` Artem Bityutskiy
  2012-06-06 15:56 ` [PATCH v2 6/7] affs: introduce VFS superblock object back-reference Artem Bityutskiy
  2012-06-06 15:56 ` [PATCH v2 7/7] affs: get rid of affs_sync_super Artem Bityutskiy
  6 siblings, 0 replies; 11+ messages in thread
From: Artem Bityutskiy @ 2012-06-06 15:56 UTC (permalink / raw)
  To: Al Viro, Jan Kara; +Cc: Linux FS Maling List, Linux Kernel Maling List

From: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>

The VFS's 'lock_super()' and 'unlock_super()' calls are deprecated and unwanted
and just wait for a brave knight who'd kill them. This patch makes AFFS stop
using them and use the buffer-head's own lock instead.

Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
---
 fs/affs/super.c |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/fs/affs/super.c b/fs/affs/super.c
index 4ceec56..da7498d 100644
--- a/fs/affs/super.c
+++ b/fs/affs/super.c
@@ -31,13 +31,14 @@ affs_commit_super(struct super_block *sb, int wait)
 	struct buffer_head *bh = sbi->s_root_bh;
 	struct affs_root_tail *tail = AFFS_ROOT_TAIL(sb, bh);
 
-	lock_super(sb);
+	lock_buffer(bh);
 	secs_to_datestamp(get_seconds(), &tail->disk_change);
 	affs_fix_checksum(sb, bh);
+	unlock_buffer(bh);
+
 	mark_buffer_dirty(bh);
 	if (wait)
 		sync_dirty_buffer(bh);
-	unlock_super(sb);
 }
 
 static void
-- 
1.7.7.6


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

* [PATCH v2 6/7] affs: introduce VFS superblock object back-reference
  2012-06-06 15:56 [PATCH v2 0/7] affs: stop using write_supers and s_dirt Artem Bityutskiy
                   ` (4 preceding siblings ...)
  2012-06-06 15:56 ` [PATCH v2 5/7] affs: stop using lock_super Artem Bityutskiy
@ 2012-06-06 15:56 ` Artem Bityutskiy
  2012-06-06 15:56 ` [PATCH v2 7/7] affs: get rid of affs_sync_super Artem Bityutskiy
  6 siblings, 0 replies; 11+ messages in thread
From: Artem Bityutskiy @ 2012-06-06 15:56 UTC (permalink / raw)
  To: Al Viro, Jan Kara; +Cc: Linux FS Maling List, Linux Kernel Maling List

From: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>

Add an 'sb' VFS superblock back-reference to the 'struct affs_sb_info' data
structure - we will need to find the VFS superblock from a 'struct
affs_sb_info' object in the next patch, so this change is jut a preparation.

Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
---
 fs/affs/affs.h  |    1 +
 fs/affs/super.c |    1 +
 2 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/fs/affs/affs.h b/fs/affs/affs.h
index 1fceb32..5a726e9 100644
--- a/fs/affs/affs.h
+++ b/fs/affs/affs.h
@@ -100,6 +100,7 @@ struct affs_sb_info {
 	char *s_prefix;			/* Prefix for volumes and assigns. */
 	char s_volume[32];		/* Volume prefix for absolute symlinks. */
 	spinlock_t symlink_lock;	/* protects the previous two */
+	struct super_block *sb;		/* the VFS superblock object */
 };
 
 #define SF_INTL		0x0001		/* International filesystem. */
diff --git a/fs/affs/super.c b/fs/affs/super.c
index da7498d..0496cbb 100644
--- a/fs/affs/super.c
+++ b/fs/affs/super.c
@@ -299,6 +299,7 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent)
 		return -ENOMEM;
 
 	sb->s_fs_info = sbi;
+	sbi->sb = sb;
 	mutex_init(&sbi->s_bmlock);
 	spin_lock_init(&sbi->symlink_lock);
 
-- 
1.7.7.6


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

* [PATCH v2 7/7] affs: get rid of affs_sync_super
  2012-06-06 15:56 [PATCH v2 0/7] affs: stop using write_supers and s_dirt Artem Bityutskiy
                   ` (5 preceding siblings ...)
  2012-06-06 15:56 ` [PATCH v2 6/7] affs: introduce VFS superblock object back-reference Artem Bityutskiy
@ 2012-06-06 15:56 ` Artem Bityutskiy
  2012-07-02 14:06   ` Artem Bityutskiy
  6 siblings, 1 reply; 11+ messages in thread
From: Artem Bityutskiy @ 2012-06-06 15:56 UTC (permalink / raw)
  To: Al Viro, Jan Kara; +Cc: Linux FS Maling List, Linux Kernel Maling List

From: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>

This patch makes affs stop using the VFS '->write_super()' method along with
the 's_dirt' superblock flag, because they are on their way out.

The whole "superblock write-out" VFS infrastructure is served by the
'sync_supers()' kernel thread, which wakes up every 5 (by default) seconds and
writes out all dirty superblocks using the '->write_super()' call-back.  But the
problem with this thread is that it wastes power by waking up the system every
5 seconds, even if there are no diry superblocks, or there are no client
file-systems which would need this (e.g., btrfs does not use
'->write_super()'). So we want to kill it completely and thus, we need to make
file-systems to stop using the '->write_super()' VFS service, and then remove
it together with the kernel thread.

Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
---
 fs/affs/affs.h   |    6 ++++++
 fs/affs/bitmap.c |    4 ++--
 fs/affs/super.c  |   48 +++++++++++++++++++++++++++++++++++++-----------
 3 files changed, 45 insertions(+), 13 deletions(-)

diff --git a/fs/affs/affs.h b/fs/affs/affs.h
index 5a726e9..3a130e2 100644
--- a/fs/affs/affs.h
+++ b/fs/affs/affs.h
@@ -3,6 +3,7 @@
 #include <linux/buffer_head.h>
 #include <linux/amigaffs.h>
 #include <linux/mutex.h>
+#include <linux/workqueue.h>
 
 /* AmigaOS allows file names with up to 30 characters length.
  * Names longer than that will be silently truncated. If you
@@ -101,6 +102,9 @@ struct affs_sb_info {
 	char s_volume[32];		/* Volume prefix for absolute symlinks. */
 	spinlock_t symlink_lock;	/* protects the previous two */
 	struct super_block *sb;		/* the VFS superblock object */
+	int work_queued;		/* non-zero delayed work is queued */
+	struct delayed_work sb_work;	/* superblock flush delayed work */
+	spinlock_t work_lock;		/* protects sb_work and work_queued */
 };
 
 #define SF_INTL		0x0001		/* International filesystem. */
@@ -121,6 +125,8 @@ static inline struct affs_sb_info *AFFS_SB(struct super_block *sb)
 	return sb->s_fs_info;
 }
 
+void affs_mark_sb_dirty(struct super_block *sb);
+
 /* amigaffs.c */
 
 extern int	affs_insert_hash(struct inode *inode, struct buffer_head *bh);
diff --git a/fs/affs/bitmap.c b/fs/affs/bitmap.c
index 3e26271..6e0be43 100644
--- a/fs/affs/bitmap.c
+++ b/fs/affs/bitmap.c
@@ -103,7 +103,7 @@ affs_free_block(struct super_block *sb, u32 block)
 	*(__be32 *)bh->b_data = cpu_to_be32(tmp - mask);
 
 	mark_buffer_dirty(bh);
-	sb->s_dirt = 1;
+	affs_mark_sb_dirty(sb);
 	bm->bm_free++;
 
 	mutex_unlock(&sbi->s_bmlock);
@@ -248,7 +248,7 @@ find_bit:
 	*(__be32 *)bh->b_data = cpu_to_be32(tmp + mask);
 
 	mark_buffer_dirty(bh);
-	sb->s_dirt = 1;
+	affs_mark_sb_dirty(sb);
 
 	mutex_unlock(&sbi->s_bmlock);
 
diff --git a/fs/affs/super.c b/fs/affs/super.c
index 0496cbb..c70f1e5 100644
--- a/fs/affs/super.c
+++ b/fs/affs/super.c
@@ -17,6 +17,7 @@
 #include <linux/magic.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
+#include <linux/writeback.h>
 #include "affs.h"
 
 extern struct timezone sys_tz;
@@ -47,6 +48,7 @@ affs_put_super(struct super_block *sb)
 	struct affs_sb_info *sbi = AFFS_SB(sb);
 	pr_debug("AFFS: put_super()\n");
 
+	cancel_delayed_work_sync(&sbi->sb_work);
 	kfree(sbi->s_prefix);
 	affs_free_bitmap(sb);
 	affs_brelse(sbi->s_root_bh);
@@ -54,23 +56,45 @@ affs_put_super(struct super_block *sb)
 	sb->s_fs_info = NULL;
 }
 
-static void
-affs_write_super(struct super_block *sb)
-{
-	if (!(sb->s_flags & MS_RDONLY))
-		affs_commit_super(sb, 1);
-	sb->s_dirt = 0;
-	pr_debug("AFFS: write_super() at %lu, clean=2\n", get_seconds());
-}
-
 static int
 affs_sync_fs(struct super_block *sb, int wait)
 {
 	affs_commit_super(sb, wait);
-	sb->s_dirt = 0;
 	return 0;
 }
 
+static void flush_superblock(struct work_struct *work)
+{
+	struct affs_sb_info *sbi;
+	struct super_block *sb;
+
+	sbi = container_of(work, struct affs_sb_info, sb_work.work);
+	sb = sbi->sb;
+
+	spin_lock(&sbi->work_lock);
+	sbi->work_queued = 0;
+	spin_unlock(&sbi->work_lock);
+
+	affs_commit_super(sb, 1);
+}
+
+void affs_mark_sb_dirty(struct super_block *sb)
+{
+	struct affs_sb_info *sbi = AFFS_SB(sb);
+	unsigned long delay;
+
+	if (sb->s_flags & MS_RDONLY)
+	       return;
+
+	spin_lock(&sbi->work_lock);
+	if (!sbi->work_queued) {
+	       delay = msecs_to_jiffies(dirty_writeback_interval * 10);
+	       queue_delayed_work(system_long_wq, &sbi->sb_work, delay);
+	       sbi->work_queued = 1;
+	}
+	spin_unlock(&sbi->work_lock);
+}
+
 static struct kmem_cache * affs_inode_cachep;
 
 static struct inode *affs_alloc_inode(struct super_block *sb)
@@ -132,7 +156,6 @@ static const struct super_operations affs_sops = {
 	.write_inode	= affs_write_inode,
 	.evict_inode	= affs_evict_inode,
 	.put_super	= affs_put_super,
-	.write_super	= affs_write_super,
 	.sync_fs	= affs_sync_fs,
 	.statfs		= affs_statfs,
 	.remount_fs	= affs_remount,
@@ -302,6 +325,8 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent)
 	sbi->sb = sb;
 	mutex_init(&sbi->s_bmlock);
 	spin_lock_init(&sbi->symlink_lock);
+	spin_lock_init(&sbi->work_lock);
+	INIT_DELAYED_WORK(&sbi->sb_work, flush_superblock);
 
 	if (!parse_options(data,&uid,&gid,&i,&reserved,&root_block,
 				&blocksize,&sbi->s_prefix,
@@ -526,6 +551,7 @@ affs_remount(struct super_block *sb, int *flags, char *data)
 		return -EINVAL;
 	}
 
+	flush_delayed_work_sync(&sbi->sb_work);
 	replace_mount_options(sb, new_opts);
 
 	sbi->s_flags = mount_flags;
-- 
1.7.7.6


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

* Re: [PATCH v2 1/7] affs: stop setting bm_flags
  2012-06-06 15:56 ` [PATCH v2 1/7] affs: stop setting bm_flags Artem Bityutskiy
@ 2012-06-16 18:49   ` Geert Uytterhoeven
  2012-06-27  9:18     ` Artem Bityutskiy
  0 siblings, 1 reply; 11+ messages in thread
From: Geert Uytterhoeven @ 2012-06-16 18:49 UTC (permalink / raw)
  To: Artem Bityutskiy
  Cc: Al Viro, Jan Kara, Linux FS Maling List,
	Linux Kernel Maling List, Linux/m68k

On Wed, Jun 6, 2012 at 5:56 PM, Artem Bityutskiy <dedekind1@gmail.com> wrote:
> From: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
>
> AFFS stores values '1' and '2' in 'bm_flags', and I fail to see any logic when
> it prefers one or another. AFFS writes '1' only from '->put_super()', while
> '->sync_fs()' and '->write_super()' store value '2'.  So on the first glance,
> it looks like we want to have '1' if we unmount.  However, this does not really
> happen in these cases:
>  1. superblock is written via 'write_super()' then we unmount;
>  2. we re-mount R/O, then unmount.
> which are quite typical.
>
> I could not find good documentation describing this field, except of one random
> piece of documentation in the internet which says that -1 means that the root
> block is valid, which is not consistent with what we have in the Linux AFFS
> driver.

The book "Amiga Intern" (German version on the 'net, which is faster to access
than the Dutch version somewhere in my attic ;-) agrees with this ("Dieses Flag
enthält -1 (TRUE), wenn die Bit-Map der Diskette gültig ist").

I checked some file systems I had lying around, and they all have 0xffffffff in
bm_flag (byte offset 0x138 in the block at the middle of the file system).
At bit to my surprise, as I expected two of them (very old backups of file
systems) to have been written to from Linux at least once, but of course I can
be mistaken, and never have trusted Linux's affs with them ;-).
Mounting (copies of) them on Ubuntu and writing to them changes this flag to 1.

After digging in the affs sources, it seems we had this behavior since at least
2.0.29 (which is 1997 or so), so I think it's safe to assume it's been like that
forever.

> Jan Kara commented on this: "I have some vague recollection that on Amiga
> boolean was usually encoded as: 0 == false, ~0 == -1 == true. But it has been
> ages..."

include/exec/types.h:

#define TRUE            1
#define FALSE           0

However, include/dos/dos.h:

#define DOSTRUE (-1L)
#define DOSFALSE (0L)

So AmigaOS will probably always use 0xffffffff.

> Thus, my conclusion is that value of '1' is as good as value of '2' and we can
> just always use '2'. An Jan Kara suggested to go further: "generally bm_flags
> handling looks strange. If they are 0, we mount fs read only and thus cannot
> change them.  If they are != 0, we write 2 there. So IMHO if you just removed
> bm_flags setting, nothing will really happen."

As no one ever complained, 1 or 2 or whatever non-zero value probably doesn't
matter at all to AmigaOS.

> So this patch removes the bm_flags setting completely. This makes the "clean"
> argument of the 'affs_commit_super()' function unneeded, so it is also removed.
>
> Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
> ---
>  fs/affs/super.c |    9 ++++-----
>  1 files changed, 4 insertions(+), 5 deletions(-)
>
> diff --git a/fs/affs/super.c b/fs/affs/super.c
> index 0782653..1d42e46 100644
> --- a/fs/affs/super.c
> +++ b/fs/affs/super.c
> @@ -25,13 +25,12 @@ static int affs_statfs(struct dentry *dentry, struct kstatfs *buf);
>  static int affs_remount (struct super_block *sb, int *flags, char *data);
>
>  static void
> -affs_commit_super(struct super_block *sb, int wait, int clean)
> +affs_commit_super(struct super_block *sb, int wait)
>  {
>        struct affs_sb_info *sbi = AFFS_SB(sb);
>        struct buffer_head *bh = sbi->s_root_bh;
>        struct affs_root_tail *tail = AFFS_ROOT_TAIL(sb, bh);
>
> -       tail->bm_flag = cpu_to_be32(clean);
>        secs_to_datestamp(get_seconds(), &tail->disk_change);
>        affs_fix_checksum(sb, bh);
>        mark_buffer_dirty(bh);
> @@ -46,7 +45,7 @@ affs_put_super(struct super_block *sb)
>        pr_debug("AFFS: put_super()\n");
>
>        if (!(sb->s_flags & MS_RDONLY) && sb->s_dirt)
> -               affs_commit_super(sb, 1, 1);
> +               affs_commit_super(sb, 1);
>
>        kfree(sbi->s_prefix);
>        affs_free_bitmap(sb);
> @@ -60,7 +59,7 @@ affs_write_super(struct super_block *sb)
>  {
>        lock_super(sb);
>        if (!(sb->s_flags & MS_RDONLY))
> -               affs_commit_super(sb, 1, 2);
> +               affs_commit_super(sb, 1);
>        sb->s_dirt = 0;
>        unlock_super(sb);
>
> @@ -71,7 +70,7 @@ static int
>  affs_sync_fs(struct super_block *sb, int wait)
>  {
>        lock_super(sb);
> -       affs_commit_super(sb, wait, 2);
> +       affs_commit_super(sb, wait);
>        sb->s_dirt = 0;
>        unlock_super(sb);
>        return 0;
> --
> 1.7.7.6

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

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

* Re: [PATCH v2 1/7] affs: stop setting bm_flags
  2012-06-16 18:49   ` Geert Uytterhoeven
@ 2012-06-27  9:18     ` Artem Bityutskiy
  0 siblings, 0 replies; 11+ messages in thread
From: Artem Bityutskiy @ 2012-06-27  9:18 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Al Viro, Jan Kara, Linux FS Maling List,
	Linux Kernel Maling List, Linux/m68k

[-- Attachment #1: Type: text/plain, Size: 633 bytes --]

On Sat, 2012-06-16 at 20:49 +0200, Geert Uytterhoeven wrote:
> > I could not find good documentation describing this field, except of one random
> > piece of documentation in the internet which says that -1 means that the root
> > block is valid, which is not consistent with what we have in the Linux AFFS
> > driver.
> 
> The book "Amiga Intern" (German version on the 'net, which is faster to access
> than the Dutch version somewhere in my attic ;-) agrees with this ("Dieses Flag
> enthält -1 (TRUE), wenn die Bit-Map der Diskette gültig ist").

Thangs Geert for confirming.

-- 
Best Regards,
Artem Bityutskiy

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: [PATCH v2 7/7] affs: get rid of affs_sync_super
  2012-06-06 15:56 ` [PATCH v2 7/7] affs: get rid of affs_sync_super Artem Bityutskiy
@ 2012-07-02 14:06   ` Artem Bityutskiy
  0 siblings, 0 replies; 11+ messages in thread
From: Artem Bityutskiy @ 2012-07-02 14:06 UTC (permalink / raw)
  To: Al Viro; +Cc: Jan Kara, Linux FS Maling List, Linux Kernel Maling List

[-- Attachment #1: Type: text/plain, Size: 6331 bytes --]

From: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Date: Tue, 5 Jun 2012 13:30:44 +0300
Subject: [PATCH v2 13/23] affs: get rid of affs_sync_super

This patch makes affs stop using the VFS '->write_super()' method along with
the 's_dirt' superblock flag, because they are on their way out.

The whole "superblock write-out" VFS infrastructure is served by the
'sync_supers()' kernel thread, which wakes up every 5 (by default) seconds and
writes out all dirty superblocks using the '->write_super()' call-back.  But the
problem with this thread is that it wastes power by waking up the system every
5 seconds, even if there are no diry superblocks, or there are no client
file-systems which would need this (e.g., btrfs does not use
'->write_super()'). So we want to kill it completely and thus, we need to make
file-systems to stop using the '->write_super()' VFS service, and then remove
it together with the kernel thread.

Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
---
 fs/affs/affs.h   |    6 ++++++
 fs/affs/bitmap.c |    4 ++--
 fs/affs/super.c  |   48 +++++++++++++++++++++++++++++++++++++-----------
 3 files changed, 45 insertions(+), 13 deletions(-)

|This is patch is the same except that it fixes several white-space
|issues. If you plrefer an incremental patch, please, let me know. The
|issues are:
|
|WARNING:SUSPECT_CODE_INDENT: suspect code indent for conditional statements (8, 15)
|#140: FILE: fs/affs/super.c:86:
|+       if (sb->s_flags & MS_RDONLY)
|+              return;
|
|WARNING:SUSPECT_CODE_INDENT: suspect code indent for conditional statements (8, 15)
|#144: FILE: fs/affs/super.c:90:
|+       if (!sbi->work_queued) {
|+              delay = msecs_to_jiffies(dirty_writeback_interval * 10);

diff --git a/fs/affs/affs.h b/fs/affs/affs.h
index 5a726e9..3a130e2 100644
--- a/fs/affs/affs.h
+++ b/fs/affs/affs.h
@@ -3,6 +3,7 @@
 #include <linux/buffer_head.h>
 #include <linux/amigaffs.h>
 #include <linux/mutex.h>
+#include <linux/workqueue.h>
 
 /* AmigaOS allows file names with up to 30 characters length.
  * Names longer than that will be silently truncated. If you
@@ -101,6 +102,9 @@ struct affs_sb_info {
 	char s_volume[32];		/* Volume prefix for absolute symlinks. */
 	spinlock_t symlink_lock;	/* protects the previous two */
 	struct super_block *sb;		/* the VFS superblock object */
+	int work_queued;		/* non-zero delayed work is queued */
+	struct delayed_work sb_work;	/* superblock flush delayed work */
+	spinlock_t work_lock;		/* protects sb_work and work_queued */
 };
 
 #define SF_INTL		0x0001		/* International filesystem. */
@@ -121,6 +125,8 @@ static inline struct affs_sb_info *AFFS_SB(struct super_block *sb)
 	return sb->s_fs_info;
 }
 
+void affs_mark_sb_dirty(struct super_block *sb);
+
 /* amigaffs.c */
 
 extern int	affs_insert_hash(struct inode *inode, struct buffer_head *bh);
diff --git a/fs/affs/bitmap.c b/fs/affs/bitmap.c
index 3e26271..6e0be43 100644
--- a/fs/affs/bitmap.c
+++ b/fs/affs/bitmap.c
@@ -103,7 +103,7 @@ affs_free_block(struct super_block *sb, u32 block)
 	*(__be32 *)bh->b_data = cpu_to_be32(tmp - mask);
 
 	mark_buffer_dirty(bh);
-	sb->s_dirt = 1;
+	affs_mark_sb_dirty(sb);
 	bm->bm_free++;
 
 	mutex_unlock(&sbi->s_bmlock);
@@ -248,7 +248,7 @@ find_bit:
 	*(__be32 *)bh->b_data = cpu_to_be32(tmp + mask);
 
 	mark_buffer_dirty(bh);
-	sb->s_dirt = 1;
+	affs_mark_sb_dirty(sb);
 
 	mutex_unlock(&sbi->s_bmlock);
 
diff --git a/fs/affs/super.c b/fs/affs/super.c
index 0496cbb..c70f1e5 100644
--- a/fs/affs/super.c
+++ b/fs/affs/super.c
@@ -17,6 +17,7 @@
 #include <linux/magic.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
+#include <linux/writeback.h>
 #include "affs.h"
 
 extern struct timezone sys_tz;
@@ -47,6 +48,7 @@ affs_put_super(struct super_block *sb)
 	struct affs_sb_info *sbi = AFFS_SB(sb);
 	pr_debug("AFFS: put_super()\n");
 
+	cancel_delayed_work_sync(&sbi->sb_work);
 	kfree(sbi->s_prefix);
 	affs_free_bitmap(sb);
 	affs_brelse(sbi->s_root_bh);
@@ -54,23 +56,45 @@ affs_put_super(struct super_block *sb)
 	sb->s_fs_info = NULL;
 }
 
-static void
-affs_write_super(struct super_block *sb)
-{
-	if (!(sb->s_flags & MS_RDONLY))
-		affs_commit_super(sb, 1);
-	sb->s_dirt = 0;
-	pr_debug("AFFS: write_super() at %lu, clean=2\n", get_seconds());
-}
-
 static int
 affs_sync_fs(struct super_block *sb, int wait)
 {
 	affs_commit_super(sb, wait);
-	sb->s_dirt = 0;
 	return 0;
 }
 
+static void flush_superblock(struct work_struct *work)
+{
+	struct affs_sb_info *sbi;
+	struct super_block *sb;
+
+	sbi = container_of(work, struct affs_sb_info, sb_work.work);
+	sb = sbi->sb;
+
+	spin_lock(&sbi->work_lock);
+	sbi->work_queued = 0;
+	spin_unlock(&sbi->work_lock);
+
+	affs_commit_super(sb, 1);
+}
+
+void affs_mark_sb_dirty(struct super_block *sb)
+{
+	struct affs_sb_info *sbi = AFFS_SB(sb);
+	unsigned long delay;
+
+	if (sb->s_flags & MS_RDONLY)
+		return;
+
+	spin_lock(&sbi->work_lock);
+	if (!sbi->work_queued) {
+		delay = msecs_to_jiffies(dirty_writeback_interval * 10);
+		queue_delayed_work(system_long_wq, &sbi->sb_work, delay);
+		sbi->work_queued = 1;
+	}
+	spin_unlock(&sbi->work_lock);
+}
+
 static struct kmem_cache * affs_inode_cachep;
 
 static struct inode *affs_alloc_inode(struct super_block *sb)
@@ -132,7 +156,6 @@ static const struct super_operations affs_sops = {
 	.write_inode	= affs_write_inode,
 	.evict_inode	= affs_evict_inode,
 	.put_super	= affs_put_super,
-	.write_super	= affs_write_super,
 	.sync_fs	= affs_sync_fs,
 	.statfs		= affs_statfs,
 	.remount_fs	= affs_remount,
@@ -302,6 +325,8 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent)
 	sbi->sb = sb;
 	mutex_init(&sbi->s_bmlock);
 	spin_lock_init(&sbi->symlink_lock);
+	spin_lock_init(&sbi->work_lock);
+	INIT_DELAYED_WORK(&sbi->sb_work, flush_superblock);
 
 	if (!parse_options(data,&uid,&gid,&i,&reserved,&root_block,
 				&blocksize,&sbi->s_prefix,
@@ -526,6 +551,7 @@ affs_remount(struct super_block *sb, int *flags, char *data)
 		return -EINVAL;
 	}
 
+	flush_delayed_work_sync(&sbi->sb_work);
 	replace_mount_options(sb, new_opts);
 
 	sbi->s_flags = mount_flags;
-- 
1.7.10

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

end of thread, other threads:[~2012-07-02 14:02 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-06-06 15:56 [PATCH v2 0/7] affs: stop using write_supers and s_dirt Artem Bityutskiy
2012-06-06 15:56 ` [PATCH v2 1/7] affs: stop setting bm_flags Artem Bityutskiy
2012-06-16 18:49   ` Geert Uytterhoeven
2012-06-27  9:18     ` Artem Bityutskiy
2012-06-06 15:56 ` [PATCH v2 2/7] affs: remove useless superblock writeout on unmount Artem Bityutskiy
2012-06-06 15:56 ` [PATCH v2 3/7] affs: remove useless superblock writeout on remount Artem Bityutskiy
2012-06-06 15:56 ` [PATCH v2 4/7] affs: re-structure superblock locking a bit Artem Bityutskiy
2012-06-06 15:56 ` [PATCH v2 5/7] affs: stop using lock_super Artem Bityutskiy
2012-06-06 15:56 ` [PATCH v2 6/7] affs: introduce VFS superblock object back-reference Artem Bityutskiy
2012-06-06 15:56 ` [PATCH v2 7/7] affs: get rid of affs_sync_super Artem Bityutskiy
2012-07-02 14:06   ` Artem Bityutskiy

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).