From patchwork Thu Mar 5 05:21:21 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: NeilBrown X-Patchwork-Id: 5943551 Return-Path: X-Original-To: patchwork-linux-fsdevel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id AF196BF440 for ; Thu, 5 Mar 2015 05:24:38 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id D382F202BE for ; Thu, 5 Mar 2015 05:24:37 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 6104A202B8 for ; Thu, 5 Mar 2015 05:24:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753301AbbCEFW4 (ORCPT ); Thu, 5 Mar 2015 00:22:56 -0500 Received: from cantor2.suse.de ([195.135.220.15]:42164 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752083AbbCEFWy (ORCPT ); Thu, 5 Mar 2015 00:22:54 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id D36CDAB09; Thu, 5 Mar 2015 05:22:52 +0000 (UTC) From: NeilBrown To: Alexander Viro Date: Thu, 05 Mar 2015 16:21:21 +1100 Subject: [PATCH 4/9] VFS/namei: abort RCU-walk on symlink if atime needs updating. Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Message-ID: <20150305052121.23906.28659.stgit@notabene.brown> In-Reply-To: <20150305051530.23906.65097.stgit@notabene.brown> References: <20150305051530.23906.65097.stgit@notabene.brown> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 only allow RCU-walk on a symlink if that fails. Signed-off-by: NeilBrown --- fs/inode.c | 26 +++++++++++++++++++------- fs/namei.c | 7 ++++++- include/linux/fs.h | 1 + 3 files changed, 26 insertions(+), 8 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/fs/inode.c b/fs/inode.c index f00b16f45507..a0da920e4650 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -1584,30 +1584,41 @@ static int update_time(struct inode *inode, struct timespec *time, int flags) * This function automatically handles read only file systems and media, * as well as the "noatime" flag and inode specific "noatime" markers. */ -void touch_atime(const struct path *path) +int atime_needs_update(const struct path *path) { struct vfsmount *mnt = path->mnt; struct inode *inode = path->dentry->d_inode; struct timespec now; if (inode->i_flags & S_NOATIME) - return; + return 0; if (IS_NOATIME(inode)) - return; + return 0; if ((inode->i_sb->s_flags & MS_NODIRATIME) && S_ISDIR(inode->i_mode)) - return; + return 0; if (mnt->mnt_flags & MNT_NOATIME) - return; + return 0; if ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode)) - return; + return 0; now = current_fs_time(inode->i_sb); if (!relatime_need_update(mnt, inode, now)) - return; + return 0; if (timespec_equal(&inode->i_atime, &now)) + return 0; + return 1; +} + +void touch_atime(const struct path *path) +{ + struct vfsmount *mnt = path->mnt; + struct inode *inode = path->dentry->d_inode; + struct timespec now; + + if (!atime_needs_update(path)) return; if (!sb_start_write_trylock(inode->i_sb)) @@ -1624,6 +1635,7 @@ void touch_atime(const struct path *path) * We may also fail on filesystems that have the ability to make parts * of the fs read only, e.g. subvolumes in Btrfs. */ + now = current_fs_time(inode->i_sb); update_time(inode, &now, S_ATIME); __mnt_drop_write(mnt); skip_update: diff --git a/fs/namei.c b/fs/namei.c index a4879bb3b4ee..5814d1b2daab 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -886,7 +886,12 @@ follow_link(struct path *link, struct nameidata *nd, void **p) cond_resched(); current->total_link_count++; - touch_atime(link); + if (nd->flags & LOOKUP_RCU) { + error = -ECHILD; + if (atime_needs_update(link)) + goto out_put_nd_path; + } else + touch_atime(link); nd_set_link(nd, NULL); error = security_inode_follow_link(link->dentry, nd); diff --git a/include/linux/fs.h b/include/linux/fs.h index eaef987ae3cf..6665aa16abcb 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1845,6 +1845,7 @@ enum file_time_flags { S_VERSION = 8, }; +extern int atime_needs_update(const struct path *); extern void touch_atime(const struct path *); static inline void file_accessed(struct file *file) {