[CRIU] [PATCH 1/2] tty: Add restoration of locked/exclusive ptys
Cyrill Gorcunov
gorcunov at openvz.org
Wed Sep 5 06:50:04 EDT 2012
Since opening locked/exclusive ptys do return
different error code we can figure out what
exactly tty flag the peer has.
Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
include/tty.h | 3 ++
protobuf/tty.proto | 6 ++++
tty.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++-----
3 files changed, 77 insertions(+), 8 deletions(-)
diff --git a/include/tty.h b/include/tty.h
index 8457270..8a06bad 100644
--- a/include/tty.h
+++ b/include/tty.h
@@ -13,6 +13,9 @@
#endif
#define PTS_FMT "/dev/pts/%d"
+#define TTY_LOCKED (1 << 0)
+#define TTY_EXCLUSIVE (1 << 1)
+
extern int dump_tty(struct fd_parms *p, int lfd, const struct cr_fdset *set);
extern int collect_tty(void);
extern int tty_is_master(struct fdinfo_list_entry *le);
diff --git a/protobuf/tty.proto b/protobuf/tty.proto
index 8f497dc..38adab2 100644
--- a/protobuf/tty.proto
+++ b/protobuf/tty.proto
@@ -31,6 +31,12 @@ message tty_file_entry {
required uint64 pos = 5;
required uint64 rdev = 6;
required fown_entry fown = 7;
+
+ /*
+ * Bits
+ * 0 - locked
+ * 1 - exclusive
+ */
required uint32 tty_flags = 8;
enum Type {
diff --git a/tty.c b/tty.c
index b4e89bc..8ac61f7 100644
--- a/tty.c
+++ b/tty.c
@@ -81,9 +81,6 @@
* restore the master end might be already closed for any reason so
* to resolve such problem we open a fake master peer with proper index
* and hook a slave on it, then we close master peer.
- *
- * - Find a way to fetch tty flags from the kernel (locked/exclusive)
- * and save it in tty_flags.
*/
#undef LOG_PREFIX
@@ -259,11 +256,6 @@ static int pty_open_ptmx_index(int flags, int index)
return ret;
}
-/*
- * FIXME Need to find a way to figure out if master
- * is in locked state when being dumped. If so, need
- * to re-lock it on restore.
- */
static int unlock_pty_master(int master)
{
const int lock = 0;
@@ -281,6 +273,58 @@ static int unlock_pty_master(int master)
return 0;
}
+static int lock_pty_master(int master)
+{
+ const int lock = 1;
+
+ if (ioctl(master, TIOCSPTLCK, &lock)) {
+ pr_err("Unable to lock pty master device %d\n", master);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int set_exclusive_pty_master(int master)
+{
+ if (ioctl(master, TIOCEXCL)) {
+ pr_err("Unable to make pty master exclusive %d\n", master);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int get_pty_flags(int index, unsigned int *flags)
+{
+ char pts_name[64];
+ int ret = 0, fd;
+
+ *flags = 0;
+
+ snprintf(pts_name, sizeof(pts_name), PTS_FMT, index);
+
+ fd = open(pts_name, O_RDONLY);
+ if (fd < 0) {
+ switch (errno) {
+ case EIO:
+ *flags |= TTY_LOCKED;
+ break;
+ case EBUSY:
+ *flags |= TTY_EXCLUSIVE;
+ break;
+ default:
+ pr_perror("Can't open %s to obtain flags",
+ pts_name);
+ ret = -1;
+ break;
+ }
+ } else
+ close(fd);
+
+ return ret;
+}
+
static int tty_get_sid(int fd)
{
int sid, ret;
@@ -498,6 +542,11 @@ static int pty_open_ptmx(struct tty_file_info *info)
if (pty_open_slaves(info))
goto err;
+ if (info->tfe->tty_flags & TTY_LOCKED)
+ lock_pty_master(master);
+ else if (info->tfe->tty_flags & TTY_EXCLUSIVE)
+ set_exclusive_pty_master(master);
+
return master;
err:
close_safe(&master);
@@ -676,6 +725,7 @@ static int dump_control_pty(int index, pid_t sid, pid_t prgp)
pr_info("Dump control terminal for %d\n", sid);
snprintf(path, sizeof(path), "/dev/pts/%d", index);
+
fd = open(path, O_RDONLY);
if (fd < 0) {
pr_err("Can't open terminal %s\n", path);
@@ -760,9 +810,19 @@ static int __dump_one_pty(int lfd, u32 id, const struct fd_parms *p, pid_t sid,
if (sid < 0 || prgp < 0)
return -1;
+ /*
+ * Also figure out the flags master pty has.
+ */
+ if (get_pty_flags(pty.index, &e.tty_flags))
+ return -1;
+
if (sid) {
+ if (e.tty_flags & TTY_LOCKED)
+ unlock_pty_master(lfd);
if (dump_control_pty(pty.index, sid, prgp))
return -1;
+ if (e.tty_flags & TTY_LOCKED)
+ lock_pty_master(lfd);
}
}
--
1.7.7.6
More information about the CRIU
mailing list