From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 10670C433EF for ; Wed, 16 Feb 2022 10:28:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229462AbiBPK3C (ORCPT ); Wed, 16 Feb 2022 05:29:02 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:32964 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229799AbiBPK25 (ORCPT ); Wed, 16 Feb 2022 05:28:57 -0500 Received: from mail-ed1-x52a.google.com (mail-ed1-x52a.google.com [IPv6:2a00:1450:4864:20::52a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2863421F5C1 for ; Wed, 16 Feb 2022 02:28:33 -0800 (PST) Received: by mail-ed1-x52a.google.com with SMTP id h18so3086482edb.7 for ; Wed, 16 Feb 2022 02:28:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=szeredi.hu; s=google; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to; bh=h5LMjKcr6PyqZitTAY4fxVujQ96SMEzb1ukbNS+2yqQ=; b=F8ZP+yWx3/Vgmx9io+r2UQbYy4b794FeDw8vT/9eSh+GVB9n4TBfBb6lKbxjKXySfZ 6cpWpoF+fHenSWzmay83Tryjq/DtAEW4dY/GA0/b1r5wqmIZLdTElVQg/8ZLwy4Bvpox CjF0xb3TIlkmO4k/w1JRrOFg6KwPt1tDR1VzQ= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to; bh=h5LMjKcr6PyqZitTAY4fxVujQ96SMEzb1ukbNS+2yqQ=; b=iChz1o2UwbDXR0ibTrhxYLE1D5Q8/YRtWbVTjUcVTvKTD6PNsBVvx1XTh1rvwvNoDn Oi2tNXs9DZqPGFWlxIniZyKW8TZj9diQUjiHtMiKYlWJtdXQZV0n+WgFZ5iss+x9LGHu L95IRQACeW4akZUSgeXA99Ce1jdughA4w5Kud4why/0Sc0tUlsSgdcywHWoRK8z9KW9T 1pGKNJb1jYmPe3oES4vr3uJLhRjXWTWFbot8jTPS3Oe5Rx9TN6Yzn9sOiLKGiAAqsmfw A3S3UYPwvC9Ki2OGDVXbcjxlwMs2su2ujkWQnMFe443fu+2b38yfN3Eec1AfKrjO0y0R BpZw== X-Gm-Message-State: AOAM5335+rWYkDalcjizlOmbqUZHYZyWMffM8/dBUJtbSCYdq93R9hG6 Jb3X3MCh2chbWt0KiRwNPj+Nrg== X-Google-Smtp-Source: ABdhPJy7Y6JBt5j2jM9BY2aJtfySo/GeQzuue2bA5X4BQ4sBhrOE0G8XQI6we7N0sLQWONlCLCFKcQ== X-Received: by 2002:aa7:daca:0:b0:410:d02a:1bf3 with SMTP id x10-20020aa7daca000000b00410d02a1bf3mr2173399eds.455.1645007306948; Wed, 16 Feb 2022 02:28:26 -0800 (PST) Received: from miu.piliscsaba.redhat.com (catv-178-48-189-3.catv.fixed.vodafone.hu. [178.48.189.3]) by smtp.gmail.com with ESMTPSA id qo24sm3284400ejb.92.2022.02.16.02.28.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 16 Feb 2022 02:28:25 -0800 (PST) Date: Wed, 16 Feb 2022 11:28:18 +0100 From: Miklos Szeredi To: Al Viro Cc: Matthew Wilcox , Xavier Roche , linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, "Aneesh Kumar K.V" Subject: Re: race between vfs_rename and do_linkat (mv and link) Message-ID: References: <20220214210708.GA2167841@xavier-xps> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Wed, Feb 16, 2022 at 10:28:20AM +0100, Miklos Szeredi wrote: > So this is a fairly special situation. How about adding a new rwsem > (could possibly be global or per-fs)? > > - acquired for read in lock_rename() before inode locks > - acquired for write in do_linkat before inode locks, but only on retry Something like this: diff --git a/fs/namei.c b/fs/namei.c index 3f1829b3ab5b..dd6908cee49d 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -122,6 +122,8 @@ * PATH_MAX includes the nul terminator --RR. */ +static DECLARE_RWSEM(link_rwsem); + #define EMBEDDED_NAME_MAX (PATH_MAX - offsetof(struct filename, iname)) struct filename * @@ -2961,6 +2963,8 @@ struct dentry *lock_rename(struct dentry *p1, struct dentry *p2) { struct dentry *p; + down_read(&link_rwsem); + if (p1 == p2) { inode_lock_nested(p1->d_inode, I_MUTEX_PARENT); return NULL; @@ -2995,6 +2999,8 @@ void unlock_rename(struct dentry *p1, struct dentry *p2) inode_unlock(p2->d_inode); mutex_unlock(&p1->d_sb->s_vfs_rename_mutex); } + + up_read(&link_rwsem); } EXPORT_SYMBOL(unlock_rename); @@ -4456,6 +4462,7 @@ int do_linkat(int olddfd, struct filename *old, int newdfd, struct path old_path, new_path; struct inode *delegated_inode = NULL; int how = 0; + bool lock = false; int error; if ((flags & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH)) != 0) { @@ -4474,10 +4481,13 @@ int do_linkat(int olddfd, struct filename *old, int newdfd, if (flags & AT_SYMLINK_FOLLOW) how |= LOOKUP_FOLLOW; +retry_lock: + if (lock) + down_write(&link_rwsem); retry: error = filename_lookup(olddfd, old, how, &old_path, NULL); if (error) - goto out_putnames; + goto out_unlock_link; new_dentry = filename_create(newdfd, new, &new_path, (how & LOOKUP_REVAL)); @@ -4511,8 +4521,16 @@ int do_linkat(int olddfd, struct filename *old, int newdfd, how |= LOOKUP_REVAL; goto retry; } + if (!lock && error == -ENOENT) { + path_put(&old_path); + lock = true; + goto retry_lock; + } out_putpath: path_put(&old_path); +out_unlock_link: + if (lock) + up_write(&link_rwsem); out_putnames: putname(old); putname(new);