linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/12] misc filesystem patches for 4.9
@ 2016-09-16 12:19 Miklos Szeredi
  2016-09-16 12:19 ` [PATCH 01/12] ima: use file_dentry() Miklos Szeredi
                   ` (11 more replies)
  0 siblings, 12 replies; 16+ messages in thread
From: Miklos Szeredi @ 2016-09-16 12:19 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: linux-kernel, Al Viro

Assorted vfs/fs fixes and cleanups for 4.9.

Git tree is:
  git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs.git#misc

Thanks,
Miklos

---
Aihua Zhang (1):
  fsnotify: support overlayfs

Miklos Szeredi (11):
  ima: use file_dentry()
  vfs: move permission checking into notify_change() for utimes(NULL)
  vfs: update ovl inode before relatime check
  locks: fix file locking on overlayfs
  vfs: make argument of d_real_inode() const
  vfs: do get_write_access() on upper layer of overlayfs
  btrfs: use filemap_check_errors()
  f2fs: use filemap_check_errors()
  posix_acl: don't ignore return value of posix_acl_create_masq()
  cifs: don't use ->d_time
  vfat: don't use ->d_time

 fs/attr.c                             | 15 ++++++++++
 fs/btrfs/ctree.h                      |  1 -
 fs/btrfs/file.c                       |  2 +-
 fs/btrfs/inode.c                      | 15 ----------
 fs/btrfs/tree-log.c                   |  4 +--
 fs/cifs/cifsfs.h                      | 10 +++++++
 fs/cifs/dir.c                         |  6 ++--
 fs/cifs/inode.c                       |  2 +-
 fs/f2fs/node.c                        |  7 ++---
 fs/fat/namei_vfat.c                   | 19 ++++++++++---
 fs/inode.c                            | 33 ++++++++++++++++++----
 fs/internal.h                         |  9 ++++++
 fs/locks.c                            | 53 ++++++++++++++++++++---------------
 fs/namei.c                            |  2 +-
 fs/namespace.c                        |  2 +-
 fs/open.c                             | 17 +++++++++--
 fs/overlayfs/super.c                  |  2 +-
 fs/posix_acl.c                        | 11 ++++----
 fs/utimes.c                           | 17 +----------
 include/linux/dcache.h                |  5 ++--
 include/linux/fs.h                    | 18 ++++++++++--
 include/linux/fsnotify.h              | 14 +++++----
 include/uapi/linux/fs.h               |  1 +
 security/integrity/ima/ima_appraise.c |  4 +--
 security/integrity/ima/ima_main.c     |  2 +-
 25 files changed, 170 insertions(+), 101 deletions(-)

-- 
2.5.5

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

* [PATCH 01/12] ima: use file_dentry()
  2016-09-16 12:19 [PATCH 00/12] misc filesystem patches for 4.9 Miklos Szeredi
@ 2016-09-16 12:19 ` Miklos Szeredi
  2016-09-16 12:19 ` [PATCH 02/12] vfs: move permission checking into notify_change() for utimes(NULL) Miklos Szeredi
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: Miklos Szeredi @ 2016-09-16 12:19 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: linux-kernel, Al Viro, stable, Mimi Zohar

Ima tries to call ->setxattr() on overlayfs dentry after having locked
underlying inode, which results in a deadlock.

Reported-by: Krisztian Litkey <kli@iki.fi>
Fixes: 4bacc9c9234c ("overlayfs: Make f_path always point to the overlay and f_inode to the underlay")
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Cc: <stable@vger.kernel.org> # v4.2
Cc: Mimi Zohar <zohar@linux.vnet.ibm.com>
---
 security/integrity/ima/ima_appraise.c | 4 ++--
 security/integrity/ima/ima_main.c     | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index 4b9b4a4e1b89..ef1e4e701780 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -190,7 +190,7 @@ int ima_appraise_measurement(enum ima_hooks func,
 {
 	static const char op[] = "appraise_data";
 	char *cause = "unknown";
-	struct dentry *dentry = file->f_path.dentry;
+	struct dentry *dentry = file_dentry(file);
 	struct inode *inode = d_backing_inode(dentry);
 	enum integrity_status status = INTEGRITY_UNKNOWN;
 	int rc = xattr_len, hash_start = 0;
@@ -295,7 +295,7 @@ out:
  */
 void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file)
 {
-	struct dentry *dentry = file->f_path.dentry;
+	struct dentry *dentry = file_dentry(file);
 	int rc = 0;
 
 	/* do not collect and update hash for digital signatures */
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 596ef616ac21..423d111b3b94 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -228,7 +228,7 @@ static int process_measurement(struct file *file, char *buf, loff_t size,
 	if ((action & IMA_APPRAISE_SUBMASK) ||
 		    strcmp(template_desc->name, IMA_TEMPLATE_IMA_NAME) != 0)
 		/* read 'security.ima' */
-		xattr_len = ima_read_xattr(file->f_path.dentry, &xattr_value);
+		xattr_len = ima_read_xattr(file_dentry(file), &xattr_value);
 
 	hash_algo = ima_get_hash_algo(xattr_value, xattr_len);
 
-- 
2.5.5

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

* [PATCH 02/12] vfs: move permission checking into notify_change() for utimes(NULL)
  2016-09-16 12:19 [PATCH 00/12] misc filesystem patches for 4.9 Miklos Szeredi
  2016-09-16 12:19 ` [PATCH 01/12] ima: use file_dentry() Miklos Szeredi
@ 2016-09-16 12:19 ` Miklos Szeredi
  2016-09-16 12:19 ` [PATCH 03/12] vfs: update ovl inode before relatime check Miklos Szeredi
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: Miklos Szeredi @ 2016-09-16 12:19 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: linux-kernel, Al Viro, stable

This fixes a bug where the permission was not properly checked in
overlayfs.  The testcase is ltp/utimensat01.

It is also cleaner and safer to do the permission checking in the vfs
helper instead of the caller.

This patch introduces an additional ia_valid flag ATTR_TOUCH (since
touch(1) is the most obvious user of utimes(NULL)) that is passed into
notify_change whenever the conditions for this special permission checking
mode are met.

Reported-by: Aihua Zhang <zhangaihua1@huawei.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Tested-by: Aihua Zhang <zhangaihua1@huawei.com>
Cc: <stable@vger.kernel.org> # v3.18+
---
 fs/attr.c          | 15 +++++++++++++++
 fs/utimes.c        | 17 +----------------
 include/linux/fs.h |  1 +
 3 files changed, 17 insertions(+), 16 deletions(-)

diff --git a/fs/attr.c b/fs/attr.c
index 42bb42bb3c72..3c42cab06b5d 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -202,6 +202,21 @@ int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **de
 			return -EPERM;
 	}
 
+	/*
+	 * If utimes(2) and friends are called with times == NULL (or both
+	 * times are UTIME_NOW), then we need to check for write permission
+	 */
+	if (ia_valid & ATTR_TOUCH) {
+		if (IS_IMMUTABLE(inode))
+			return -EPERM;
+
+		if (!inode_owner_or_capable(inode)) {
+			error = inode_permission(inode, MAY_WRITE);
+			if (error)
+				return error;
+		}
+	}
+
 	if ((ia_valid & ATTR_MODE)) {
 		umode_t amode = attr->ia_mode;
 		/* Flag setting protected by i_mutex */
diff --git a/fs/utimes.c b/fs/utimes.c
index 794f5f5b1fb5..ba54b9e648c9 100644
--- a/fs/utimes.c
+++ b/fs/utimes.c
@@ -87,21 +87,7 @@ static int utimes_common(struct path *path, struct timespec *times)
 		 */
 		newattrs.ia_valid |= ATTR_TIMES_SET;
 	} else {
-		/*
-		 * If times is NULL (or both times are UTIME_NOW),
-		 * then we need to check permissions, because
-		 * inode_change_ok() won't do it.
-		 */
-		error = -EPERM;
-                if (IS_IMMUTABLE(inode))
-			goto mnt_drop_write_and_out;
-
-		error = -EACCES;
-		if (!inode_owner_or_capable(inode)) {
-			error = inode_permission(inode, MAY_WRITE);
-			if (error)
-				goto mnt_drop_write_and_out;
-		}
+		newattrs.ia_valid |= ATTR_TOUCH;
 	}
 retry_deleg:
 	inode_lock(inode);
@@ -113,7 +99,6 @@ retry_deleg:
 			goto retry_deleg;
 	}
 
-mnt_drop_write_and_out:
 	mnt_drop_write(path->mnt);
 out:
 	return error;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 901e25d495cc..7c391366fb43 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -224,6 +224,7 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
 #define ATTR_KILL_PRIV	(1 << 14)
 #define ATTR_OPEN	(1 << 15) /* Truncating from open(O_TRUNC) */
 #define ATTR_TIMES_SET	(1 << 16)
+#define ATTR_TOUCH	(1 << 17)
 
 /*
  * Whiteout is represented by a char device.  The following constants define the
-- 
2.5.5

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

* [PATCH 03/12] vfs: update ovl inode before relatime check
  2016-09-16 12:19 [PATCH 00/12] misc filesystem patches for 4.9 Miklos Szeredi
  2016-09-16 12:19 ` [PATCH 01/12] ima: use file_dentry() Miklos Szeredi
  2016-09-16 12:19 ` [PATCH 02/12] vfs: move permission checking into notify_change() for utimes(NULL) Miklos Szeredi
@ 2016-09-16 12:19 ` Miklos Szeredi
  2016-09-16 12:19 ` [PATCH 04/12] fsnotify: support overlayfs Miklos Szeredi
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: Miklos Szeredi @ 2016-09-16 12:19 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: linux-kernel, Al Viro

On overlayfs relatime_need_update() needs inode times to be correct on
overlay inode.  But i_mtime and i_ctime are updated by filesystem code on
underlying inode only, so they will be out-of-date on the overlay inode.

This patch copies the times from the underlying inode if needed.  This
can't be done if called from RCU lookup (link following) but link m/ctime
are not updated by fs, so this is all right.

This patch doesn't change functionality for anything but overlayfs.

Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
---
 fs/inode.c         | 33 +++++++++++++++++++++++++++------
 fs/internal.h      |  9 +++++++++
 fs/namei.c         |  2 +-
 include/linux/fs.h |  1 -
 4 files changed, 37 insertions(+), 8 deletions(-)

diff --git a/fs/inode.c b/fs/inode.c
index 7e3ef3af3db9..4a1fc1631e00 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -1536,16 +1536,36 @@ sector_t bmap(struct inode *inode, sector_t block)
 EXPORT_SYMBOL(bmap);
 
 /*
+ * Update times in overlayed inode from underlying real inode
+ */
+static void update_ovl_inode_times(struct dentry *dentry, struct inode *inode,
+			       bool rcu)
+{
+	if (!rcu) {
+		struct inode *realinode = d_real_inode(dentry);
+
+		if (unlikely(inode != realinode) &&
+		    (!timespec_equal(&inode->i_mtime, &realinode->i_mtime) ||
+		     !timespec_equal(&inode->i_ctime, &realinode->i_ctime))) {
+			inode->i_mtime = realinode->i_mtime;
+			inode->i_ctime = realinode->i_ctime;
+		}
+	}
+}
+
+/*
  * With relative atime, only update atime if the previous atime is
  * earlier than either the ctime or mtime or if at least a day has
  * passed since the last atime update.
  */
-static int relatime_need_update(struct vfsmount *mnt, struct inode *inode,
-			     struct timespec now)
+static int relatime_need_update(const struct path *path, struct inode *inode,
+				struct timespec now, bool rcu)
 {
 
-	if (!(mnt->mnt_flags & MNT_RELATIME))
+	if (!(path->mnt->mnt_flags & MNT_RELATIME))
 		return 1;
+
+	update_ovl_inode_times(path->dentry, inode, rcu);
 	/*
 	 * Is mtime younger than atime? If yes, update atime:
 	 */
@@ -1612,7 +1632,8 @@ static int update_time(struct inode *inode, struct timespec *time, int flags)
  *	This function automatically handles read only file systems and media,
  *	as well as the "noatime" flag and inode specific "noatime" markers.
  */
-bool atime_needs_update(const struct path *path, struct inode *inode)
+bool __atime_needs_update(const struct path *path, struct inode *inode,
+			  bool rcu)
 {
 	struct vfsmount *mnt = path->mnt;
 	struct timespec now;
@@ -1638,7 +1659,7 @@ bool atime_needs_update(const struct path *path, struct inode *inode)
 
 	now = current_fs_time(inode->i_sb);
 
-	if (!relatime_need_update(mnt, inode, now))
+	if (!relatime_need_update(path, inode, now, rcu))
 		return false;
 
 	if (timespec_equal(&inode->i_atime, &now))
@@ -1653,7 +1674,7 @@ void touch_atime(const struct path *path)
 	struct inode *inode = d_inode(path->dentry);
 	struct timespec now;
 
-	if (!atime_needs_update(path, inode))
+	if (!__atime_needs_update(path, inode, false))
 		return;
 
 	if (!sb_start_write_trylock(inode->i_sb))
diff --git a/fs/internal.h b/fs/internal.h
index ba0737649d4a..a63da5e96148 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -120,6 +120,15 @@ extern long prune_icache_sb(struct super_block *sb, struct shrink_control *sc);
 extern void inode_add_lru(struct inode *inode);
 extern int dentry_needs_remove_privs(struct dentry *dentry);
 
+extern bool __atime_needs_update(const struct path *, struct inode *, bool);
+static inline bool atime_needs_update_rcu(const struct path *path,
+					  struct inode *inode)
+{
+	return __atime_needs_update(path, inode, true);
+}
+
+extern bool atime_needs_update_rcu(const struct path *, struct inode *);
+
 /*
  * fs-writeback.c
  */
diff --git a/fs/namei.c b/fs/namei.c
index adb04146df09..4bbcae1ba58e 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1015,7 +1015,7 @@ const char *get_link(struct nameidata *nd)
 	if (!(nd->flags & LOOKUP_RCU)) {
 		touch_atime(&last->link);
 		cond_resched();
-	} else if (atime_needs_update(&last->link, inode)) {
+	} else if (atime_needs_update_rcu(&last->link, inode)) {
 		if (unlikely(unlazy_walk(nd, NULL, 0)))
 			return ERR_PTR(-ECHILD);
 		touch_atime(&last->link);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 7c391366fb43..7db097d673a8 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2007,7 +2007,6 @@ enum file_time_flags {
 	S_VERSION = 8,
 };
 
-extern bool atime_needs_update(const struct path *, struct inode *);
 extern void touch_atime(const struct path *);
 static inline void file_accessed(struct file *file)
 {
-- 
2.5.5

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

* [PATCH 04/12] fsnotify: support overlayfs
  2016-09-16 12:19 [PATCH 00/12] misc filesystem patches for 4.9 Miklos Szeredi
                   ` (2 preceding siblings ...)
  2016-09-16 12:19 ` [PATCH 03/12] vfs: update ovl inode before relatime check Miklos Szeredi
@ 2016-09-16 12:19 ` Miklos Szeredi
  2016-09-16 16:38   ` Jan Kara
  2016-09-16 12:19 ` [PATCH 05/12] locks: fix file locking on overlayfs Miklos Szeredi
                   ` (7 subsequent siblings)
  11 siblings, 1 reply; 16+ messages in thread
From: Miklos Szeredi @ 2016-09-16 12:19 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: Aihua Zhang, linux-kernel, Al Viro, Jan Kara, Eric Paris

From: Aihua Zhang <zhangaihua1@huawei.com>

When an event occurs direct it to the overlay inode instead of the real
underlying inode.

This will work even if the file was first on the lower layer and then
copied up, while the watch is there.  This is because the watch is on the
overlay inode, which stays the same through the copy-up.

For filesystems other than overlayfs this is a no-op, except for the
performance impact of an extra pointer dereferece.

Verified to work correctly with the inotify/fanotify tests in LTP.

Signed-off-by: Aihua Zhang <zhangaihua1@huawei.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Cc: Jan Kara <jack@suse.cz>
Cc: Eric Paris <eparis@redhat.com>
---
 include/linux/fsnotify.h | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h
index eed9e853a06f..b8bcc058e031 100644
--- a/include/linux/fsnotify.h
+++ b/include/linux/fsnotify.h
@@ -29,7 +29,11 @@ static inline int fsnotify_parent(struct path *path, struct dentry *dentry, __u3
 static inline int fsnotify_perm(struct file *file, int mask)
 {
 	struct path *path = &file->f_path;
-	struct inode *inode = file_inode(file);
+	/*
+	 * Do not use file_inode() here or anywhere in this file to get the
+	 * inode.  That would break *notity on overlayfs.
+	 */
+	struct inode *inode = path->dentry->d_inode;
 	__u32 fsnotify_mask = 0;
 	int ret;
 
@@ -173,7 +177,7 @@ static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry)
 static inline void fsnotify_access(struct file *file)
 {
 	struct path *path = &file->f_path;
-	struct inode *inode = file_inode(file);
+	struct inode *inode = path->dentry->d_inode;
 	__u32 mask = FS_ACCESS;
 
 	if (S_ISDIR(inode->i_mode))
@@ -191,7 +195,7 @@ static inline void fsnotify_access(struct file *file)
 static inline void fsnotify_modify(struct file *file)
 {
 	struct path *path = &file->f_path;
-	struct inode *inode = file_inode(file);
+	struct inode *inode = path->dentry->d_inode;
 	__u32 mask = FS_MODIFY;
 
 	if (S_ISDIR(inode->i_mode))
@@ -209,7 +213,7 @@ static inline void fsnotify_modify(struct file *file)
 static inline void fsnotify_open(struct file *file)
 {
 	struct path *path = &file->f_path;
-	struct inode *inode = file_inode(file);
+	struct inode *inode = path->dentry->d_inode;
 	__u32 mask = FS_OPEN;
 
 	if (S_ISDIR(inode->i_mode))
@@ -225,7 +229,7 @@ static inline void fsnotify_open(struct file *file)
 static inline void fsnotify_close(struct file *file)
 {
 	struct path *path = &file->f_path;
-	struct inode *inode = file_inode(file);
+	struct inode *inode = path->dentry->d_inode;
 	fmode_t mode = file->f_mode;
 	__u32 mask = (mode & FMODE_WRITE) ? FS_CLOSE_WRITE : FS_CLOSE_NOWRITE;
 
-- 
2.5.5

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

* [PATCH 05/12] locks: fix file locking on overlayfs
  2016-09-16 12:19 [PATCH 00/12] misc filesystem patches for 4.9 Miklos Szeredi
                   ` (3 preceding siblings ...)
  2016-09-16 12:19 ` [PATCH 04/12] fsnotify: support overlayfs Miklos Szeredi
@ 2016-09-16 12:19 ` Miklos Szeredi
  2016-09-16 12:19 ` [PATCH 06/12] vfs: make argument of d_real_inode() const Miklos Szeredi
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: Miklos Szeredi @ 2016-09-16 12:19 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: linux-kernel, Al Viro, J. Bruce Fields

This patch allows flock, posix locks, ofd locks and leases to work
correctly on overlayfs.

Instead of using the underlying inode for storing lock context use the
overlay inode.  This allows locks to be persistent across copy-up.

This is done by introducing locks_inode() helper and using it instead of
file_inode() to get the inode in locking code.  For non-overlayfs the two
are equivalent, except for an extra pointer dereference in locks_inode().

Since lock operations are in "struct file_operations" we must also make
sure not to call underlying filesystem's lock operations.  Introcude a
super block flag MS_NOREMOTELOCK to this effect.

Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Acked-by: Jeff Layton <jlayton@poochiereds.net>
Cc: "J. Bruce Fields" <bfields@fieldses.org>
---
 fs/locks.c              | 50 +++++++++++++++++++++++++++----------------------
 fs/namespace.c          |  2 +-
 fs/open.c               |  2 +-
 fs/overlayfs/super.c    |  2 +-
 include/linux/fs.h      | 16 ++++++++++++++--
 include/uapi/linux/fs.h |  1 +
 6 files changed, 46 insertions(+), 27 deletions(-)

diff --git a/fs/locks.c b/fs/locks.c
index ee1b15f6fc13..c1656cff53ee 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -139,6 +139,11 @@
 #define IS_LEASE(fl)	(fl->fl_flags & (FL_LEASE|FL_DELEG|FL_LAYOUT))
 #define IS_OFDLCK(fl)	(fl->fl_flags & FL_OFDLCK)
 
+static inline bool is_remote_lock(struct file *filp)
+{
+	return likely(!(filp->f_path.dentry->d_sb->s_flags & MS_NOREMOTELOCK));
+}
+
 static bool lease_breaking(struct file_lock *fl)
 {
 	return fl->fl_flags & (FL_UNLOCK_PENDING | FL_DOWNGRADE_PENDING);
@@ -791,7 +796,7 @@ posix_test_lock(struct file *filp, struct file_lock *fl)
 {
 	struct file_lock *cfl;
 	struct file_lock_context *ctx;
-	struct inode *inode = file_inode(filp);
+	struct inode *inode = locks_inode(filp);
 
 	ctx = smp_load_acquire(&inode->i_flctx);
 	if (!ctx || list_empty_careful(&ctx->flc_posix)) {
@@ -1192,7 +1197,7 @@ static int posix_lock_inode(struct inode *inode, struct file_lock *request,
 int posix_lock_file(struct file *filp, struct file_lock *fl,
 			struct file_lock *conflock)
 {
-	return posix_lock_inode(file_inode(filp), fl, conflock);
+	return posix_lock_inode(locks_inode(filp), fl, conflock);
 }
 EXPORT_SYMBOL(posix_lock_file);
 
@@ -1232,7 +1237,7 @@ static int posix_lock_inode_wait(struct inode *inode, struct file_lock *fl)
 int locks_mandatory_locked(struct file *file)
 {
 	int ret;
-	struct inode *inode = file_inode(file);
+	struct inode *inode = locks_inode(file);
 	struct file_lock_context *ctx;
 	struct file_lock *fl;
 
@@ -1572,7 +1577,7 @@ EXPORT_SYMBOL(lease_get_mtime);
 int fcntl_getlease(struct file *filp)
 {
 	struct file_lock *fl;
-	struct inode *inode = file_inode(filp);
+	struct inode *inode = locks_inode(filp);
 	struct file_lock_context *ctx;
 	int type = F_UNLCK;
 	LIST_HEAD(dispose);
@@ -1580,7 +1585,7 @@ int fcntl_getlease(struct file *filp)
 	ctx = smp_load_acquire(&inode->i_flctx);
 	if (ctx && !list_empty_careful(&ctx->flc_lease)) {
 		spin_lock(&ctx->flc_lock);
-		time_out_leases(file_inode(filp), &dispose);
+		time_out_leases(inode, &dispose);
 		list_for_each_entry(fl, &ctx->flc_lease, fl_list) {
 			if (fl->fl_file != filp)
 				continue;
@@ -1628,7 +1633,7 @@ generic_add_lease(struct file *filp, long arg, struct file_lock **flp, void **pr
 {
 	struct file_lock *fl, *my_fl = NULL, *lease;
 	struct dentry *dentry = filp->f_path.dentry;
-	struct inode *inode = file_inode(filp);
+	struct inode *inode = dentry->d_inode;
 	struct file_lock_context *ctx;
 	bool is_deleg = (*flp)->fl_flags & FL_DELEG;
 	int error;
@@ -1742,7 +1747,7 @@ static int generic_delete_lease(struct file *filp, void *owner)
 {
 	int error = -EAGAIN;
 	struct file_lock *fl, *victim = NULL;
-	struct inode *inode = file_inode(filp);
+	struct inode *inode = locks_inode(filp);
 	struct file_lock_context *ctx;
 	LIST_HEAD(dispose);
 
@@ -1782,7 +1787,7 @@ static int generic_delete_lease(struct file *filp, void *owner)
 int generic_setlease(struct file *filp, long arg, struct file_lock **flp,
 			void **priv)
 {
-	struct inode *inode = file_inode(filp);
+	struct inode *inode = locks_inode(filp);
 	int error;
 
 	if ((!uid_eq(current_fsuid(), inode->i_uid)) && !capable(CAP_LEASE))
@@ -1830,7 +1835,7 @@ EXPORT_SYMBOL(generic_setlease);
 int
 vfs_setlease(struct file *filp, long arg, struct file_lock **lease, void **priv)
 {
-	if (filp->f_op->setlease)
+	if (filp->f_op->setlease && is_remote_lock(filp))
 		return filp->f_op->setlease(filp, arg, lease, priv);
 	else
 		return generic_setlease(filp, arg, lease, priv);
@@ -1979,7 +1984,7 @@ SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd)
 	if (error)
 		goto out_free;
 
-	if (f.file->f_op->flock)
+	if (f.file->f_op->flock && is_remote_lock(f.file))
 		error = f.file->f_op->flock(f.file,
 					  (can_sleep) ? F_SETLKW : F_SETLK,
 					  lock);
@@ -2005,7 +2010,7 @@ SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd)
  */
 int vfs_test_lock(struct file *filp, struct file_lock *fl)
 {
-	if (filp->f_op->lock)
+	if (filp->f_op->lock && is_remote_lock(filp))
 		return filp->f_op->lock(filp, F_GETLK, fl);
 	posix_test_lock(filp, fl);
 	return 0;
@@ -2129,7 +2134,7 @@ out:
  */
 int vfs_lock_file(struct file *filp, unsigned int cmd, struct file_lock *fl, struct file_lock *conf)
 {
-	if (filp->f_op->lock)
+	if (filp->f_op->lock && is_remote_lock(filp))
 		return filp->f_op->lock(filp, cmd, fl);
 	else
 		return posix_lock_file(filp, fl, conf);
@@ -2191,7 +2196,7 @@ int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd,
 	if (file_lock == NULL)
 		return -ENOLCK;
 
-	inode = file_inode(filp);
+	inode = locks_inode(filp);
 
 	/*
 	 * This might block, so we do it before checking the inode.
@@ -2343,7 +2348,7 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd,
 	if (copy_from_user(&flock, l, sizeof(flock)))
 		goto out;
 
-	inode = file_inode(filp);
+	inode = locks_inode(filp);
 
 	/* Don't allow mandatory locks on files that may be memory mapped
 	 * and shared.
@@ -2426,6 +2431,7 @@ out:
 void locks_remove_posix(struct file *filp, fl_owner_t owner)
 {
 	int error;
+	struct inode *inode = locks_inode(filp);
 	struct file_lock lock;
 	struct file_lock_context *ctx;
 
@@ -2434,7 +2440,7 @@ void locks_remove_posix(struct file *filp, fl_owner_t owner)
 	 * posix_lock_file().  Another process could be setting a lock on this
 	 * file at the same time, but we wouldn't remove that lock anyway.
 	 */
-	ctx =  smp_load_acquire(&file_inode(filp)->i_flctx);
+	ctx =  smp_load_acquire(&inode->i_flctx);
 	if (!ctx || list_empty(&ctx->flc_posix))
 		return;
 
@@ -2452,7 +2458,7 @@ void locks_remove_posix(struct file *filp, fl_owner_t owner)
 
 	if (lock.fl_ops && lock.fl_ops->fl_release_private)
 		lock.fl_ops->fl_release_private(&lock);
-	trace_locks_remove_posix(file_inode(filp), &lock, error);
+	trace_locks_remove_posix(inode, &lock, error);
 }
 
 EXPORT_SYMBOL(locks_remove_posix);
@@ -2469,12 +2475,12 @@ locks_remove_flock(struct file *filp, struct file_lock_context *flctx)
 		.fl_type = F_UNLCK,
 		.fl_end = OFFSET_MAX,
 	};
-	struct inode *inode = file_inode(filp);
+	struct inode *inode = locks_inode(filp);
 
 	if (list_empty(&flctx->flc_flock))
 		return;
 
-	if (filp->f_op->flock)
+	if (filp->f_op->flock && is_remote_lock(filp))
 		filp->f_op->flock(filp, F_SETLKW, &fl);
 	else
 		flock_lock_inode(inode, &fl);
@@ -2508,7 +2514,7 @@ void locks_remove_file(struct file *filp)
 {
 	struct file_lock_context *ctx;
 
-	ctx = smp_load_acquire(&file_inode(filp)->i_flctx);
+	ctx = smp_load_acquire(&locks_inode(filp)->i_flctx);
 	if (!ctx)
 		return;
 
@@ -2552,7 +2558,7 @@ EXPORT_SYMBOL(posix_unblock_lock);
  */
 int vfs_cancel_lock(struct file *filp, struct file_lock *fl)
 {
-	if (filp->f_op->lock)
+	if (filp->f_op->lock && is_remote_lock(filp))
 		return filp->f_op->lock(filp, F_CANCELLK, fl);
 	return 0;
 }
@@ -2580,7 +2586,7 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl,
 		fl_pid = fl->fl_pid;
 
 	if (fl->fl_file != NULL)
-		inode = file_inode(fl->fl_file);
+		inode = locks_inode(fl->fl_file);
 
 	seq_printf(f, "%lld:%s ", id, pfx);
 	if (IS_POSIX(fl)) {
@@ -2682,7 +2688,7 @@ static void __show_fd_locks(struct seq_file *f,
 void show_fd_locks(struct seq_file *f,
 		  struct file *filp, struct files_struct *files)
 {
-	struct inode *inode = file_inode(filp);
+	struct inode *inode = locks_inode(filp);
 	struct file_lock_context *ctx;
 	int id = 0;
 
diff --git a/fs/namespace.c b/fs/namespace.c
index 7bb2cda3bfef..dcd9afe21e62 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -2700,7 +2700,7 @@ long do_mount(const char *dev_name, const char __user *dir_name,
 
 	flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE | MS_BORN |
 		   MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT |
-		   MS_STRICTATIME);
+		   MS_STRICTATIME | MS_NOREMOTELOCK);
 
 	if (flags & MS_REMOUNT)
 		retval = do_remount(&path, flags & ~MS_REMOUNT, mnt_flags,
diff --git a/fs/open.c b/fs/open.c
index 4fd6e256f4f4..648fb9d3e97a 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -726,7 +726,7 @@ static int do_dentry_open(struct file *f,
 	if (error)
 		goto cleanup_all;
 
-	error = break_lease(inode, f->f_flags);
+	error = break_lease(locks_inode(f), f->f_flags);
 	if (error)
 		goto cleanup_all;
 
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index e2a94a26767b..3d0b9dee2b76 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -1320,7 +1320,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
 	sb->s_xattr = ovl_xattr_handlers;
 	sb->s_root = root_dentry;
 	sb->s_fs_info = ufs;
-	sb->s_flags |= MS_POSIXACL;
+	sb->s_flags |= MS_POSIXACL | MS_NOREMOTELOCK;
 
 	return 0;
 
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 7db097d673a8..8ee0f011547f 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1065,6 +1065,18 @@ struct file_lock_context {
 
 extern void send_sigio(struct fown_struct *fown, int fd, int band);
 
+/*
+ * Return the inode to use for locking
+ *
+ * For overlayfs this should be the overlay inode, not the real inode returned
+ * by file_inode().  For any other fs file_inode(filp) and locks_inode(filp) are
+ * equal.
+ */
+static inline struct inode *locks_inode(const struct file *f)
+{
+	return f->f_path.dentry->d_inode;
+}
+
 #ifdef CONFIG_FILE_LOCKING
 extern int fcntl_getlk(struct file *, unsigned int, struct flock __user *);
 extern int fcntl_setlk(unsigned int, struct file *, unsigned int,
@@ -1252,7 +1264,7 @@ static inline struct dentry *file_dentry(const struct file *file)
 
 static inline int locks_lock_file_wait(struct file *filp, struct file_lock *fl)
 {
-	return locks_lock_inode_wait(file_inode(filp), fl);
+	return locks_lock_inode_wait(locks_inode(filp), fl);
 }
 
 struct fasync_struct {
@@ -2155,7 +2167,7 @@ static inline int mandatory_lock(struct inode *ino)
 
 static inline int locks_verify_locked(struct file *file)
 {
-	if (mandatory_lock(file_inode(file)))
+	if (mandatory_lock(locks_inode(file)))
 		return locks_mandatory_locked(file);
 	return 0;
 }
diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h
index 3b00f7c8943f..2473272169f2 100644
--- a/include/uapi/linux/fs.h
+++ b/include/uapi/linux/fs.h
@@ -132,6 +132,7 @@ struct inodes_stat_t {
 #define MS_LAZYTIME	(1<<25) /* Update the on-disk [acm]times lazily */
 
 /* These sb flags are internal to the kernel */
+#define MS_NOREMOTELOCK	(1<<27)
 #define MS_NOSEC	(1<<28)
 #define MS_BORN		(1<<29)
 #define MS_ACTIVE	(1<<30)
-- 
2.5.5

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

* [PATCH 06/12] vfs: make argument of d_real_inode() const
  2016-09-16 12:19 [PATCH 00/12] misc filesystem patches for 4.9 Miklos Szeredi
                   ` (4 preceding siblings ...)
  2016-09-16 12:19 ` [PATCH 05/12] locks: fix file locking on overlayfs Miklos Szeredi
@ 2016-09-16 12:19 ` Miklos Szeredi
  2016-09-16 12:19 ` [PATCH 07/12] vfs: do get_write_access() on upper layer of overlayfs Miklos Szeredi
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: Miklos Szeredi @ 2016-09-16 12:19 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: linux-kernel, Al Viro

d_op->d_real() leaves the dentry alone except if the third argument is
non-zero.  Unfortunately very difficult to explain to the compiler without
a cast.

Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Acked-by: Jeff Layton <jlayton@poochiereds.net>
---
 include/linux/dcache.h | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 5ff3e9a4fe5f..5beed7b30561 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -584,9 +584,10 @@ static inline struct dentry *d_real(struct dentry *dentry,
  * If dentry is on an union/overlay, then return the underlying, real inode.
  * Otherwise return d_inode().
  */
-static inline struct inode *d_real_inode(struct dentry *dentry)
+static inline struct inode *d_real_inode(const struct dentry *dentry)
 {
-	return d_backing_inode(d_real(dentry, NULL, 0));
+	/* This usage of d_real() results in const dentry */
+	return d_backing_inode(d_real((struct dentry *) dentry, NULL, 0));
 }
 
 
-- 
2.5.5

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

* [PATCH 07/12] vfs: do get_write_access() on upper layer of overlayfs
  2016-09-16 12:19 [PATCH 00/12] misc filesystem patches for 4.9 Miklos Szeredi
                   ` (5 preceding siblings ...)
  2016-09-16 12:19 ` [PATCH 06/12] vfs: make argument of d_real_inode() const Miklos Szeredi
@ 2016-09-16 12:19 ` Miklos Szeredi
  2016-09-16 12:19 ` [PATCH 08/12] btrfs: use filemap_check_errors() Miklos Szeredi
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: Miklos Szeredi @ 2016-09-16 12:19 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: linux-kernel, Al Viro, J. Bruce Fields

The problem with writecount is: we want consistent handling of it for
underlying filesystems as well as overlayfs.  Making sure i_writecount is
correct on all layers is difficult.  Instead this patch makes sure that
when write access is acquired, it's always done on the underlying writable
layer (called the upper layer).  We must also make sure to look at the
writecount on this layer when checking for conflicting leases.

Open for write already updates the upper layer's writecount.  Leaving only
truncate.

For truncate copy up must happen before get_write_access() so that the
writecount is updated on the upper layer.  Problem with this is if
something fails after that, then copy-up was done needlessly.  E.g. if
break_lease() was interrupted.  Probably not a big deal in practice.

Another interesting case is if there's a denywrite on a lower file that is
then opened for write or truncated.  With this patch these will succeed,
which is somewhat counterintuitive.  But I think it's still acceptable,
considering that the copy-up does actually create a different file, so the
old, denywrite mapping won't be touched.

On non-overlayfs d_real() is an identity function and d_real_inode() is
equivalent to d_inode() so this patch doesn't change behavior in that case.

Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Acked-by: Jeff Layton <jlayton@poochiereds.net>
Cc: "J. Bruce Fields" <bfields@fieldses.org>
---
 fs/locks.c |  3 ++-
 fs/open.c  | 15 +++++++++++++--
 2 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/fs/locks.c b/fs/locks.c
index c1656cff53ee..b242d5b99589 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -1618,7 +1618,8 @@ check_conflicting_open(const struct dentry *dentry, const long arg, int flags)
 	if (flags & FL_LAYOUT)
 		return 0;
 
-	if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0))
+	if ((arg == F_RDLCK) &&
+	    (atomic_read(&d_real_inode(dentry)->i_writecount) > 0))
 		return -EAGAIN;
 
 	if ((arg == F_WRLCK) && ((d_count(dentry) > 1) ||
diff --git a/fs/open.c b/fs/open.c
index 648fb9d3e97a..8aeb08bb278b 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -68,6 +68,7 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
 long vfs_truncate(const struct path *path, loff_t length)
 {
 	struct inode *inode;
+	struct dentry *upperdentry;
 	long error;
 
 	inode = path->dentry->d_inode;
@@ -90,7 +91,17 @@ long vfs_truncate(const struct path *path, loff_t length)
 	if (IS_APPEND(inode))
 		goto mnt_drop_write_and_out;
 
-	error = get_write_access(inode);
+	/*
+	 * If this is an overlayfs then do as if opening the file so we get
+	 * write access on the upper inode, not on the overlay inode.  For
+	 * non-overlay filesystems d_real() is an identity function.
+	 */
+	upperdentry = d_real(path->dentry, NULL, O_WRONLY);
+	error = PTR_ERR(upperdentry);
+	if (IS_ERR(upperdentry))
+		goto mnt_drop_write_and_out;
+
+	error = get_write_access(upperdentry->d_inode);
 	if (error)
 		goto mnt_drop_write_and_out;
 
@@ -109,7 +120,7 @@ long vfs_truncate(const struct path *path, loff_t length)
 		error = do_truncate(path->dentry, length, 0, NULL);
 
 put_write_and_out:
-	put_write_access(inode);
+	put_write_access(upperdentry->d_inode);
 mnt_drop_write_and_out:
 	mnt_drop_write(path->mnt);
 out:
-- 
2.5.5

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

* [PATCH 08/12] btrfs: use filemap_check_errors()
  2016-09-16 12:19 [PATCH 00/12] misc filesystem patches for 4.9 Miklos Szeredi
                   ` (6 preceding siblings ...)
  2016-09-16 12:19 ` [PATCH 07/12] vfs: do get_write_access() on upper layer of overlayfs Miklos Szeredi
@ 2016-09-16 12:19 ` Miklos Szeredi
  2016-09-16 12:19 ` [PATCH 09/12] f2fs: " Miklos Szeredi
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: Miklos Szeredi @ 2016-09-16 12:19 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: linux-kernel, Al Viro, Chris Mason

Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Reviewed-by: Omar Sandoval <osandov@fb.com>
Cc: Chris Mason <clm@fb.com>
---
 fs/btrfs/ctree.h    |  1 -
 fs/btrfs/file.c     |  2 +-
 fs/btrfs/inode.c    | 15 ---------------
 fs/btrfs/tree-log.c |  4 ++--
 4 files changed, 3 insertions(+), 19 deletions(-)

diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 33fe03551105..e62fd50237e4 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -3161,7 +3161,6 @@ int btrfs_prealloc_file_range_trans(struct inode *inode,
 				    struct btrfs_trans_handle *trans, int mode,
 				    u64 start, u64 num_bytes, u64 min_size,
 				    loff_t actual_len, u64 *alloc_hint);
-int btrfs_inode_check_errors(struct inode *inode);
 extern const struct dentry_operations btrfs_dentry_operations;
 #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
 void btrfs_test_inode_set_ops(struct inode *inode);
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index fea31a4a6e36..4843cb994835 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -2040,7 +2040,7 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
 		 * flags for any errors that might have happened while doing
 		 * writeback of file data.
 		 */
-		ret = btrfs_inode_check_errors(inode);
+		ret = filemap_check_errors(inode->i_mapping);
 		inode_unlock(inode);
 		goto out;
 	}
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index e6811c42e41e..0207622ec622 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -10543,21 +10543,6 @@ out_inode:
 
 }
 
-/* Inspired by filemap_check_errors() */
-int btrfs_inode_check_errors(struct inode *inode)
-{
-	int ret = 0;
-
-	if (test_bit(AS_ENOSPC, &inode->i_mapping->flags) &&
-	    test_and_clear_bit(AS_ENOSPC, &inode->i_mapping->flags))
-		ret = -ENOSPC;
-	if (test_bit(AS_EIO, &inode->i_mapping->flags) &&
-	    test_and_clear_bit(AS_EIO, &inode->i_mapping->flags))
-		ret = -EIO;
-
-	return ret;
-}
-
 static const struct inode_operations btrfs_dir_inode_operations = {
 	.getattr	= btrfs_getattr,
 	.lookup		= btrfs_lookup,
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index ef9c55bc7907..8a84ebd8e7cc 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -3961,7 +3961,7 @@ static int wait_ordered_extents(struct btrfs_trans_handle *trans,
 			 * i_mapping flags, so that the next fsync won't get
 			 * an outdated io error too.
 			 */
-			btrfs_inode_check_errors(inode);
+			filemap_check_errors(inode->i_mapping);
 			*ordered_io_error = true;
 			break;
 		}
@@ -4198,7 +4198,7 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans,
 	 * without writing to the log tree and the fsync must report the
 	 * file data write error and not commit the current transaction.
 	 */
-	ret = btrfs_inode_check_errors(inode);
+	ret = filemap_check_errors(inode->i_mapping);
 	if (ret)
 		ctx->io_err = ret;
 process:
-- 
2.5.5

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

* [PATCH 09/12] f2fs: use filemap_check_errors()
  2016-09-16 12:19 [PATCH 00/12] misc filesystem patches for 4.9 Miklos Szeredi
                   ` (7 preceding siblings ...)
  2016-09-16 12:19 ` [PATCH 08/12] btrfs: use filemap_check_errors() Miklos Szeredi
@ 2016-09-16 12:19 ` Miklos Szeredi
  2016-09-16 12:19 ` [PATCH 10/12] posix_acl: don't ignore return value of posix_acl_create_masq() Miklos Szeredi
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: Miklos Szeredi @ 2016-09-16 12:19 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: linux-kernel, Al Viro, Jaegeuk Kim

Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Cc: Jaegeuk Kim <jaegeuk@kernel.org>
---
 fs/f2fs/node.c | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index f75d197d5beb..67ed2192f926 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -1513,7 +1513,7 @@ int wait_on_node_pages_writeback(struct f2fs_sb_info *sbi, nid_t ino)
 {
 	pgoff_t index = 0, end = ULONG_MAX;
 	struct pagevec pvec;
-	int ret2 = 0, ret = 0;
+	int ret2, ret = 0;
 
 	pagevec_init(&pvec, 0);
 
@@ -1542,10 +1542,7 @@ int wait_on_node_pages_writeback(struct f2fs_sb_info *sbi, nid_t ino)
 		cond_resched();
 	}
 
-	if (unlikely(test_and_clear_bit(AS_ENOSPC, &NODE_MAPPING(sbi)->flags)))
-		ret2 = -ENOSPC;
-	if (unlikely(test_and_clear_bit(AS_EIO, &NODE_MAPPING(sbi)->flags)))
-		ret2 = -EIO;
+	ret2 = filemap_check_errors(NODE_MAPPING(sbi));
 	if (!ret)
 		ret = ret2;
 	return ret;
-- 
2.5.5

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

* [PATCH 10/12] posix_acl: don't ignore return value of posix_acl_create_masq()
  2016-09-16 12:19 [PATCH 00/12] misc filesystem patches for 4.9 Miklos Szeredi
                   ` (8 preceding siblings ...)
  2016-09-16 12:19 ` [PATCH 09/12] f2fs: " Miklos Szeredi
@ 2016-09-16 12:19 ` Miklos Szeredi
  2016-09-16 12:45   ` Andreas Grünbacher
  2016-09-16 12:19 ` [PATCH 11/12] cifs: don't use ->d_time Miklos Szeredi
  2016-09-16 12:19 ` [PATCH 12/12] vfat: " Miklos Szeredi
  11 siblings, 1 reply; 16+ messages in thread
From: Miklos Szeredi @ 2016-09-16 12:19 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: linux-kernel, Al Viro, Andreas Gruenbacher

Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Cc: Andreas Gruenbacher <agruenba@redhat.com>
---
 fs/posix_acl.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/fs/posix_acl.c b/fs/posix_acl.c
index 59d47ab0791a..ea3eb6f3bf1e 100644
--- a/fs/posix_acl.c
+++ b/fs/posix_acl.c
@@ -598,13 +598,14 @@ posix_acl_create(struct inode *dir, umode_t *mode,
 	if (IS_ERR(p))
 		return PTR_ERR(p);
 
+	ret = -ENOMEM;
 	clone = posix_acl_clone(p, GFP_NOFS);
 	if (!clone)
-		goto no_mem;
+		goto err_release;
 
 	ret = posix_acl_create_masq(clone, mode);
 	if (ret < 0)
-		goto no_mem_clone;
+		goto err_release_clone;
 
 	if (ret == 0)
 		posix_acl_release(clone);
@@ -618,11 +619,11 @@ posix_acl_create(struct inode *dir, umode_t *mode,
 
 	return 0;
 
-no_mem_clone:
+err_release_clone:
 	posix_acl_release(clone);
-no_mem:
+err_release:
 	posix_acl_release(p);
-	return -ENOMEM;
+	return ret;
 }
 EXPORT_SYMBOL_GPL(posix_acl_create);
 
-- 
2.5.5

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

* [PATCH 11/12] cifs: don't use ->d_time
  2016-09-16 12:19 [PATCH 00/12] misc filesystem patches for 4.9 Miklos Szeredi
                   ` (9 preceding siblings ...)
  2016-09-16 12:19 ` [PATCH 10/12] posix_acl: don't ignore return value of posix_acl_create_masq() Miklos Szeredi
@ 2016-09-16 12:19 ` Miklos Szeredi
  2016-09-16 12:19 ` [PATCH 12/12] vfat: " Miklos Szeredi
  11 siblings, 0 replies; 16+ messages in thread
From: Miklos Szeredi @ 2016-09-16 12:19 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: linux-kernel, Al Viro, Steve French

Use d_fsdata instead, which is the same size.  Introduce helpers to hide
the typecasts.

Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Cc: Steve French <sfrench@samba.org>
---
 fs/cifs/cifsfs.h | 10 ++++++++++
 fs/cifs/dir.c    |  6 +++---
 fs/cifs/inode.c  |  2 +-
 3 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 9dcf974acc47..c9c00a862036 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -41,6 +41,16 @@ cifs_uniqueid_to_ino_t(u64 fileid)
 
 }
 
+static inline void cifs_set_time(struct dentry *dentry, unsigned long time)
+{
+	dentry->d_fsdata = (void *) time;
+}
+
+static inline unsigned long cifs_get_time(struct dentry *dentry)
+{
+	return (unsigned long) dentry->d_fsdata;
+}
+
 extern struct file_system_type cifs_fs_type;
 extern const struct address_space_operations cifs_addr_ops;
 extern const struct address_space_operations cifs_addr_ops_smallbuf;
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 4716c54dbfc6..789ff1df2d8d 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -40,7 +40,7 @@ renew_parental_timestamps(struct dentry *direntry)
 	/* BB check if there is a way to get the kernel to do this or if we
 	   really need this */
 	do {
-		direntry->d_time = jiffies;
+		cifs_set_time(direntry, jiffies);
 		direntry = direntry->d_parent;
 	} while (!IS_ROOT(direntry));
 }
@@ -802,7 +802,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
 
 	} else if (rc == -ENOENT) {
 		rc = 0;
-		direntry->d_time = jiffies;
+		cifs_set_time(direntry, jiffies);
 		d_add(direntry, NULL);
 	/*	if it was once a directory (but how can we tell?) we could do
 		shrink_dcache_parent(direntry); */
@@ -862,7 +862,7 @@ cifs_d_revalidate(struct dentry *direntry, unsigned int flags)
 	if (flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET))
 		return 0;
 
-	if (time_after(jiffies, direntry->d_time + HZ) || !lookupCacheEnabled)
+	if (time_after(jiffies, cifs_get_time(direntry) + HZ) || !lookupCacheEnabled)
 		return 0;
 
 	return 1;
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index b87efd0c92d6..0b4a35514351 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -1951,7 +1951,7 @@ int cifs_revalidate_dentry_attr(struct dentry *dentry)
 
 	cifs_dbg(FYI, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld\n",
 		 full_path, inode, inode->i_count.counter,
-		 dentry, dentry->d_time, jiffies);
+		 dentry, cifs_get_time(dentry), jiffies);
 
 	if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
 		rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
-- 
2.5.5

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

* [PATCH 12/12] vfat: don't use ->d_time
  2016-09-16 12:19 [PATCH 00/12] misc filesystem patches for 4.9 Miklos Szeredi
                   ` (10 preceding siblings ...)
  2016-09-16 12:19 ` [PATCH 11/12] cifs: don't use ->d_time Miklos Szeredi
@ 2016-09-16 12:19 ` Miklos Szeredi
  11 siblings, 0 replies; 16+ messages in thread
From: Miklos Szeredi @ 2016-09-16 12:19 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: linux-kernel, Al Viro, OGAWA Hirofumi

Use d_fsdata instead, which is the same size.  Introduce helpers to hide
the typecasts.

Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Cc: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
---
 fs/fat/namei_vfat.c | 19 +++++++++++++++----
 1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c
index 92b7363dafa9..4afdc3f36470 100644
--- a/fs/fat/namei_vfat.c
+++ b/fs/fat/namei_vfat.c
@@ -21,6 +21,17 @@
 #include <linux/namei.h>
 #include "fat.h"
 
+static inline unsigned long vfat_d_version(struct dentry *dentry)
+{
+	return (unsigned long) dentry->d_fsdata;
+}
+
+static inline void vfat_d_version_set(struct dentry *dentry,
+				      unsigned long version)
+{
+	dentry->d_fsdata = (void *) version;
+}
+
 /*
  * If new entry was created in the parent, it could create the 8.3
  * alias (the shortname of logname).  So, the parent may have the
@@ -33,7 +44,7 @@ static int vfat_revalidate_shortname(struct dentry *dentry)
 {
 	int ret = 1;
 	spin_lock(&dentry->d_lock);
-	if (dentry->d_time != d_inode(dentry->d_parent)->i_version)
+	if (vfat_d_version(dentry) != d_inode(dentry->d_parent)->i_version)
 		ret = 0;
 	spin_unlock(&dentry->d_lock);
 	return ret;
@@ -759,7 +770,7 @@ static struct dentry *vfat_lookup(struct inode *dir, struct dentry *dentry,
 out:
 	mutex_unlock(&MSDOS_SB(sb)->s_lock);
 	if (!inode)
-		dentry->d_time = dir->i_version;
+		vfat_d_version_set(dentry, dir->i_version);
 	return d_splice_alias(inode, dentry);
 error:
 	mutex_unlock(&MSDOS_SB(sb)->s_lock);
@@ -823,7 +834,7 @@ static int vfat_rmdir(struct inode *dir, struct dentry *dentry)
 	clear_nlink(inode);
 	inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC;
 	fat_detach(inode);
-	dentry->d_time = dir->i_version;
+	vfat_d_version_set(dentry, dir->i_version);
 out:
 	mutex_unlock(&MSDOS_SB(sb)->s_lock);
 
@@ -849,7 +860,7 @@ static int vfat_unlink(struct inode *dir, struct dentry *dentry)
 	clear_nlink(inode);
 	inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC;
 	fat_detach(inode);
-	dentry->d_time = dir->i_version;
+	vfat_d_version_set(dentry, dir->i_version);
 out:
 	mutex_unlock(&MSDOS_SB(sb)->s_lock);
 
-- 
2.5.5

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

* Re: [PATCH 10/12] posix_acl: don't ignore return value of posix_acl_create_masq()
  2016-09-16 12:19 ` [PATCH 10/12] posix_acl: don't ignore return value of posix_acl_create_masq() Miklos Szeredi
@ 2016-09-16 12:45   ` Andreas Grünbacher
  0 siblings, 0 replies; 16+ messages in thread
From: Andreas Grünbacher @ 2016-09-16 12:45 UTC (permalink / raw)
  To: Miklos Szeredi
  Cc: Linux FS-devel Mailing List, Linux Kernel Mailing List, Al Viro,
	Andreas Gruenbacher

2016-09-16 14:19 GMT+02:00 Miklos Szeredi <mszeredi@redhat.com>:
> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
> Cc: Andreas Gruenbacher <agruenba@redhat.com>
> ---
>  fs/posix_acl.c | 11 ++++++-----
>  1 file changed, 6 insertions(+), 5 deletions(-)
>
> diff --git a/fs/posix_acl.c b/fs/posix_acl.c
> index 59d47ab0791a..ea3eb6f3bf1e 100644
> --- a/fs/posix_acl.c
> +++ b/fs/posix_acl.c
> @@ -598,13 +598,14 @@ posix_acl_create(struct inode *dir, umode_t *mode,
>         if (IS_ERR(p))
>                 return PTR_ERR(p);
>
> +       ret = -ENOMEM;
>         clone = posix_acl_clone(p, GFP_NOFS);
>         if (!clone)
> -               goto no_mem;
> +               goto err_release;
>
>         ret = posix_acl_create_masq(clone, mode);
>         if (ret < 0)
> -               goto no_mem_clone;
> +               goto err_release_clone;
>
>         if (ret == 0)
>                 posix_acl_release(clone);
> @@ -618,11 +619,11 @@ posix_acl_create(struct inode *dir, umode_t *mode,
>
>         return 0;
>
> -no_mem_clone:
> +err_release_clone:
>         posix_acl_release(clone);
> -no_mem:
> +err_release:
>         posix_acl_release(p);
> -       return -ENOMEM;
> +       return ret;
>  }
>  EXPORT_SYMBOL_GPL(posix_acl_create);

Indeed, the return value of posix_acl_create_masq shouldn't be ignored
here. posix_acl_create_masq can still only fail when the default ACL
of the parent directory is corrupted as users are prohibited from
setting invalid default ACLs.

Reviewed-by: Andreas Gruenbacher <agruenba@redhat.com>

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

* Re: [PATCH 04/12] fsnotify: support overlayfs
  2016-09-16 12:19 ` [PATCH 04/12] fsnotify: support overlayfs Miklos Szeredi
@ 2016-09-16 16:38   ` Jan Kara
  2016-09-17  6:20     ` Amir Goldstein
  0 siblings, 1 reply; 16+ messages in thread
From: Jan Kara @ 2016-09-16 16:38 UTC (permalink / raw)
  To: Miklos Szeredi
  Cc: linux-fsdevel, Aihua Zhang, linux-kernel, Al Viro, Jan Kara, Eric Paris

On Fri 16-09-16 14:19:23, Miklos Szeredi wrote:
> From: Aihua Zhang <zhangaihua1@huawei.com>
> 
> When an event occurs direct it to the overlay inode instead of the real
> underlying inode.
> 
> This will work even if the file was first on the lower layer and then
> copied up, while the watch is there.  This is because the watch is on the
> overlay inode, which stays the same through the copy-up.
> 
> For filesystems other than overlayfs this is a no-op, except for the
> performance impact of an extra pointer dereferece.
> 
> Verified to work correctly with the inotify/fanotify tests in LTP.
> 
> Signed-off-by: Aihua Zhang <zhangaihua1@huawei.com>
> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
> Cc: Jan Kara <jack@suse.cz>
> Cc: Eric Paris <eparis@redhat.com>
> ---
>  include/linux/fsnotify.h | 14 +++++++++-----
>  1 file changed, 9 insertions(+), 5 deletions(-)
> 
> diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h
> index eed9e853a06f..b8bcc058e031 100644
> --- a/include/linux/fsnotify.h
> +++ b/include/linux/fsnotify.h
> @@ -29,7 +29,11 @@ static inline int fsnotify_parent(struct path *path, struct dentry *dentry, __u3
>  static inline int fsnotify_perm(struct file *file, int mask)
>  {
>  	struct path *path = &file->f_path;
> -	struct inode *inode = file_inode(file);
> +	/*
> +	 * Do not use file_inode() here or anywhere in this file to get the
> +	 * inode.  That would break *notity on overlayfs.
> +	 */
> +	struct inode *inode = path->dentry->d_inode;

So shouldn't we rather have d_backing_inode(path->dentry) here and
everywhere else?

									Honza
-- 
Jan Kara <jack@suse.com>
SUSE Labs, CR

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

* Re: [PATCH 04/12] fsnotify: support overlayfs
  2016-09-16 16:38   ` Jan Kara
@ 2016-09-17  6:20     ` Amir Goldstein
  0 siblings, 0 replies; 16+ messages in thread
From: Amir Goldstein @ 2016-09-17  6:20 UTC (permalink / raw)
  To: Jan Kara
  Cc: Miklos Szeredi, linux-fsdevel, Aihua Zhang, linux-kernel,
	Al Viro, Eric Paris

On Fri, Sep 16, 2016 at 7:38 PM, Jan Kara <jack@suse.cz> wrote:
> On Fri 16-09-16 14:19:23, Miklos Szeredi wrote:
>> From: Aihua Zhang <zhangaihua1@huawei.com>
>>
>> When an event occurs direct it to the overlay inode instead of the real
>> underlying inode.
>>
>> This will work even if the file was first on the lower layer and then
>> copied up, while the watch is there.  This is because the watch is on the
>> overlay inode, which stays the same through the copy-up.
>>
>> For filesystems other than overlayfs this is a no-op, except for the
>> performance impact of an extra pointer dereferece.
>>
>> Verified to work correctly with the inotify/fanotify tests in LTP.
>>
>> Signed-off-by: Aihua Zhang <zhangaihua1@huawei.com>
>> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
>> Cc: Jan Kara <jack@suse.cz>
>> Cc: Eric Paris <eparis@redhat.com>
>> ---
>>  include/linux/fsnotify.h | 14 +++++++++-----
>>  1 file changed, 9 insertions(+), 5 deletions(-)
>>
>> diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h
>> index eed9e853a06f..b8bcc058e031 100644
>> --- a/include/linux/fsnotify.h
>> +++ b/include/linux/fsnotify.h
>> @@ -29,7 +29,11 @@ static inline int fsnotify_parent(struct path *path, struct dentry *dentry, __u3
>>  static inline int fsnotify_perm(struct file *file, int mask)
>>  {
>>       struct path *path = &file->f_path;
>> -     struct inode *inode = file_inode(file);
>> +     /*
>> +      * Do not use file_inode() here or anywhere in this file to get the
>> +      * inode.  That would break *notity on overlayfs.
>> +      */
>> +     struct inode *inode = path->dentry->d_inode;
>
> So shouldn't we rather have d_backing_inode(path->dentry) here and
> everywhere else?

d_backing_inode()'s intention is quite the opposite
it's documented as "Get upper or lower inode we should be using"

So there is no helper to return this "unreal" inode.
In fact, it seems that was the intention of d_inode() helper,
but it won't work for overlayfs.

Miklos just submitted a new helper locks_inode() for 4.9, which does
exactly that.
I suppose it's either another similar helper fsnotify_inode() or find
a better and generic
name for this creature.

IMO, the helper file_dentry(), that Miklos introduced in commit d101a1259
should be renamed to file_backing_dentry() and a new helper file_dentry()
should be used here. i.e. inode = d_inode(file_dentry(file));

Also in this case, I think that an explicit name for the helper to get
the "unreal" dentry
would serve better then a generic name, but I can't think of a better name...

Cheers,
Amir.

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

end of thread, other threads:[~2016-09-17  6:20 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-16 12:19 [PATCH 00/12] misc filesystem patches for 4.9 Miklos Szeredi
2016-09-16 12:19 ` [PATCH 01/12] ima: use file_dentry() Miklos Szeredi
2016-09-16 12:19 ` [PATCH 02/12] vfs: move permission checking into notify_change() for utimes(NULL) Miklos Szeredi
2016-09-16 12:19 ` [PATCH 03/12] vfs: update ovl inode before relatime check Miklos Szeredi
2016-09-16 12:19 ` [PATCH 04/12] fsnotify: support overlayfs Miklos Szeredi
2016-09-16 16:38   ` Jan Kara
2016-09-17  6:20     ` Amir Goldstein
2016-09-16 12:19 ` [PATCH 05/12] locks: fix file locking on overlayfs Miklos Szeredi
2016-09-16 12:19 ` [PATCH 06/12] vfs: make argument of d_real_inode() const Miklos Szeredi
2016-09-16 12:19 ` [PATCH 07/12] vfs: do get_write_access() on upper layer of overlayfs Miklos Szeredi
2016-09-16 12:19 ` [PATCH 08/12] btrfs: use filemap_check_errors() Miklos Szeredi
2016-09-16 12:19 ` [PATCH 09/12] f2fs: " Miklos Szeredi
2016-09-16 12:19 ` [PATCH 10/12] posix_acl: don't ignore return value of posix_acl_create_masq() Miklos Szeredi
2016-09-16 12:45   ` Andreas Grünbacher
2016-09-16 12:19 ` [PATCH 11/12] cifs: don't use ->d_time Miklos Szeredi
2016-09-16 12:19 ` [PATCH 12/12] vfat: " Miklos Szeredi

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