lkml.org 
[lkml]   [2010]   [Jun]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCHv5 04/16] VFS: add memory barrier to sb_mark_clean and sb_mark_dirty
Date
From: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>

The proper way for file-systems to synchronize the superblock
should be as follows:

1. when modifying the SB, first modify it, then mark it as dirty;
2. when synchronizing the SB, first mark as clean, then start
synchronizing.

And to make ensure the order, we need memory barriers in 'sb_mark_clean()'
and 'sb_mark_dirty()'.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
---
include/linux/fs.h | 14 ++++++++++++++
mm/backing-dev.c | 5 +++++
2 files changed, 19 insertions(+), 0 deletions(-)

diff --git a/include/linux/fs.h b/include/linux/fs.h
index ca1e993..3acaccf 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1783,10 +1783,24 @@ extern int get_sb_pseudo(struct file_system_type *, char *,
struct vfsmount *mnt);
extern void simple_set_mnt(struct vfsmount *mnt, struct super_block *sb);

+/*
+ * The SB clean/dirty state manipulations should be done as follows:
+ * 1. modification: first modify the SB-related data, then mark the SB as
+ * dirty;
+ * 2. synchronization: first mark the SB as clean, then start synchronizing it.
+ *
+ * This order makes sure that races are harmless and we never end up in a
+ * situation when the SB is modified but is nevertheless marked as clean.
+ */
void sb_mark_dirty(struct super_block *sb);
static inline void sb_mark_clean(struct super_block *sb)
{
sb->s_dirty = 0;
+ /*
+ * Normally FSes first unset the sb->s_dirty flag, and then start
+ * synchronizing the SB. The memory barrier ensures this order.
+ */
+ smp_mb();
}
static inline int sb_is_dirty(struct super_block *sb)
{
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index d751284..d861bd4 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -352,6 +352,11 @@ static void bdi_flush_io(struct backing_dev_info *bdi)

void sb_mark_dirty(struct super_block *sb)
{
+ /*
+ * Normally FSes modify the SB, and then mark it as dirty. The memory
+ * barrier ensures this order.
+ */
+ smp_mb();
sb->s_dirty = 1;
/*
* sb->s_dirty store must be visible to sync_supers before we load
--
1.7.0.1


\
 
 \ /
  Last update: 2010-06-06 16:59    [W:0.880 / U:0.652 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site