From: Erez Zadok <ezk@cs.sunysb.edu>
To: akpm@linux-foundation.org
Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org,
viro@ftp.linux.org.uk, hch@infradead.org,
Hugh Dickins <hugh@veritas.com>, Erez Zadok <ezk@cs.sunysb.edu>
Subject: [PATCH 11/30] Unionfs: restructure unionfs_setattr and fix truncation order
Date: Fri, 28 Dec 2007 15:42:45 -0500 [thread overview]
Message-ID: <1198874591189-git-send-email-ezk@cs.sunysb.edu> (raw)
In-Reply-To: <11988745841003-git-send-email-ezk@cs.sunysb.edu>
From: Hugh Dickins <hugh@veritas.com>
Restructure the code to move the lower notify_change out of the loop in
unionfs_setattr. Cleanup and simplify the code. Then fix the truncation
order which fsx-linux in a unionfs on tmpfs found. Then handle copyup
properly.
When shrinking a file, unionfs_setattr needs to vmtruncate the upper level
before notifying change to the lower level, to eliminate those dirty pages
beyond new eof which otherwise drift down to the lower level's writepage,
writing beyond its eof (and later uncovered when the file is expanded).
Also truncate the upper level first when expanding, in the case when
the upper level's s_maxbytes is more limiting than the lower level's.
Signed-off-by: Hugh Dickins <hugh@veritas.com>
Signed-off-by: Erez Zadok <ezk@cs.sunysb.edu>
---
fs/unionfs/inode.c | 97 ++++++++++++++++++++++++++-------------------------
1 files changed, 49 insertions(+), 48 deletions(-)
diff --git a/fs/unionfs/inode.c b/fs/unionfs/inode.c
index 78cdfa2..37258c8 100644
--- a/fs/unionfs/inode.c
+++ b/fs/unionfs/inode.c
@@ -998,11 +998,10 @@ static int unionfs_setattr(struct dentry *dentry, struct iattr *ia)
{
int err = 0;
struct dentry *lower_dentry;
- struct inode *inode = NULL;
- struct inode *lower_inode = NULL;
+ struct inode *inode;
+ struct inode *lower_inode;
int bstart, bend, bindex;
- int i;
- int copyup = 0;
+ loff_t size;
unionfs_read_lock(dentry->d_sb);
unionfs_lock_dentry(dentry);
@@ -1023,62 +1022,64 @@ static int unionfs_setattr(struct dentry *dentry, struct iattr *ia)
if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
ia->ia_valid &= ~ATTR_MODE;
- for (bindex = bstart; (bindex <= bend) || (bindex == bstart);
- bindex++) {
- lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
- if (!lower_dentry)
- continue;
- BUG_ON(lower_dentry->d_inode == NULL);
-
- /* If the file is on a read only branch */
- if (is_robranch_super(dentry->d_sb, bindex)
- || IS_RDONLY(lower_dentry->d_inode)) {
- if (copyup || (bindex != bstart))
- continue;
- /* Only if its the leftmost file, copyup the file */
- for (i = bstart - 1; i >= 0; i--) {
- loff_t size = i_size_read(dentry->d_inode);
- if (ia->ia_valid & ATTR_SIZE)
- size = ia->ia_size;
- err = copyup_dentry(dentry->d_parent->d_inode,
- dentry, bstart, i,
- dentry->d_name.name,
- dentry->d_name.len,
- NULL, size);
-
- if (!err) {
- copyup = 1;
- lower_dentry =
- unionfs_lower_dentry(dentry);
- break;
- }
- /*
- * if error is in the leftmost branch, pass
- * it up.
- */
- if (i == 0)
- goto out;
- }
+ lower_dentry = unionfs_lower_dentry(dentry);
+ BUG_ON(!lower_dentry); /* should never happen after above revalidate */
+
+ /* copyup if the file is on a read only branch */
+ if (is_robranch_super(dentry->d_sb, bstart)
+ || IS_RDONLY(lower_dentry->d_inode)) {
+ /* check if we have a branch to copy up to */
+ if (bstart <= 0) {
+ err = -EACCES;
+ goto out;
+ }
+ if (ia->ia_valid & ATTR_SIZE)
+ size = ia->ia_size;
+ else
+ size = i_size_read(inode);
+ /* copyup to next available branch */
+ for (bindex = bstart - 1; bindex >= 0; bindex--) {
+ err = copyup_dentry(dentry->d_parent->d_inode,
+ dentry, bstart, bindex,
+ dentry->d_name.name,
+ dentry->d_name.len,
+ NULL, size);
+ if (!err)
+ break;
}
- err = notify_change(lower_dentry, ia);
if (err)
goto out;
- break;
+ /* get updated lower_dentry after copyup */
+ lower_dentry = unionfs_lower_dentry(dentry);
}
- /* for mmap */
+ lower_inode = unionfs_lower_inode(inode);
+
+ /*
+ * If shrinking, first truncate upper level to cancel writing dirty
+ * pages beyond the new eof; and also if its' maxbytes is more
+ * limiting (fail with -EFBIG before making any change to the lower
+ * level). There is no need to vmtruncate the upper level
+ * afterwards in the other cases: we fsstack_copy_inode_size from
+ * the lower level.
+ */
if (ia->ia_valid & ATTR_SIZE) {
- if (ia->ia_size != i_size_read(inode)) {
+ size = i_size_read(inode);
+ if (ia->ia_size < size || (ia->ia_size > size &&
+ inode->i_sb->s_maxbytes < lower_inode->i_sb->s_maxbytes)) {
err = vmtruncate(inode, ia->ia_size);
if (err)
- printk(KERN_ERR
- "unionfs: setattr: vmtruncate failed\n");
+ goto out;
}
}
- /* get the size from the first lower inode */
- lower_inode = unionfs_lower_inode(inode);
+ /* notify the (possibly copied-up) lower inode */
+ err = notify_change(lower_dentry, ia);
+ if (err)
+ goto out;
+
+ /* get attributes from the first lower inode */
unionfs_copy_attr_all(inode, lower_inode);
/*
* unionfs_copy_attr_all will copy the lower times to our inode if
--
1.5.2.2
next prev parent reply other threads:[~2007-12-28 20:51 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-12-28 20:42 [GIT PULL -mm] 00/30 Unionfs+fsstack updates/fixes/cleanups Erez Zadok
2007-12-28 20:42 ` [PATCH 01/30] VFS/fs_stack: drop cast on inode passed to i_size_read Erez Zadok
2007-12-28 20:42 ` [PATCH 02/30] VFS/fs_stack: use locking around i_size_write in 32-bit systems Erez Zadok
2007-12-28 20:42 ` [PATCH 03/30] Unionfs: " Erez Zadok
2007-12-28 20:42 ` [PATCH 04/30] Unionfs: clarify usage.txt read/write behavior Erez Zadok
2007-12-28 20:42 ` [PATCH 05/30] Unionfs: interpose cleanup and fix for spliced dentries Erez Zadok
2007-12-28 20:42 ` [PATCH 06/30] Unionfs: initialize inode times for reused inodes Erez Zadok
2007-12-28 20:42 ` [PATCH 07/30] Unionfs: create new special files only in first branch Erez Zadok
2007-12-28 20:42 ` [PATCH 08/30] Unionfs: create new symlinks " Erez Zadok
2007-12-28 20:42 ` [PATCH 09/30] Unionfs: release special files on copyup Erez Zadok
2007-12-28 20:42 ` [PATCH 10/30] Unionfs: mmap fixes Erez Zadok
2007-12-28 20:42 ` Erez Zadok [this message]
2007-12-28 20:42 ` [PATCH 12/30] Unionfs: remove custom read/write methods Erez Zadok
2007-12-28 20:42 ` [PATCH 13/30] Unionfs: prevent deadlock in cache coherency Erez Zadok
2007-12-28 20:42 ` [PATCH 14/30] Unionfs: remove unnecessary conditional inode lock Erez Zadok
2007-12-28 20:42 ` [PATCH 15/30] Unionfs: remove unnecessary lock when deleting whiteouts Erez Zadok
2007-12-28 20:42 ` [PATCH 16/30] Unionfs: remove unnecessary lock in read_inode Erez Zadok
2007-12-28 20:42 ` [PATCH 17/30] Unionfs: remove unnecessary locking in follow-link Erez Zadok
2007-12-28 20:42 ` [PATCH 18/30] Unionfs: remove unnecessary parent lock in create Erez Zadok
2007-12-28 20:42 ` [PATCH 19/30] Unionfs: prevent false lockdep warnings in stacking Erez Zadok
2007-12-28 20:42 ` [PATCH 20/30] Unionfs: implement lockdep classes Erez Zadok
2007-12-28 20:42 ` [PATCH 21/30] Unionfs: minor code rearrangement in rename Erez Zadok
2007-12-28 20:42 ` [PATCH 22/30] Unionfs: handle on lower inodes in lookup Erez Zadok
2007-12-28 20:42 ` [PATCH 23/30] Unionfs: set our superblock a/m/ctime granularity Erez Zadok
2007-12-28 20:42 ` [PATCH 24/30] Unionfs: update inode times after a successful open Erez Zadok
2007-12-28 20:42 ` [PATCH 25/30] Unionfs: minor cleanup in check_empty Erez Zadok
2007-12-28 20:43 ` [PATCH 26/30] Unionfs: initialize namelist variable in rename Erez Zadok
2007-12-28 20:43 ` [PATCH 27/30] Unionfs: cleanup lower inodes after successful unlink Erez Zadok
2007-12-28 20:43 ` [PATCH 28/30] Unionfs: don't check dentry on error Erez Zadok
2007-12-28 20:43 ` [PATCH 29/30] Unionfs: implement d_iput method Erez Zadok
2007-12-28 20:43 ` [PATCH 30/30] Unionfs: don't check parent dentries Erez Zadok
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=1198874591189-git-send-email-ezk@cs.sunysb.edu \
--to=ezk@cs.sunysb.edu \
--cc=akpm@linux-foundation.org \
--cc=hch@infradead.org \
--cc=hugh@veritas.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=viro@ftp.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
all inboxes | Powered by JetHome®