static int dump_seek(struct file *file, loff_t off)
 {
-       if (file->f_op->llseek) {
-               if (file->f_op->llseek(file, off, 0) != off)
+       if (file->f_op->llseek && file->f_op->llseek != no_llseek) {
+               if (file->f_op->llseek(file, off, 1) != off)
                        return 0;
-       } else
-               file->f_pos = off;
+       } else {
+               char *buf = (char *)get_zeroed_page(GFP_KERNEL);
+               if (!buf)
+                       return 0;
+               while (off > 0) {
+                       unsigned long n = off;
+                       if (n > PAGE_SIZE)
+                               n = PAGE_SIZE;
+                       if (!dump_write(file, buf, n))
+                               return 0;
+                       off -= n;
+               }
+               free_page((unsigned long)buf);
+       }
        return 1;
 }
 
        return sz;
 }
 
-#define DUMP_WRITE(addr, nr)   \
-       do { if (!dump_write(file, (addr), (nr))) return 0; } while(0)
-#define DUMP_SEEK(off) \
-       do { if (!dump_seek(file, (off))) return 0; } while(0)
+#define DUMP_WRITE(addr, nr, foffset)  \
+       do { if (!dump_write(file, (addr), (nr))) return 0; *foffset += (nr); } while(0)
 
-static int writenote(struct memelfnote *men, struct file *file)
+static int alignfile(struct file *file, loff_t *foffset)
 {
-       struct elf_note en;
+       char buf[4] = { 0, };
+       DUMP_WRITE(buf, roundup(*foffset, 4) - *foffset, foffset);
+       return 1;
+}
 
+static int writenote(struct memelfnote *men, struct file *file,
+                       loff_t *foffset)
+{
+       struct elf_note en;
        en.n_namesz = strlen(men->name) + 1;
        en.n_descsz = men->datasz;
        en.n_type = men->type;
 
-       DUMP_WRITE(&en, sizeof(en));
-       DUMP_WRITE(men->name, en.n_namesz);
-       /* XXX - cast from long long to long to avoid need for libgcc.a */
-       DUMP_SEEK(roundup((unsigned long)file->f_pos, 4));      /* XXX */
-       DUMP_WRITE(men->data, men->datasz);
-       DUMP_SEEK(roundup((unsigned long)file->f_pos, 4));      /* XXX */
+       DUMP_WRITE(&en, sizeof(en), foffset);
+       DUMP_WRITE(men->name, en.n_namesz, foffset);
+       if (!alignfile(file, foffset))
+               return 0;
+       DUMP_WRITE(men->data, men->datasz, foffset);
+       if (!alignfile(file, foffset))
+               return 0;
 
        return 1;
 }
 #undef DUMP_WRITE
-#undef DUMP_SEEK
 
 #define DUMP_WRITE(addr, nr)   \
        if ((size += (nr)) > limit || !dump_write(file, (addr), (nr))) \
        int i;
        struct vm_area_struct *vma;
        struct elfhdr *elf = NULL;
-       loff_t offset = 0, dataoff;
+       loff_t offset = 0, dataoff, foffset;
        unsigned long limit = current->signal->rlim[RLIMIT_CORE].rlim_cur;
        int numnote;
        struct memelfnote *notes = NULL;
                DUMP_WRITE(&phdr, sizeof(phdr));
        }
 
-       /* Page-align dumped data */
+       foffset = offset;
+
        dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
 
        /* Write program headers for segments dump */
                phdr.p_align = ELF_EXEC_PAGESIZE;
 
                DUMP_WRITE(&phdr, sizeof(phdr));
+               foffset += sizeof(phdr);
        }
 
 #ifdef ELF_CORE_WRITE_EXTRA_PHDRS
 
        /* write out the notes section */
        for (i = 0; i < numnote; i++)
-               if (!writenote(notes + i, file))
+               if (!writenote(notes + i, file, &foffset))
                        goto end_coredump;
 
        /* write out the thread status notes section */
                                list_entry(t, struct elf_thread_status, list);
 
                for (i = 0; i < tmp->num_notes; i++)
-                       if (!writenote(&tmp->notes[i], file))
+                       if (!writenote(&tmp->notes[i], file, &foffset))
                                goto end_coredump;
        }
- 
-       DUMP_SEEK(dataoff);
+
+       /* Align to page */
+       DUMP_SEEK(dataoff - foffset);
 
        for (vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
                unsigned long addr;
 
                        if (get_user_pages(current, current->mm, addr, 1, 0, 1,
                                                &page, &vma) <= 0) {
-                               DUMP_SEEK(file->f_pos + PAGE_SIZE);
+                               DUMP_SEEK(PAGE_SIZE);
                        } else {
                                if (page == ZERO_PAGE(addr)) {
-                                       DUMP_SEEK(file->f_pos + PAGE_SIZE);
+                                       DUMP_SEEK(PAGE_SIZE);
                                } else {
                                        void *kaddr;
                                        flush_cache_page(vma, addr,
        ELF_CORE_WRITE_EXTRA_DATA;
 #endif
 
-       if (file->f_pos != offset) {
-               /* Sanity check */
-               printk(KERN_WARNING
-                      "elf_core_dump: file->f_pos (%Ld) != offset (%Ld)\n",
-                      file->f_pos, offset);
-       }
-
 end_coredump:
        set_fs(fs);
 
 
 #endif
 
 int core_uses_pid;
-char core_pattern[65] = "core";
+char core_pattern[128] = "core";
 int suid_dumpable = 0;
 
 EXPORT_SYMBOL(suid_dumpable);
        int retval = 0;
        int fsuid = current->fsuid;
        int flag = 0;
+       int ispipe = 0;
 
        binfmt = current->binfmt;
        if (!binfmt || !binfmt->core_dump)
        lock_kernel();
        format_corename(corename, core_pattern, signr);
        unlock_kernel();
-       file = filp_open(corename, O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag, 0600);
+       if (corename[0] == '|') {
+               /* SIGPIPE can happen, but it's just never processed */
+               if(call_usermodehelper_pipe(corename+1, NULL, NULL, &file)) {
+                       printk(KERN_INFO "Core dump to %s pipe failed\n",
+                              corename);
+                       goto fail_unlock;
+               }
+               ispipe = 1;
+       } else
+               file = filp_open(corename,
+                                O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE, 0600);
        if (IS_ERR(file))
                goto fail_unlock;
        inode = file->f_dentry->d_inode;
        if (inode->i_nlink > 1)
                goto close_fail;        /* multiple links - don't dump */
-       if (d_unhashed(file->f_dentry))
+       if (!ispipe && d_unhashed(file->f_dentry))
                goto close_fail;
 
-       if (!S_ISREG(inode->i_mode))
+       /* AK: actually i see no reason to not allow this for named pipes etc.,
+          but keep the previous behaviour for now. */
+       if (!ispipe && !S_ISREG(inode->i_mode))
                goto close_fail;
        if (!file->f_op)
                goto close_fail;
        if (!file->f_op->write)
                goto close_fail;
-       if (do_truncate(file->f_dentry, 0, 0, file) != 0)
+       if (!ispipe && do_truncate(file->f_dentry, 0, 0, file) != 0)
                goto close_fail;
 
        retval = binfmt->core_dump(signr, regs, file);