summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-04-04 18:43:49 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2018-04-04 18:43:49 -0700
commit9abf8acea297b4c65f5fa3206e2b8e468e730e84 (patch)
tree03e231d7e785e4cf3ae8849b523cebd1660f57fc /fs
parentac9053d2dcb9e8c3fa35ce458dfca8fddc141680 (diff)
parent4f794097797f551917b68797e39f25fcb17d5b3a (diff)
Merge tag 'tty-4.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty/serial driver updates from Greg KH: "Here is the big set of tty and serial driver patches for 4.17-rc1 Not all that big really, most are just small fixes and additions to existing drivers. There's a bunch of work on the imx serial driver recently for some reason, and a new embedded serial driver added as well. Full details are in the shortlog. All of these have been in the linux-next tree for a while with no reported issues" * tag 'tty-4.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (66 commits) serial: expose buf_overrun count through proc interface serial: mvebu-uart: fix tx lost characters tty: serial: msm_geni_serial: Fix return value check in qcom_geni_serial_probe() tty: serial: msm_geni_serial: Add serial driver support for GENI based QUP 8250-men-mcb: add support for 16z025 and 16z057 powerpc: Mark the variable earlycon_acpi_spcr_enable maybe_unused serial: stm32: fix initialization of RS485 mode ARM: dts: STi: Remove "console=ttyASN" from bootargs for STi boards vt: change SGR 21 to follow the standards serdev: Fix typo in serdev_device_alloc ARM: dts: STi: Fix aliases property name for STi boards tty: st-asc: Update tty alias serial: stm32: add support for RS485 hardware control mode dt-bindings: serial: stm32: add RS485 optional properties selftests: add devpts selftests devpts: comment devpts_mntget() devpts: resolve devpts bind-mounts devpts: hoist out check for DEVPTS_SUPER_MAGIC serial: 8250: Add Nuvoton NPCM UART serial: mxs-auart: disable clks of Alphascale ASM9260 ...
Diffstat (limited to 'fs')
-rw-r--r--fs/devpts/inode.c66
1 files changed, 47 insertions, 19 deletions
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index e31d6ed3ec32..e072e955ce33 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -138,10 +138,6 @@ static int devpts_ptmx_path(struct path *path)
struct super_block *sb;
int err;
- /* Has the devpts filesystem already been found? */
- if (path->mnt->mnt_sb->s_magic == DEVPTS_SUPER_MAGIC)
- return 0;
-
/* Is a devpts filesystem at "pts" in the same directory? */
err = path_pts(path);
if (err)
@@ -156,25 +152,53 @@ static int devpts_ptmx_path(struct path *path)
return 0;
}
+/*
+ * Try to find a suitable devpts filesystem. We support the following
+ * scenarios:
+ * - The ptmx device node is located in the same directory as the devpts
+ * mount where the pts device nodes are located.
+ * This is e.g. the case when calling open on the /dev/pts/ptmx device
+ * node when the devpts filesystem is mounted at /dev/pts.
+ * - The ptmx device node is located outside the devpts filesystem mount
+ * where the pts device nodes are located. For example, the ptmx device
+ * is a symlink, separate device node, or bind-mount.
+ * A supported scenario is bind-mounting /dev/pts/ptmx to /dev/ptmx and
+ * then calling open on /dev/ptmx. In this case a suitable pts
+ * subdirectory can be found in the common parent directory /dev of the
+ * devpts mount and the ptmx bind-mount, after resolving the /dev/ptmx
+ * bind-mount.
+ * If no suitable pts subdirectory can be found this function will fail.
+ * This is e.g. the case when bind-mounting /dev/pts/ptmx to /ptmx.
+ */
struct vfsmount *devpts_mntget(struct file *filp, struct pts_fs_info *fsi)
{
struct path path;
- int err;
+ int err = 0;
path = filp->f_path;
path_get(&path);
- err = devpts_ptmx_path(&path);
+ /* Walk upward while the start point is a bind mount of
+ * a single file.
+ */
+ while (path.mnt->mnt_root == path.dentry)
+ if (follow_up(&path) == 0)
+ break;
+
+ /* devpts_ptmx_path() finds a devpts fs or returns an error. */
+ if ((path.mnt->mnt_sb->s_magic != DEVPTS_SUPER_MAGIC) ||
+ (DEVPTS_SB(path.mnt->mnt_sb) != fsi))
+ err = devpts_ptmx_path(&path);
dput(path.dentry);
- if (err) {
- mntput(path.mnt);
- return ERR_PTR(err);
- }
- if (DEVPTS_SB(path.mnt->mnt_sb) != fsi) {
- mntput(path.mnt);
- return ERR_PTR(-ENODEV);
+ if (!err) {
+ if (DEVPTS_SB(path.mnt->mnt_sb) == fsi)
+ return path.mnt;
+
+ err = -ENODEV;
}
- return path.mnt;
+
+ mntput(path.mnt);
+ return ERR_PTR(err);
}
struct pts_fs_info *devpts_acquire(struct file *filp)
@@ -182,15 +206,19 @@ struct pts_fs_info *devpts_acquire(struct file *filp)
struct pts_fs_info *result;
struct path path;
struct super_block *sb;
- int err;
path = filp->f_path;
path_get(&path);
- err = devpts_ptmx_path(&path);
- if (err) {
- result = ERR_PTR(err);
- goto out;
+ /* Has the devpts filesystem already been found? */
+ if (path.mnt->mnt_sb->s_magic != DEVPTS_SUPER_MAGIC) {
+ int err;
+
+ err = devpts_ptmx_path(&path);
+ if (err) {
+ result = ERR_PTR(err);
+ goto out;
+ }
}
/*