linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/3] fsfreeze: wait in killable state in __sb_start_write
@ 2013-04-13 10:35 Marco Stornelli
  2013-04-15 11:57 ` Jan Kara
  0 siblings, 1 reply; 3+ messages in thread
From: Marco Stornelli @ 2013-04-13 10:35 UTC (permalink / raw)
  To: Linux FS Devel; +Cc: Linux Kernel, Jan Kara, Al Viro

Added a new enum to decide if we want to sleep in uninterruptible or
killable state or we want simply to return immediately.

Signed-off-by: Marco Stornelli <marco.stornelli@gmail.com>
---
 fs/super.c         |   24 ++++++++++++++++++------
 include/linux/fs.h |   19 +++++++++++++------
 2 files changed, 31 insertions(+), 12 deletions(-)

diff --git a/fs/super.c b/fs/super.c
index 7465d43..6b70c7f 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -1190,14 +1190,25 @@ static void acquire_freeze_lock(struct super_block *sb, int level, bool trylock,
  * This is an internal function, please use sb_start_{write,pagefault,intwrite}
  * instead.
  */
-int __sb_start_write(struct super_block *sb, int level, bool wait)
+int __sb_start_write(struct super_block *sb, int level, int wait)
 {
+	int ret = 0;
 retry:
 	if (unlikely(sb->s_writers.frozen >= level)) {
-		if (!wait)
-			return 0;
-		wait_event(sb->s_writers.wait_unfrozen,
-			   sb->s_writers.frozen < level);
+		switch (wait) {
+		case FREEZE_NOWAIT:
+			return ret;
+		case FREEZE_WAIT:
+			wait_event(sb->s_writers.wait_unfrozen,
+				   sb->s_writers.frozen < level);
+			break;
+		case FREEZE_WAIT_KILLABLE:
+			ret = wait_event_killable(sb->s_writers.wait_unfrozen,
+				   sb->s_writers.frozen < level);
+			if (ret)
+				return -EINTR;
+			break;
+		}
 	}
 
 #ifdef CONFIG_LOCKDEP
@@ -1213,7 +1224,8 @@ retry:
 		__sb_end_write(sb, level);
 		goto retry;
 	}
-	return 1;
+	ret = 1;
+	return ret;
 }
 EXPORT_SYMBOL(__sb_start_write);
 
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 8d47c9a..c8b7325 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1220,6 +1220,13 @@ enum {
 
 #define SB_FREEZE_LEVELS (SB_FREEZE_COMPLETE - 1)
 
+/* Possible waiting modes */
+enum {
+	FREEZE_NOWAIT = 0,		/* no blocking call */
+	FREEZE_WAIT	= 1,		/* wait in uninterruptible state */
+	FREEZE_WAIT_KILLABLE = 2,	/* wait in killable state */
+};
+
 struct sb_writers {
 	/* Counters for counting writers at each level */
 	struct percpu_counter	counter[SB_FREEZE_LEVELS];
@@ -1335,7 +1342,7 @@ extern struct timespec current_fs_time(struct super_block *sb);
  */
 
 void __sb_end_write(struct super_block *sb, int level);
-int __sb_start_write(struct super_block *sb, int level, bool wait);
+int __sb_start_write(struct super_block *sb, int level, int wait);
 
 /**
  * sb_end_write - drop write access to a superblock
@@ -1394,12 +1401,12 @@ static inline void sb_end_intwrite(struct super_block *sb)
  */
 static inline void sb_start_write(struct super_block *sb)
 {
-	__sb_start_write(sb, SB_FREEZE_WRITE, true);
+	__sb_start_write(sb, SB_FREEZE_WRITE, FREEZE_WAIT);
 }
 
 static inline int sb_start_write_trylock(struct super_block *sb)
 {
-	return __sb_start_write(sb, SB_FREEZE_WRITE, false);
+	return __sb_start_write(sb, SB_FREEZE_WRITE, FREEZE_NOWAIT);
 }
 
 /**
@@ -1423,7 +1430,7 @@ static inline int sb_start_write_trylock(struct super_block *sb)
  */
 static inline void sb_start_pagefault(struct super_block *sb)
 {
-	__sb_start_write(sb, SB_FREEZE_PAGEFAULT, true);
+	__sb_start_write(sb, SB_FREEZE_PAGEFAULT, FREEZE_WAIT);
 }
 
 /*
@@ -1441,7 +1448,7 @@ static inline void sb_start_pagefault(struct super_block *sb)
  */
 static inline void sb_start_intwrite(struct super_block *sb)
 {
-	__sb_start_write(sb, SB_FREEZE_FS, true);
+	__sb_start_write(sb, SB_FREEZE_FS, FREEZE_WAIT);
 }
 
 
@@ -2224,7 +2231,7 @@ static inline void file_start_write(struct file *file)
 {
 	if (!S_ISREG(file_inode(file)->i_mode))
 		return;
-	__sb_start_write(file_inode(file)->i_sb, SB_FREEZE_WRITE, true);
+	__sb_start_write(file_inode(file)->i_sb, SB_FREEZE_WRITE, FREEZE_WAIT);
 }
 
 static inline void file_end_write(struct file *file)
-- 
1.7.3.4

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

* Re: [PATCH 1/3] fsfreeze: wait in killable state in __sb_start_write
  2013-04-13 10:35 [PATCH 1/3] fsfreeze: wait in killable state in __sb_start_write Marco Stornelli
@ 2013-04-15 11:57 ` Jan Kara
       [not found]   ` <CANGUGtD67qdQyokqbaUHC0FW115udEwd8VJj6j+z5Puzjkbpxg@mail.gmail.com>
  0 siblings, 1 reply; 3+ messages in thread
From: Jan Kara @ 2013-04-15 11:57 UTC (permalink / raw)
  To: Marco Stornelli; +Cc: Linux FS Devel, Linux Kernel, Jan Kara, Al Viro

On Sat 13-04-13 12:35:54, Marco Stornelli wrote:
> Added a new enum to decide if we want to sleep in uninterruptible or
> killable state or we want simply to return immediately.
  I like the patch. You can add:
Reviewed-by: Jan Kara <jack@suse.cz>

								Honza

> 
> Signed-off-by: Marco Stornelli <marco.stornelli@gmail.com>
> ---
>  fs/super.c         |   24 ++++++++++++++++++------
>  include/linux/fs.h |   19 +++++++++++++------
>  2 files changed, 31 insertions(+), 12 deletions(-)
> 
> diff --git a/fs/super.c b/fs/super.c
> index 7465d43..6b70c7f 100644
> --- a/fs/super.c
> +++ b/fs/super.c
> @@ -1190,14 +1190,25 @@ static void acquire_freeze_lock(struct super_block *sb, int level, bool trylock,
>   * This is an internal function, please use sb_start_{write,pagefault,intwrite}
>   * instead.
>   */
> -int __sb_start_write(struct super_block *sb, int level, bool wait)
> +int __sb_start_write(struct super_block *sb, int level, int wait)
>  {
> +	int ret = 0;
>  retry:
>  	if (unlikely(sb->s_writers.frozen >= level)) {
> -		if (!wait)
> -			return 0;
> -		wait_event(sb->s_writers.wait_unfrozen,
> -			   sb->s_writers.frozen < level);
> +		switch (wait) {
> +		case FREEZE_NOWAIT:
> +			return ret;
> +		case FREEZE_WAIT:
> +			wait_event(sb->s_writers.wait_unfrozen,
> +				   sb->s_writers.frozen < level);
> +			break;
> +		case FREEZE_WAIT_KILLABLE:
> +			ret = wait_event_killable(sb->s_writers.wait_unfrozen,
> +				   sb->s_writers.frozen < level);
> +			if (ret)
> +				return -EINTR;
> +			break;
> +		}
>  	}
>  
>  #ifdef CONFIG_LOCKDEP
> @@ -1213,7 +1224,8 @@ retry:
>  		__sb_end_write(sb, level);
>  		goto retry;
>  	}
> -	return 1;
> +	ret = 1;
> +	return ret;
>  }
>  EXPORT_SYMBOL(__sb_start_write);
>  
> diff --git a/include/linux/fs.h b/include/linux/fs.h
> index 8d47c9a..c8b7325 100644
> --- a/include/linux/fs.h
> +++ b/include/linux/fs.h
> @@ -1220,6 +1220,13 @@ enum {
>  
>  #define SB_FREEZE_LEVELS (SB_FREEZE_COMPLETE - 1)
>  
> +/* Possible waiting modes */
> +enum {
> +	FREEZE_NOWAIT = 0,		/* no blocking call */
> +	FREEZE_WAIT	= 1,		/* wait in uninterruptible state */
> +	FREEZE_WAIT_KILLABLE = 2,	/* wait in killable state */
> +};
> +
>  struct sb_writers {
>  	/* Counters for counting writers at each level */
>  	struct percpu_counter	counter[SB_FREEZE_LEVELS];
> @@ -1335,7 +1342,7 @@ extern struct timespec current_fs_time(struct super_block *sb);
>   */
>  
>  void __sb_end_write(struct super_block *sb, int level);
> -int __sb_start_write(struct super_block *sb, int level, bool wait);
> +int __sb_start_write(struct super_block *sb, int level, int wait);
>  
>  /**
>   * sb_end_write - drop write access to a superblock
> @@ -1394,12 +1401,12 @@ static inline void sb_end_intwrite(struct super_block *sb)
>   */
>  static inline void sb_start_write(struct super_block *sb)
>  {
> -	__sb_start_write(sb, SB_FREEZE_WRITE, true);
> +	__sb_start_write(sb, SB_FREEZE_WRITE, FREEZE_WAIT);
>  }
>  
>  static inline int sb_start_write_trylock(struct super_block *sb)
>  {
> -	return __sb_start_write(sb, SB_FREEZE_WRITE, false);
> +	return __sb_start_write(sb, SB_FREEZE_WRITE, FREEZE_NOWAIT);
>  }
>  
>  /**
> @@ -1423,7 +1430,7 @@ static inline int sb_start_write_trylock(struct super_block *sb)
>   */
>  static inline void sb_start_pagefault(struct super_block *sb)
>  {
> -	__sb_start_write(sb, SB_FREEZE_PAGEFAULT, true);
> +	__sb_start_write(sb, SB_FREEZE_PAGEFAULT, FREEZE_WAIT);
>  }
>  
>  /*
> @@ -1441,7 +1448,7 @@ static inline void sb_start_pagefault(struct super_block *sb)
>   */
>  static inline void sb_start_intwrite(struct super_block *sb)
>  {
> -	__sb_start_write(sb, SB_FREEZE_FS, true);
> +	__sb_start_write(sb, SB_FREEZE_FS, FREEZE_WAIT);
>  }
>  
>  
> @@ -2224,7 +2231,7 @@ static inline void file_start_write(struct file *file)
>  {
>  	if (!S_ISREG(file_inode(file)->i_mode))
>  		return;
> -	__sb_start_write(file_inode(file)->i_sb, SB_FREEZE_WRITE, true);
> +	__sb_start_write(file_inode(file)->i_sb, SB_FREEZE_WRITE, FREEZE_WAIT);
>  }
>  
>  static inline void file_end_write(struct file *file)
> -- 
> 1.7.3.4
-- 
Jan Kara <jack@suse.cz>
SUSE Labs, CR

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

* Re: [PATCH 1/3] fsfreeze: wait in killable state in __sb_start_write
       [not found]   ` <CANGUGtD67qdQyokqbaUHC0FW115udEwd8VJj6j+z5Puzjkbpxg@mail.gmail.com>
@ 2013-04-17  6:49     ` Marco Stornelli
  0 siblings, 0 replies; 3+ messages in thread
From: Marco Stornelli @ 2013-04-17  6:49 UTC (permalink / raw)
  To: Jan Kara; +Cc: Linux FS Devel, Linux Kernel, Al Viro

Resend due to mail client problem.

Marco

2013/4/17 Marco Stornelli <marco.stornelli@gmail.com>
>
> Hi,
>
>
> 2013/4/15 Jan Kara <jack@suse.cz>
>>
>> On Sat 13-04-13 12:35:54, Marco Stornelli wrote:
>> > Added a new enum to decide if we want to sleep in uninterruptible or
>> > killable state or we want simply to return immediately.
>>   I like the patch. You can add:
>> Reviewed-by: Jan Kara <jack@suse.cz>
>>
>>                                                                 Honza
>>
>

I'm happy if we can include the patches. However I do an update about
the on-going and additional work: the patches submitted can  be
applied as-is, however, I'm still working on extending the killable
path in mnt_want_write/mnt_want_write_file and I'm seeing if it's
possible to change even the page_mkwrite path. In the first case, as
Al said, there are three clear "hot" points, do_last, kern_path_create
and mq_open. However I modified the code carefully in these code paths
and I did some basic tests and it works. I'm going to submit the patch
next week for a review if I'm able to do more tests.
About the page_mkwrite path and the return value VM_FAULT_RETRY: the
return value of get_user_pages can be 0 in case of VM_FAULT_RETRY. The
caller set the nonblocking flag and it can manage the situation.
Blocking callers, instead, have a BUG_ON on the return value of 0.
They want either an error code or the number of pages gotten. A little
modification of __get_user_pages can do the work. However,
page_mkwrite could return VM_FAULT_RETRY even if the flag
FAULT_FLAG_ALLOW_RETRY is not set, I don't know if it's correct and
this flag in each case, at the moment, it's not visibile in
page_mkwrite. In addition, I need to understand if a skip can be
useful, or in each case the process will go to sleep in
uninterruptible state in a step forward. Any comments is welcome.

Marco

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

end of thread, other threads:[~2013-04-17  6:50 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-04-13 10:35 [PATCH 1/3] fsfreeze: wait in killable state in __sb_start_write Marco Stornelli
2013-04-15 11:57 ` Jan Kara
     [not found]   ` <CANGUGtD67qdQyokqbaUHC0FW115udEwd8VJj6j+z5Puzjkbpxg@mail.gmail.com>
2013-04-17  6:49     ` Marco Stornelli

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).