From 6b2553918d8b4e6de9853fd6315bec7271a2e592 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 17 Nov 2015 10:20:54 -0500 Subject: replace ->follow_link() with new method that could stay in RCU mode new method: ->get_link(); replacement of ->follow_link(). The differences are: * inode and dentry are passed separately * might be called both in RCU and non-RCU mode; the former is indicated by passing it a NULL dentry. * when called that way it isn't allowed to block and should return ERR_PTR(-ECHILD) if it needs to be called in non-RCU mode. It's a flagday change - the old method is gone, all in-tree instances converted. Conversion isn't hard; said that, so far very few instances do not immediately bail out when called in RCU mode. That'll change in the next commits. Signed-off-by: Al Viro --- fs/kernfs/symlink.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'fs/kernfs') diff --git a/fs/kernfs/symlink.c b/fs/kernfs/symlink.c index db27252..ffae857 100644 --- a/fs/kernfs/symlink.c +++ b/fs/kernfs/symlink.c @@ -112,10 +112,15 @@ static int kernfs_getlink(struct dentry *dentry, char *path) return error; } -static const char *kernfs_iop_follow_link(struct dentry *dentry, void **cookie) +static const char *kernfs_iop_get_link(struct dentry *dentry, + struct inode *inode, void **cookie) { int error = -ENOMEM; - unsigned long page = get_zeroed_page(GFP_KERNEL); + unsigned long page; + + if (!dentry) + return ERR_PTR(-ECHILD); + page = get_zeroed_page(GFP_KERNEL); if (!page) return ERR_PTR(-ENOMEM); error = kernfs_getlink(dentry, (char *)page); @@ -132,7 +137,7 @@ const struct inode_operations kernfs_symlink_iops = { .getxattr = kernfs_iop_getxattr, .listxattr = kernfs_iop_listxattr, .readlink = generic_readlink, - .follow_link = kernfs_iop_follow_link, + .get_link = kernfs_iop_get_link, .put_link = free_page_put_link, .setattr = kernfs_iop_setattr, .getattr = kernfs_iop_getattr, -- cgit v1.1 From cd3417c8fc9504cc1afe944515f338aff9ec286b Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 29 Dec 2015 16:03:53 -0500 Subject: kill free_page_put_link() all callers are better off with kfree_put_link() Signed-off-by: Al Viro --- fs/kernfs/symlink.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'fs/kernfs') diff --git a/fs/kernfs/symlink.c b/fs/kernfs/symlink.c index ffae857..f9efdae 100644 --- a/fs/kernfs/symlink.c +++ b/fs/kernfs/symlink.c @@ -116,19 +116,19 @@ static const char *kernfs_iop_get_link(struct dentry *dentry, struct inode *inode, void **cookie) { int error = -ENOMEM; - unsigned long page; + char *page; if (!dentry) return ERR_PTR(-ECHILD); - page = get_zeroed_page(GFP_KERNEL); + page = kzalloc(PAGE_SIZE, GFP_KERNEL); if (!page) return ERR_PTR(-ENOMEM); - error = kernfs_getlink(dentry, (char *)page); + error = kernfs_getlink(dentry, page); if (unlikely(error < 0)) { - free_page((unsigned long)page); + kfree(page); return ERR_PTR(error); } - return *cookie = (char *)page; + return *cookie = page; } const struct inode_operations kernfs_symlink_iops = { @@ -138,7 +138,7 @@ const struct inode_operations kernfs_symlink_iops = { .listxattr = kernfs_iop_listxattr, .readlink = generic_readlink, .get_link = kernfs_iop_get_link, - .put_link = free_page_put_link, + .put_link = kfree_put_link, .setattr = kernfs_iop_setattr, .getattr = kernfs_iop_getattr, .permission = kernfs_iop_permission, -- cgit v1.1 From fceef393a538134f03b778c5d2519e670269342f Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 29 Dec 2015 15:58:39 -0500 Subject: switch ->get_link() to delayed_call, kill ->put_link() Signed-off-by: Al Viro --- fs/kernfs/symlink.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'fs/kernfs') diff --git a/fs/kernfs/symlink.c b/fs/kernfs/symlink.c index f9efdae..117b8b3 100644 --- a/fs/kernfs/symlink.c +++ b/fs/kernfs/symlink.c @@ -113,22 +113,24 @@ static int kernfs_getlink(struct dentry *dentry, char *path) } static const char *kernfs_iop_get_link(struct dentry *dentry, - struct inode *inode, void **cookie) + struct inode *inode, + struct delayed_call *done) { - int error = -ENOMEM; - char *page; + char *body; + int error; if (!dentry) return ERR_PTR(-ECHILD); - page = kzalloc(PAGE_SIZE, GFP_KERNEL); - if (!page) + body = kzalloc(PAGE_SIZE, GFP_KERNEL); + if (!body) return ERR_PTR(-ENOMEM); - error = kernfs_getlink(dentry, page); + error = kernfs_getlink(dentry, body); if (unlikely(error < 0)) { - kfree(page); + kfree(body); return ERR_PTR(error); } - return *cookie = page; + set_delayed_call(done, kfree_link, body); + return body; } const struct inode_operations kernfs_symlink_iops = { @@ -138,7 +140,6 @@ const struct inode_operations kernfs_symlink_iops = { .listxattr = kernfs_iop_listxattr, .readlink = generic_readlink, .get_link = kernfs_iop_get_link, - .put_link = kfree_put_link, .setattr = kernfs_iop_setattr, .getattr = kernfs_iop_getattr, .permission = kernfs_iop_permission, -- cgit v1.1