From: Jan Kara <jack@suse.cz>
To: linux-fsdevel@vger.kernel.org
Cc: linux-ext4@vger.kernel.org, Al Viro <viro@ZenIV.linux.org.uk>,
tytso@mit.edu, Christoph Hellwig <hch@infradead.org>,
Jan Kara <jack@suse.cz>
Subject: [PATCH 2/3] vfs: Block mmapped writes while the fs is frozen
Date: Wed, 18 May 2011 17:18:01 +0200 [thread overview]
Message-ID: <1305731882-8334-3-git-send-email-jack@suse.cz> (raw)
In-Reply-To: <1305731882-8334-1-git-send-email-jack@suse.cz>
We should not allow file modification via mmap while the filesystem is
frozen. So block in block_page_mkwrite() while the filesystem is frozen.
We cannot do the blocking wait in __block_page_mkwrite() since e.g. ext4
will want to call that function with transaction started in some cases
and that would deadlock. But we can at least do the non-blocking reliable
check in __block_page_mkwrite() which is the hardest part anyway.
We have to check for frozen filesystem with the page marked dirty and under
page lock with which we then return from ->page_mkwrite(). Only that way we
cannot race with writeback done by freezing code - either we mark the page
dirty after the writeback has started, see freezing in progress and block, or
writeback will wait for our page lock which is released only when the fault is
done and then writeback will writeout and writeprotect the page again.
Signed-off-by: Jan Kara <jack@suse.cz>
---
fs/buffer.c | 28 +++++++++++++++++++++++++++-
include/linux/buffer_head.h | 2 ++
2 files changed, 29 insertions(+), 1 deletions(-)
diff --git a/fs/buffer.c b/fs/buffer.c
index 9c5dd88..030f808 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -2331,6 +2331,9 @@ EXPORT_SYMBOL(block_commit_write);
* page lock we can determine safely if the page is beyond EOF. If it is not
* beyond EOF, then the page is guaranteed safe against truncation until we
* unlock the page.
+ *
+ * Direct callers of this function should call vfs_check_frozen() so that page
+ * fault does not busyloop until the fs is thawed.
*/
int __block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf,
get_block_t get_block)
@@ -2363,6 +2366,22 @@ int __block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf,
if (unlikely(ret < 0))
unlock_page(page);
+ else {
+ /*
+ * Freezing in progress? We check after the page is marked
+ * dirty and with page lock held so if the test here fails, we
+ * are sure freezing code will wait during syncing until the
+ * page fault is done - at that point page will be dirty and
+ * unlocked so freezing code will write it and writeprotect it
+ * again.
+ */
+ set_page_dirty(page);
+ if (inode->i_sb->s_frozen != SB_UNFROZEN) {
+ unlock_page(page);
+ ret = -EAGAIN;
+ goto out;
+ }
+ }
out:
return ret;
}
@@ -2371,8 +2390,15 @@ EXPORT_SYMBOL(__block_page_mkwrite);
int block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf,
get_block_t get_block)
{
- int ret = __block_page_mkwrite(vma, vmf, get_block);
+ int ret;
+ struct super_block *sb = vma->vm_file->f_path.dentry->d_inode->i_sb;
+ /*
+ * This check is racy but catches the common case. The check in
+ * __block_page_mkwrite() is reliable.
+ */
+ vfs_check_frozen(sb, SB_FREEZE_WRITE);
+ ret = __block_page_mkwrite(vma, vmf, get_block);
return block_page_mkwrite_return(ret);
}
EXPORT_SYMBOL(block_page_mkwrite);
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index 2bf6a91..503c8a6 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -230,6 +230,8 @@ static inline int block_page_mkwrite_return(int err)
return VM_FAULT_NOPAGE;
if (err == -ENOMEM)
return VM_FAULT_OOM;
+ if (err == -EAGAIN)
+ return VM_FAULT_RETRY;
/* -ENOSPC, -EDQUOT, -EIO ... */
return VM_FAULT_SIGBUS;
}
--
1.7.1
next prev parent reply other threads:[~2011-05-18 15:19 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-05-18 15:17 [PATCH 0/3] Make block_page_mkwrite() handle frozen fs (V2) Jan Kara
2011-05-18 15:18 ` [PATCH 1/3] fs: Create __block_page_mkwrite() helper passing error values back Jan Kara
2011-05-18 18:07 ` Christoph Hellwig
2011-05-18 15:18 ` Jan Kara [this message]
2011-05-18 18:12 ` [PATCH 2/3] vfs: Block mmapped writes while the fs is frozen Christoph Hellwig
2011-05-19 12:08 ` Jan Kara
2011-05-18 15:18 ` [PATCH 3/3] ext4: Rewrite ext4_page_mkwrite() to return locked page Jan Kara
2011-05-18 18:00 ` [PATCH 0/3] Make block_page_mkwrite() handle frozen fs (V2) Darrick J. Wong
2011-05-19 10:57 ` Jan Kara
2011-05-20 17:59 ` Ted Ts'o
2011-05-23 13:21 ` Jan Kara
2011-05-23 14:47 ` Ted Ts'o
2011-05-19 12:30 ` Jan Kara
2011-05-19 16:34 ` Darrick J. Wong
2011-05-18 18:13 ` Christoph Hellwig
2011-05-19 12:24 ` Jan Kara
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1305731882-8334-3-git-send-email-jack@suse.cz \
--to=jack@suse.cz \
--cc=hch@infradead.org \
--cc=linux-ext4@vger.kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=tytso@mit.edu \
--cc=viro@ZenIV.linux.org.uk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).