linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	stable@vger.kernel.org, Al Viro <viro@zeniv.linux.org.uk>
Subject: [PATCH 4.12 30/31] dentry name snapshots
Date: Thu,  3 Aug 2017 16:18:00 -0700	[thread overview]
Message-ID: <20170803231738.639864626@linuxfoundation.org> (raw)
In-Reply-To: <20170803231737.202188456@linuxfoundation.org>

4.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Al Viro <viro@zeniv.linux.org.uk>

commit 49d31c2f389acfe83417083e1208422b4091cd9e upstream.

take_dentry_name_snapshot() takes a safe snapshot of dentry name;
if the name is a short one, it gets copied into caller-supplied
structure, otherwise an extra reference to external name is grabbed
(those are never modified).  In either case the pointer to stable
string is stored into the same structure.

dentry must be held by the caller of take_dentry_name_snapshot(),
but may be freely dropped afterwards - the snapshot will stay
until destroyed by release_dentry_name_snapshot().

Intended use:
	struct name_snapshot s;

	take_dentry_name_snapshot(&s, dentry);
	...
	access s.name
	...
	release_dentry_name_snapshot(&s);

Replaces fsnotify_oldname_...(), gets used in fsnotify to obtain the name
to pass down with event.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

---
 fs/dcache.c              |   27 +++++++++++++++++++++++++++
 fs/debugfs/inode.c       |   10 +++++-----
 fs/namei.c               |    8 ++++----
 fs/notify/fsnotify.c     |    8 ++++++--
 include/linux/dcache.h   |    6 ++++++
 include/linux/fsnotify.h |   31 -------------------------------
 6 files changed, 48 insertions(+), 42 deletions(-)

--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -277,6 +277,33 @@ static inline int dname_external(const s
 	return dentry->d_name.name != dentry->d_iname;
 }
 
+void take_dentry_name_snapshot(struct name_snapshot *name, struct dentry *dentry)
+{
+	spin_lock(&dentry->d_lock);
+	if (unlikely(dname_external(dentry))) {
+		struct external_name *p = external_name(dentry);
+		atomic_inc(&p->u.count);
+		spin_unlock(&dentry->d_lock);
+		name->name = p->name;
+	} else {
+		memcpy(name->inline_name, dentry->d_iname, DNAME_INLINE_LEN);
+		spin_unlock(&dentry->d_lock);
+		name->name = name->inline_name;
+	}
+}
+EXPORT_SYMBOL(take_dentry_name_snapshot);
+
+void release_dentry_name_snapshot(struct name_snapshot *name)
+{
+	if (unlikely(name->name != name->inline_name)) {
+		struct external_name *p;
+		p = container_of(name->name, struct external_name, name[0]);
+		if (unlikely(atomic_dec_and_test(&p->u.count)))
+			kfree_rcu(p, u.head);
+	}
+}
+EXPORT_SYMBOL(release_dentry_name_snapshot);
+
 static inline void __d_set_inode_and_type(struct dentry *dentry,
 					  struct inode *inode,
 					  unsigned type_flags)
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -766,7 +766,7 @@ struct dentry *debugfs_rename(struct den
 {
 	int error;
 	struct dentry *dentry = NULL, *trap;
-	const char *old_name;
+	struct name_snapshot old_name;
 
 	trap = lock_rename(new_dir, old_dir);
 	/* Source or destination directories don't exist? */
@@ -781,19 +781,19 @@ struct dentry *debugfs_rename(struct den
 	if (IS_ERR(dentry) || dentry == trap || d_really_is_positive(dentry))
 		goto exit;
 
-	old_name = fsnotify_oldname_init(old_dentry->d_name.name);
+	take_dentry_name_snapshot(&old_name, old_dentry);
 
 	error = simple_rename(d_inode(old_dir), old_dentry, d_inode(new_dir),
 			      dentry, 0);
 	if (error) {
-		fsnotify_oldname_free(old_name);
+		release_dentry_name_snapshot(&old_name);
 		goto exit;
 	}
 	d_move(old_dentry, dentry);
-	fsnotify_move(d_inode(old_dir), d_inode(new_dir), old_name,
+	fsnotify_move(d_inode(old_dir), d_inode(new_dir), old_name.name,
 		d_is_dir(old_dentry),
 		NULL, old_dentry);
-	fsnotify_oldname_free(old_name);
+	release_dentry_name_snapshot(&old_name);
 	unlock_rename(new_dir, old_dir);
 	dput(dentry);
 	return old_dentry;
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -4362,11 +4362,11 @@ int vfs_rename(struct inode *old_dir, st
 {
 	int error;
 	bool is_dir = d_is_dir(old_dentry);
-	const unsigned char *old_name;
 	struct inode *source = old_dentry->d_inode;
 	struct inode *target = new_dentry->d_inode;
 	bool new_is_dir = false;
 	unsigned max_links = new_dir->i_sb->s_max_links;
+	struct name_snapshot old_name;
 
 	if (source == target)
 		return 0;
@@ -4413,7 +4413,7 @@ int vfs_rename(struct inode *old_dir, st
 	if (error)
 		return error;
 
-	old_name = fsnotify_oldname_init(old_dentry->d_name.name);
+	take_dentry_name_snapshot(&old_name, old_dentry);
 	dget(new_dentry);
 	if (!is_dir || (flags & RENAME_EXCHANGE))
 		lock_two_nondirectories(source, target);
@@ -4468,14 +4468,14 @@ out:
 		inode_unlock(target);
 	dput(new_dentry);
 	if (!error) {
-		fsnotify_move(old_dir, new_dir, old_name, is_dir,
+		fsnotify_move(old_dir, new_dir, old_name.name, is_dir,
 			      !(flags & RENAME_EXCHANGE) ? target : NULL, old_dentry);
 		if (flags & RENAME_EXCHANGE) {
 			fsnotify_move(new_dir, old_dir, old_dentry->d_name.name,
 				      new_is_dir, NULL, new_dentry);
 		}
 	}
-	fsnotify_oldname_free(old_name);
+	release_dentry_name_snapshot(&old_name);
 
 	return error;
 }
--- a/fs/notify/fsnotify.c
+++ b/fs/notify/fsnotify.c
@@ -161,16 +161,20 @@ int __fsnotify_parent(const struct path
 	if (unlikely(!fsnotify_inode_watches_children(p_inode)))
 		__fsnotify_update_child_dentry_flags(p_inode);
 	else if (p_inode->i_fsnotify_mask & mask) {
+		struct name_snapshot name;
+
 		/* we are notifying a parent so come up with the new mask which
 		 * specifies these are events which came from a child. */
 		mask |= FS_EVENT_ON_CHILD;
 
+		take_dentry_name_snapshot(&name, dentry);
 		if (path)
 			ret = fsnotify(p_inode, mask, path, FSNOTIFY_EVENT_PATH,
-				       dentry->d_name.name, 0);
+				       name.name, 0);
 		else
 			ret = fsnotify(p_inode, mask, dentry->d_inode, FSNOTIFY_EVENT_INODE,
-				       dentry->d_name.name, 0);
+				       name.name, 0);
+		release_dentry_name_snapshot(&name);
 	}
 
 	dput(parent);
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -591,5 +591,11 @@ static inline struct inode *d_real_inode
 	return d_backing_inode(d_real((struct dentry *) dentry, NULL, 0));
 }
 
+struct name_snapshot {
+	const char *name;
+	char inline_name[DNAME_INLINE_LEN];
+};
+void take_dentry_name_snapshot(struct name_snapshot *, struct dentry *);
+void release_dentry_name_snapshot(struct name_snapshot *);
 
 #endif	/* __LINUX_DCACHE_H */
--- a/include/linux/fsnotify.h
+++ b/include/linux/fsnotify.h
@@ -293,35 +293,4 @@ static inline void fsnotify_change(struc
 	}
 }
 
-#if defined(CONFIG_FSNOTIFY)	/* notify helpers */
-
-/*
- * fsnotify_oldname_init - save off the old filename before we change it
- */
-static inline const unsigned char *fsnotify_oldname_init(const unsigned char *name)
-{
-	return kstrdup(name, GFP_KERNEL);
-}
-
-/*
- * fsnotify_oldname_free - free the name we got from fsnotify_oldname_init
- */
-static inline void fsnotify_oldname_free(const unsigned char *old_name)
-{
-	kfree(old_name);
-}
-
-#else	/* CONFIG_FSNOTIFY */
-
-static inline const char *fsnotify_oldname_init(const unsigned char *name)
-{
-	return NULL;
-}
-
-static inline void fsnotify_oldname_free(const unsigned char *old_name)
-{
-}
-
-#endif	/*  CONFIG_FSNOTIFY */
-
 #endif	/* _LINUX_FS_NOTIFY_H */

  parent reply	other threads:[~2017-08-03 23:18 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-08-03 23:17 [PATCH 4.12 00/31] 4.12.5-stable review Greg Kroah-Hartman
2017-08-03 23:17 ` [PATCH 4.12 01/31] jfs: Dont clear SGID when inheriting ACLs Greg Kroah-Hartman
2017-08-03 23:17 ` [PATCH 4.12 03/31] ALSA: hda - Add missing NVIDIA GPU codec IDs to patch table Greg Kroah-Hartman
2017-08-03 23:17 ` [PATCH 4.12 04/31] ALSA: hda - Add mute led support for HP ProBook 440 G4 Greg Kroah-Hartman
2017-08-03 23:17 ` [PATCH 4.12 05/31] parisc: Prevent TLB speculation on flushed pages on CPUs that only support equivalent aliases Greg Kroah-Hartman
2017-08-03 23:17 ` [PATCH 4.12 06/31] parisc: Extend disabled preemption in copy_user_page Greg Kroah-Hartman
2017-08-03 23:17 ` [PATCH 4.12 07/31] parisc: Suspend lockup detectors before system halt Greg Kroah-Hartman
2017-08-03 23:17 ` [PATCH 4.12 08/31] powerpc/pseries: Fix of_node_put() underflow during reconfig remove Greg Kroah-Hartman
2017-08-03 23:17 ` [PATCH 4.12 09/31] mmc: sunxi: Keep default timing phase settings for new timing mode Greg Kroah-Hartman
2017-08-03 23:17 ` [PATCH 4.12 10/31] NFS: invalidate file size when taking a lock Greg Kroah-Hartman
2017-08-03 23:17 ` [PATCH 4.12 11/31] NFSv4.1: Fix a race where CB_NOTIFY_LOCK fails to wake a waiter Greg Kroah-Hartman
2017-08-03 23:17 ` [PATCH 4.12 12/31] scripts/dtc: dtx_diff - update include dts paths to match build Greg Kroah-Hartman
2017-08-03 23:17 ` [PATCH 4.12 13/31] crypto: brcm - Fix SHA3-512 algorithm failure Greg Kroah-Hartman
2017-08-03 23:17 ` [PATCH 4.12 14/31] crypto: brcm - remove BCM_PDC_MBOX dependency in Kconfig Greg Kroah-Hartman
2017-08-03 23:17 ` [PATCH 4.12 15/31] crypto: authencesn - Fix digest_null crash Greg Kroah-Hartman
2017-08-03 23:17 ` [PATCH 4.12 16/31] KVM: PPC: Book3S HV: Enable TM before accessing TM registers Greg Kroah-Hartman
2017-08-03 23:17 ` [PATCH 4.12 17/31] KVM: PPC: Book3S HV: Fix host crash on changing HPT size Greg Kroah-Hartman
2017-08-03 23:17 ` [PATCH 4.12 18/31] dm integrity: fix inefficient allocation of journal space Greg Kroah-Hartman
2017-08-03 23:17 ` [PATCH 4.12 19/31] dm integrity: test for corrupted disk format during table load Greg Kroah-Hartman
2017-08-03 23:17 ` [PATCH 4.12 20/31] md: remove idx from struct resync_pages Greg Kroah-Hartman
2017-08-03 23:17 ` [PATCH 4.12 21/31] md/raid1: fix writebehind bio clone Greg Kroah-Hartman
2017-08-03 23:17 ` [PATCH 4.12 22/31] md/raid5: add thread_group worker async_tx_issue_pending_all Greg Kroah-Hartman
2017-08-03 23:17 ` [PATCH 4.12 23/31] drm/vmwgfx: Fix gcc-7.1.1 warning Greg Kroah-Hartman
2017-08-03 23:17 ` [PATCH 4.12 24/31] drm/vmwgfx: Limit max desktop dimensions to 8Kx8K Greg Kroah-Hartman
2017-08-03 23:17 ` [PATCH 4.12 25/31] drm/nouveau/disp/nv50-: bump max chans to 21 Greg Kroah-Hartman
2017-08-03 23:17 ` [PATCH 4.12 26/31] drm/nouveau/bar/gf100: fix access to upper half of BAR2 Greg Kroah-Hartman
2017-08-03 23:17 ` [PATCH 4.12 28/31] isdn/i4l: fix buffer overflow Greg Kroah-Hartman
2017-08-03 23:17 ` [PATCH 4.12 29/31] ipmi/watchdog: fix watchdog timeout set on reboot Greg Kroah-Hartman
2017-08-03 23:18 ` Greg Kroah-Hartman [this message]
2017-08-03 23:18 ` [PATCH 4.12 31/31] mmc: tmio-mmc: fix bad pointer math Greg Kroah-Hartman
2017-08-04  4:53 ` [PATCH 4.12 00/31] 4.12.5-stable review Guenter Roeck
2017-08-04 16:27   ` Greg Kroah-Hartman
2017-08-04 20:55 ` Shuah Khan
2017-08-04 21:46   ` Greg Kroah-Hartman

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=20170803231738.639864626@linuxfoundation.org \
    --to=gregkh@linuxfoundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=stable@vger.kernel.org \
    --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).