From e757f81e26b0fa9fb2b6a1192151ba6ceb4002d2 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Fri, 29 Jun 2007 23:40:00 +0000 Subject: [PATCH] Flag the checkpoint descriptor so on restore we can identify it and use the descriptor for the restore rather then trying to look up the original checkpoint file. This issue occurs when a program calls sys_checkpoint() manually. This allows a checkpoint-resume to be done on a copied checkpoint file, or a gzipped (then gunzipped) checkpoint file, etc. The original checkpoint file no longer needs to remain intact. Requested-by: _why --- sys/kern/imgact_elf.c | 28 ++++++++++++++++++--------- sys/kern/kern_checkpoint.c | 47 ++++++++++++++++++++++++++++++++-------------- sys/sys/ckpt.h | 7 +++++-- 3 files changed, 57 insertions(+), 25 deletions(-) diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c index b70b580f36..8a7ac0a04f 100644 --- a/sys/kern/imgact_elf.c +++ b/sys/kern/imgact_elf.c @@ -27,7 +27,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/kern/imgact_elf.c,v 1.73.2.13 2002/12/28 19:49:41 dillon Exp $ - * $DragonFly: src/sys/kern/imgact_elf.c,v 1.51 2007/06/07 23:14:25 dillon Exp $ + * $DragonFly: src/sys/kern/imgact_elf.c,v 1.52 2007/06/29 23:40:00 dillon Exp $ */ #include @@ -900,12 +900,13 @@ static int each_segment (struct proc *, segment_callback, void *, int); static int elf_corehdr (struct lwp *, int, struct file *, struct ucred *, int, elf_buf_t); static int elf_puthdr (struct lwp *, elf_buf_t, const prstatus_t *, - const prfpregset_t *, const prpsinfo_t *, int); + const prfpregset_t *, const prpsinfo_t *, int, + struct file *); static int elf_putnote (elf_buf_t, const char *, int, const void *, size_t); static int elf_putsigs(struct lwp *, elf_buf_t); static int elf_puttextvp(struct proc *, elf_buf_t); -static int elf_putfiles(struct proc *, elf_buf_t); +static int elf_putfiles(struct proc *, elf_buf_t, struct file *); extern int osreldate; @@ -963,7 +964,7 @@ generic_elf_coredump(struct lwp *lp, int sig, struct file *fp, off_t limit) * size is calculated. */ bzero(&target, sizeof(target)); - elf_puthdr(lp, &target, NULL, NULL, NULL, seginfo.count); + elf_puthdr(lp, &target, NULL, NULL, NULL, seginfo.count, fp); if (target.off + seginfo.vsize >= limit) return (EFAULT); @@ -1258,8 +1259,12 @@ elf_corehdr(struct lwp *lp, int sig, struct file *fp, struct ucred *cred, int nu /* XXX - We don't fill in the command line arguments properly yet. */ strncpy(psinfo->pr_psargs, p->p_comm, PRARGSZ); - /* Fill in the header. */ - error = elf_puthdr(lp, target, status, fpregset, psinfo, numsegs); + /* + * Fill in the header. The fp is passed so we can detect and flag + * a checkpoint file pointer within the core file itself, because + * it may not be restored from the same file handle. + */ + error = elf_puthdr(lp, target, status, fpregset, psinfo, numsegs, fp); kfree(tempdata, M_TEMP); @@ -1273,7 +1278,8 @@ elf_corehdr(struct lwp *lp, int sig, struct file *fp, struct ucred *cred, int nu static int elf_puthdr(struct lwp *lp, elf_buf_t target, const prstatus_t *status, - const prfpregset_t *fpregset, const prpsinfo_t *psinfo, int numsegs) + const prfpregset_t *fpregset, const prpsinfo_t *psinfo, int numsegs, + struct file *fp) { struct proc *p = lp->lwp_proc; int error = 0; @@ -1315,7 +1321,7 @@ elf_puthdr(struct lwp *lp, elf_buf_t target, const prstatus_t *status, if (error == 0) error = elf_putsigs(lp, target); if (error == 0) - error = elf_putfiles(p, target); + error = elf_putfiles(p, target, fp); /* * Align up to a page boundary for the program segments. The @@ -1423,7 +1429,7 @@ elf_putsigs(struct lwp *lp, elf_buf_t target) } static int -elf_putfiles(struct proc *p, elf_buf_t target) +elf_putfiles(struct proc *p, elf_buf_t target, struct file *ckfp) { int error = 0; int i; @@ -1464,6 +1470,10 @@ elf_putfiles(struct proc *p, elf_buf_t target) cfi->cfi_type = fp->f_type; cfi->cfi_flags = fp->f_flag; cfi->cfi_offset = fp->f_offset; + cfi->cfi_ckflags = 0; + + if (fp == ckfp) + cfi->cfi_ckflags |= CKFIF_ISCKPTFD; /* f_count and f_msgcount should not be saved/restored */ /* XXX save cred info */ diff --git a/sys/kern/kern_checkpoint.c b/sys/kern/kern_checkpoint.c index 4e23340e88..bcf0880491 100644 --- a/sys/kern/kern_checkpoint.c +++ b/sys/kern/kern_checkpoint.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/kern/kern_checkpoint.c,v 1.18 2007/02/25 23:17:12 corecode Exp $ + * $DragonFly: src/sys/kern/kern_checkpoint.c,v 1.19 2007/06/29 23:40:00 dillon Exp $ */ #include @@ -161,14 +161,14 @@ elf_getphdrs(struct file *fp, Elf_Phdr *phdr, size_t nbyte) PRINTF(("reading phdrs section\n")); if ((error = read_check(fp, phdr, nbyte)) != 0) goto done; - kprintf("headers section:\n"); + PRINTF(("headers section:\n")); for (i = 0; i < nheaders; i++) { - kprintf("entry type: %d\n", phdr[i].p_type); - kprintf("file offset: %d\n", phdr[i].p_offset); - kprintf("virt address: %p\n", (uint32_t *)phdr[i].p_vaddr); - kprintf("file size: %d\n", phdr[i].p_filesz); - kprintf("memory size: %d\n", phdr[i].p_memsz); - kprintf("\n"); + PRINTF(("entry type: %d\n", phdr[i].p_type)); + PRINTF(("file offset: %d\n", phdr[i].p_offset)); + PRINTF(("virt address: %p\n", (uint32_t *)phdr[i].p_vaddr)); + PRINTF(("file size: %d\n", phdr[i].p_filesz)); + PRINTF(("memory size: %d\n", phdr[i].p_memsz)); + PRINTF(("\n")); } done: return error; @@ -429,7 +429,10 @@ mmap_phdr(struct file *fp, Elf_Phdr *phdr) return error; } - +/* + * Load memory mapped segments. The segments are backed by the checkpoint + * file. + */ static int elf_loadphdrs(struct file *fp, Elf_Phdr *phdr, int numsegs) { @@ -624,12 +627,28 @@ elf_getfiles(struct proc *p, struct file *fp) if (cfi->cfi_index < 0) continue; - if ((error = ckpt_fhtovp(&cfi->cfi_fh, &vp)) != 0) - break; - if ((error = fp_vpopen(vp, OFLAGS(cfi->cfi_flags), &tempfp)) != 0) { - vput(vp); - break; + /* + * Restore a saved file descriptor. If CKFIF_ISCKPTFD is + * set the descriptor represents the checkpoint file itself, + * probably due to the user calling sys_checkpoint(). We + * want to use the fp being used to restore the checkpoint + * instead of trying to restore the original filehandle. + */ + if (cfi->cfi_ckflags & CKFIF_ISCKPTFD) { + fhold(fp); + tempfp = fp; + error = 0; + } else { + error = ckpt_fhtovp(&cfi->cfi_fh, &vp); + if (error == 0) { + error = fp_vpopen(vp, OFLAGS(cfi->cfi_flags), + &tempfp); + if (error) + vput(vp); + } } + if (error) + break; tempfp->f_offset = cfi->cfi_offset; /* diff --git a/sys/sys/ckpt.h b/sys/sys/ckpt.h index 393ac50352..1fe0f0c109 100644 --- a/sys/sys/ckpt.h +++ b/sys/sys/ckpt.h @@ -22,7 +22,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/sys/ckpt.h,v 1.10 2007/02/25 23:17:13 corecode Exp $ + * $DragonFly: src/sys/sys/ckpt.h,v 1.11 2007/06/29 23:39:58 dillon Exp $ */ #ifndef _SYS_CKPT_H_ #define _SYS_CKPT_H_ @@ -69,9 +69,12 @@ struct ckpt_fileinfo { off_t cfi_offset; /* saved f_offset */ fhandle_t cfi_fh; int cfi_type; - int cfi_reserved[7]; + int cfi_ckflags; + int cfi_reserved[6]; }; +#define CKFIF_ISCKPTFD 0x0001 + struct ckpt_siginfo { int csi_ckptpisz; struct sigacts csi_sigacts; -- 2.11.4.GIT