From 8fa9dd24667f2d6997ec21341019657342859d31 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 23 Mar 2015 13:37:40 +1100 Subject: VFS/namei: make the use of touch_atime() in get_link() RCU-safe. touch_atime is not RCU-safe, and so cannot be called on an RCU walk. However, in situations where RCU-walk makes a difference, the symlink will likely to accessed much more often than it is useful to update the atime. So split out the test of "Does the atime actually need to be updated" into atime_needs_update(), and have get_link() unlazy if it finds that it will need to do that update. Signed-off-by: NeilBrown Signed-off-by: Al Viro --- fs/namei.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'fs/namei.c') diff --git a/fs/namei.c b/fs/namei.c index 47b20086e9f3..d9f77ff60b55 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -966,13 +966,19 @@ const char *get_link(struct nameidata *nd) int error; const char *res; - if (nd->flags & LOOKUP_RCU) { + if (!(nd->flags & LOOKUP_RCU)) { + touch_atime(&last->link); + cond_resched(); + } else if (atime_needs_update(&last->link, inode)) { if (unlikely(unlazy_walk(nd, NULL, 0))) return ERR_PTR(-ECHILD); + touch_atime(&last->link); } - cond_resched(); - touch_atime(&last->link); + if (nd->flags & LOOKUP_RCU) { + if (unlikely(unlazy_walk(nd, NULL, 0))) + return ERR_PTR(-ECHILD); + } error = security_inode_follow_link(dentry, inode, nd->flags & LOOKUP_RCU); -- cgit v1.2.3-55-g7522