From: Anton Altaparmakov <aia21@cam.ac.uk>
To: Linus Torvalds <torvalds@osdl.org>
Cc: Al Viro <viro@parcelfarce.linux.theplanet.co.uk>,
Christoph Hellwig <hch@infradead.org>,
vandrove@vc.cvut.cz, Andrew Morton <akpm@osdl.org>,
linware@sh.cvut.cz, fsdevel <linux-fsdevel@vger.kernel.org>,
lkml <linux-kernel@vger.kernel.org>
Subject: Re: Kernel bug: Bad page state: related to generic symlink code and mmap
Date: Fri, 19 Aug 2005 22:20:24 +0100 (BST) [thread overview]
Message-ID: <Pine.LNX.4.60.0508192214240.7312@hermes-1.csi.cam.ac.uk> (raw)
In-Reply-To: <Pine.LNX.4.58.0508191323250.3412@g5.osdl.org>
On Fri, 19 Aug 2005, Linus Torvalds wrote:
> The one thing that strikes me is that we might actually have less pain if
> we just changed the calling convention for follow_link/put_link slightly
> instead of creating a new library function. The existing "page cache"
> thing really _does_ work very well, and would work fine for NFS and ncpfs
> too, if we just allowed an extra cookie to be passed along from
> "follow_link()" to "put_link()".
>
> A patch like this (totally untested, and you'd need to update any
> filesystems that don't use the regular page_follow_link interface) would
> seem to clean up the mess nicely.. The basic change is that follow_link()
> returns a error-pointer cookie instead of just zero or error, and that is
> passed into put_link().
>
> That simple calling convention change solves all problems. It so _happens_
> that any old binary code also continues to work (the cookie will be zero,
> and put_link will ignore it), so it shouldn't even break any unconverted
> stuff (unless they mix using their own functions _and_ using the helpher
> functions, which is of course possible).
>
> The "shouldn't break nonconverted filesystems" makes me think this is a
> safe change. Comments?
>
> NOTE NOTE NOTE! Let me say again that it's untested. It might not break
> nonconverted filesystems, but it equally well migth break even the
> converted ones ;)
>
> Linus
>
> ----
> diff --git a/fs/namei.c b/fs/namei.c
> --- a/fs/namei.c
> +++ b/fs/namei.c
> @@ -501,6 +501,7 @@ struct path {
> static inline int __do_follow_link(struct path *path, struct nameidata *nd)
> {
> int error;
> + void *cookie;
> struct dentry *dentry = path->dentry;
>
> touch_atime(path->mnt, dentry);
> @@ -508,13 +509,15 @@ static inline int __do_follow_link(struc
>
> if (path->mnt == nd->mnt)
> mntget(path->mnt);
> - error = dentry->d_inode->i_op->follow_link(dentry, nd);
> - if (!error) {
> + cookie = dentry->d_inode->i_op->follow_link(dentry, nd);
> + error = PTR_ERR(cookie);
> + if (!IS_ERR(cookie)) {
> char *s = nd_get_link(nd);
> + error = 0;
> if (s)
> error = __vfs_follow_link(nd, s);
> if (dentry->d_inode->i_op->put_link)
> - dentry->d_inode->i_op->put_link(dentry, nd);
> + dentry->d_inode->i_op->put_link(dentry, nd, cookie);
> }
> dput(dentry);
> mntput(path->mnt);
> @@ -2345,14 +2348,17 @@ int generic_readlink(struct dentry *dent
> {
> struct nameidata nd;
> int res;
> + void *cookie;
> +
> nd.depth = 0;
> - res = dentry->d_inode->i_op->follow_link(dentry, &nd);
> - if (!res) {
> + cookie = dentry->d_inode->i_op->follow_link(dentry, &nd);
> + if (!IS_ERR(cookie)) {
> res = vfs_readlink(dentry, buffer, buflen, nd_get_link(&nd));
> if (dentry->d_inode->i_op->put_link)
> - dentry->d_inode->i_op->put_link(dentry, &nd);
> + dentry->d_inode->i_op->put_link(dentry, &nd, cookie);
> + cookie = ERR_PTR(0);
You are throwing away the error return from vfs_readlink(). I suspect you
wanted:
+ cookie = ERR_PTR(res);
> }
> - return res;
> + return PTR_ERR(cookie);
> }
>
> int vfs_follow_link(struct nameidata *nd, const char *link)
> @@ -2395,23 +2401,19 @@ int page_readlink(struct dentry *dentry,
> return res;
> }
>
> -int page_follow_link_light(struct dentry *dentry, struct nameidata *nd)
> +void *page_follow_link_light(struct dentry *dentry, struct nameidata *nd)
> {
> struct page *page;
> nd_set_link(nd, page_getlink(dentry, &page));
> - return 0;
> + return page;
> }
>
> -void page_put_link(struct dentry *dentry, struct nameidata *nd)
> +void page_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie)
> {
> if (!IS_ERR(nd_get_link(nd))) {
> - struct page *page;
> - page = find_get_page(dentry->d_inode->i_mapping, 0);
> - if (!page)
> - BUG();
> + struct page *page = cookie;
> kunmap(page);
> page_cache_release(page);
> - page_cache_release(page);
> }
> }
>
> diff --git a/include/linux/fs.h b/include/linux/fs.h
> --- a/include/linux/fs.h
> +++ b/include/linux/fs.h
> @@ -993,8 +993,8 @@ struct inode_operations {
> int (*rename) (struct inode *, struct dentry *,
> struct inode *, struct dentry *);
> int (*readlink) (struct dentry *, char __user *,int);
> - int (*follow_link) (struct dentry *, struct nameidata *);
> - void (*put_link) (struct dentry *, struct nameidata *);
> + void * (*follow_link) (struct dentry *, struct nameidata *);
> + void (*put_link) (struct dentry *, struct nameidata *, void *);
> void (*truncate) (struct inode *);
> int (*permission) (struct inode *, int, struct nameidata *);
> int (*setattr) (struct dentry *, struct iattr *);
> @@ -1602,8 +1602,8 @@ extern struct file_operations generic_ro
> extern int vfs_readlink(struct dentry *, char __user *, int, const char *);
> extern int vfs_follow_link(struct nameidata *, const char *);
> extern int page_readlink(struct dentry *, char __user *, int);
> -extern int page_follow_link_light(struct dentry *, struct nameidata *);
> -extern void page_put_link(struct dentry *, struct nameidata *);
> +extern void *page_follow_link_light(struct dentry *, struct nameidata *);
> +extern void page_put_link(struct dentry *, struct nameidata *, void *);
> extern int page_symlink(struct inode *inode, const char *symname, int len);
> extern struct inode_operations page_symlink_inode_operations;
> extern int generic_readlink(struct dentry *, char __user *, int);
Best regards,
Anton
--
Anton Altaparmakov <aia21 at cam.ac.uk> (replace at with @)
Unix Support, Computing Service, University of Cambridge, CB2 3QH, UK
Linux NTFS maintainer / IRC: #ntfs on irc.freenode.net
WWW: http://linux-ntfs.sf.net/ & http://www-stu.christs.cam.ac.uk/~aia21/
next prev parent reply other threads:[~2005-08-19 21:20 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-08-19 11:14 Kernel bug: Bad page state: related to generic symlink code and mmap Anton Altaparmakov
2005-08-19 14:20 ` Al Viro
2005-08-19 15:44 ` Anton Altaparmakov
2005-08-19 15:58 ` Al Viro
2005-08-19 16:07 ` Linus Torvalds
2005-08-19 16:21 ` Al Viro
2005-08-19 16:21 ` Linus Torvalds
2005-08-19 16:43 ` Linus Torvalds
2005-08-19 16:53 ` Al Viro
2005-08-19 18:02 ` Al Viro
2005-08-19 18:00 ` Christoph Hellwig
2005-08-19 19:38 ` Al Viro
2005-08-19 19:41 ` Matthew Wilcox
2005-08-19 19:43 ` Al Viro
2005-08-19 21:19 ` Christoph Hellwig
2005-08-19 20:35 ` Linus Torvalds
2005-08-19 21:20 ` Anton Altaparmakov [this message]
2005-08-19 21:35 ` Linus Torvalds
2005-08-19 21:42 ` Al Viro
2005-08-19 19:16 ` Mika Penttilä
2005-08-19 19:40 ` Al Viro
2005-08-19 19:50 ` Mika Penttilä
2005-08-19 20:46 ` Anton Altaparmakov
2005-08-19 20:55 ` Linus Torvalds
2005-08-19 21:39 ` Anton Altaparmakov
2005-08-19 22:04 ` Linus Torvalds
2005-08-19 23:15 ` Al Viro
2005-08-19 23:17 ` Al Viro
2005-08-20 1:08 ` Linus Torvalds
2005-08-20 1:15 ` Al Viro
2005-08-20 12:49 ` Anton Altaparmakov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Pine.LNX.4.60.0508192214240.7312@hermes-1.csi.cam.ac.uk \
--to=aia21@cam.ac.uk \
--cc=akpm@osdl.org \
--cc=hch@infradead.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linware@sh.cvut.cz \
--cc=torvalds@osdl.org \
--cc=vandrove@vc.cvut.cz \
--cc=viro@parcelfarce.linux.theplanet.co.uk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).