Re: commit 0eead9ab breaks ia64 build

From: Linus Torvalds
Date: Thu Oct 14 2010 - 17:11:31 EST


On Thu, Oct 14, 2010 at 1:58 PM, Tony Luck <tony.luck@xxxxxxxxx> wrote:
> Just pulled Linus latest and get these errors on ia64 build:
>
> In file included from arch/ia64/kernel/elfcore.c:2:
> include/linux/coredump.h: In function ‘dump_write’:
> include/linux/coredump.h:14: error: implicit declaration of function ‘access_ok’
> include/linux/coredump.h:14: error: ‘VERIFY_READ’ undeclared (first
> use in this function)
>
> I guess I have to start juggling some #includes ... anyone else have problems?

Hmm. I thought that <linux/mm.h> would get it, but apparently not -
we'd need <asm/uaccess.h>.

I also (as I commented in the commit) suspect that we shouldn't do the
raw '->write()' call AT ALL, and that was always wrong. So another way
of fixing the problem with the missing access_ok() is to just use
vfs_write(), which does everything right. The reason I didn't do it is
that I suspect we shouldn't count core-dumping as a "write", so the
statistics done by vfs_write() are probably wrong.

Anyway, the real problem is that those functions really shouldn't be
inline functions to begin with. They're doing function calls, they
aren't critical, and dump_seek() in particular is too large by far. So
I suspect the proper fix is to just uninline them and put them in
fs/exec.c as real functions.

IOW, like the attached. Does that work for you?

Linus
fs/exec.c | 38 ++++++++++++++++++++++++++++++++++++++
include/linux/coredump.h | 34 ++--------------------------------
2 files changed, 40 insertions(+), 32 deletions(-)

diff --git a/fs/exec.c b/fs/exec.c
index 828dd24..03278c9 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -2014,3 +2014,41 @@ fail_creds:
fail:
return;
}
+
+/*
+ * Core dumping helper functions. These are the only things you should
+ * do on a core-file: use only these functions to write out all the
+ * necessary info.
+ */
+int dump_write(struct file *file, const void *addr, int nr)
+{
+ return access_ok(VERIFY_READ, addr, nr) && file->f_op->write(file, addr, nr, &file->f_pos) == nr;
+}
+
+int dump_seek(struct file *file, loff_t off)
+{
+ int ret = 1;
+
+ if (file->f_op->llseek && file->f_op->llseek != no_llseek) {
+ if (file->f_op->llseek(file, off, SEEK_CUR) < 0)
+ return 0;
+ } 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)) {
+ ret = 0;
+ break;
+ }
+ off -= n;
+ }
+ free_page((unsigned long)buf);
+ }
+ return ret;
+}
diff --git a/include/linux/coredump.h b/include/linux/coredump.h
index 59579cf..ba4b85a 100644
--- a/include/linux/coredump.h
+++ b/include/linux/coredump.h
@@ -9,37 +9,7 @@
* These are the only things you should do on a core-file: use only these
* functions to write out all the necessary info.
*/
-static inline int dump_write(struct file *file, const void *addr, int nr)
-{
- return access_ok(VERIFY_READ, addr, nr) && file->f_op->write(file, addr, nr, &file->f_pos) == nr;
-}
-
-static inline int dump_seek(struct file *file, loff_t off)
-{
- int ret = 1;
-
- if (file->f_op->llseek && file->f_op->llseek != no_llseek) {
- if (file->f_op->llseek(file, off, SEEK_CUR) < 0)
- return 0;
- } 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)) {
- ret = 0;
- break;
- }
- off -= n;
- }
- free_page((unsigned long)buf);
- }
- return ret;
-}
+extern int dump_write(struct file *file, const void *addr, int nr);
+extern int dump_seek(struct file *file, loff_t off);

#endif /* _LINUX_COREDUMP_H */