diff --git a/cr-restore.c b/cr-restore.c index 26dbe539f..309a54895 100644 --- a/cr-restore.c +++ b/cr-restore.c @@ -55,6 +55,7 @@ #include "tty.h" #include "cpu.h" #include "fpu.h" +#include "file-lock.h" #include "protobuf.h" #include "protobuf/sa.pb-c.h" @@ -599,6 +600,9 @@ static int restore_one_alive_task(int pid, CoreEntry *core) if (prepare_fs(pid)) return -1; + if (prepare_file_locks(pid)) + return -1; + if (prepare_sigactions(pid)) return -1; diff --git a/file-lock.c b/file-lock.c index 3d4183d1b..80a0c8f34 100644 --- a/file-lock.c +++ b/file-lock.c @@ -1,5 +1,8 @@ #include #include +#include +#include +#include #include "file-lock.h" @@ -37,3 +40,102 @@ int dump_one_file_lock(FileLockEntry *fle, const struct cr_fdset *fdset) return pb_write_one(fdset_fd(fdset, CR_FD_FILE_LOCKS), fle, PB_FILE_LOCK); } + +static int restore_file_lock(FileLockEntry *fle) +{ + int ret = -1; + unsigned int cmd; + + if (fle->flag & FL_FLOCK) { + if (fle->type & LOCK_MAND) { + cmd = fle->type; + } else if (fle->type == F_RDLCK) { + cmd = LOCK_SH; + } else if (fle->type == F_WRLCK) { + cmd = LOCK_EX; + } else if (fle->type == F_UNLCK) { + cmd = LOCK_UN; + } else { + pr_err("Unknow flock type!\n"); + goto err; + } + + pr_info("(flock)flag: %d, type: %d, cmd: %d, pid: %d, fd: %d\n", + fle->flag, fle->type, cmd, fle->pid, fle->fd); + + ret = flock(fle->fd, cmd); + if (ret < 0) { + pr_err("Can not set flock!\n"); + goto err; + } + } else if (fle->flag & FL_POSIX) { + struct flock flk; + memset(&flk, 0, sizeof(flk)); + + flk.l_whence = SEEK_SET; + flk.l_start = fle->start; + flk.l_len = fle->len; + flk.l_pid = fle->pid; + flk.l_type = fle->type; + + pr_info("(posix)flag: %d, type: %d, pid: %d, fd: %d, " + "start: %8lx, len: %8lx\n", + fle->flag, fle->type, fle->pid, fle->fd, + fle->start, fle->len); + + ret = fcntl(fle->fd, F_SETLKW, &flk); + if (ret < 0) { + pr_err("Can not set posix lock!\n"); + goto err; + } + } else { + pr_err("Unknow file lock style!\n"); + goto err; + } + + return 0; +err: + return ret; +} + +static int restore_file_locks(int pid) +{ + int fd, ret = -1; + FileLockEntry *fle; + + fd = open_image_ro(CR_FD_FILE_LOCKS, pid); + if (fd < 0) { + if (errno == ENOENT) + return 0; + else + return -1; + } + + while (1) { + ret = pb_read_one_eof(fd, &fle, PB_FILE_LOCK); + if (ret <= 0) + break; + + ret = restore_file_lock(fle); + file_lock_entry__free_unpacked(fle, NULL); + + if (ret) + goto err; + } + + close_safe(&fd); + return 0; +err: + close_safe(&fd); + return ret; +} + +int prepare_file_locks(int pid) +{ + if (!opts.handle_file_locks) + return 0; + + pr_info("Restore file locks.\n"); + + return restore_file_locks(pid); +} diff --git a/include/file-lock.h b/include/file-lock.h index d6d2397a5..dddc808f4 100644 --- a/include/file-lock.h +++ b/include/file-lock.h @@ -16,6 +16,12 @@ #endif /* operations for bsd flock(), also used by the kernel implementation */ +#define LOCK_SH 1 /* shared lock */ +#define LOCK_EX 2 /* exclusive lock */ +#define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +#define LOCK_UN 8 /* remove lock */ + #define LOCK_MAND 32 /* This is a mandatory flock ... */ #define LOCK_READ 64 /* which allows concurrent read operations */ #define LOCK_WRITE 128 /* which allows concurrent write operations */ @@ -42,4 +48,6 @@ extern struct file_lock *alloc_file_lock(void); extern void free_file_locks(void); extern int dump_one_file_lock(FileLockEntry *fle, const struct cr_fdset *fdset); +extern int prepare_file_locks(int pid); + #endif /* __FILE_LOCK_H__ */