From nobody Tue Apr 28 10:33:29 2026 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 7CFFEC433EF for ; Wed, 1 Jun 2022 17:32:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1356345AbiFARcY (ORCPT ); Wed, 1 Jun 2022 13:32:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57162 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1356317AbiFARcV (ORCPT ); Wed, 1 Jun 2022 13:32:21 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id D8DBA4969F for ; Wed, 1 Jun 2022 10:32:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1654104739; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=cPpYHnXIBZc98vfrpGPPeNO4G+nbrOWi/rqlDfKtk/c=; b=C4faVBtu5SVjPWHmlXS4Ub4OxO84MNKj1a9c+WHq6uOfo2iZ9qK7djXa8CRu+VxAXIpHEq WDVn9Q476ChG45IRv4IHcDtwyhKNNqABl/uZhR/YKe0lfcUKraYdRmLX6LyBkihmixlxuk YPLHTrEwHTWzQU36P0xIXm9dplWUX0c= Received: from mail-wm1-f72.google.com (mail-wm1-f72.google.com [209.85.128.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-122-zMwmhTKFOZyQ93Xj3I5EMg-1; Wed, 01 Jun 2022 13:32:18 -0400 X-MC-Unique: zMwmhTKFOZyQ93Xj3I5EMg-1 Received: by mail-wm1-f72.google.com with SMTP id m31-20020a05600c3b1f00b003973a563605so1233319wms.9 for ; Wed, 01 Jun 2022 10:32:17 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=cPpYHnXIBZc98vfrpGPPeNO4G+nbrOWi/rqlDfKtk/c=; b=rfSbMxsnCj4ENBNZNRkV4PnTOaH/rZsqZE/Shp/XZCg0kcselxGikBwe8lTYY26Ndn /1RnpgcCDTA5dYpLEwA3hF2LDKD3Gvz2N3sITj3NRssJEcGVlNuEWfq/gX8q5fl5paae 0qgN3qN1azRKnfumw5fIBKj5xVB9ohQfPoUsXbb4LEn3LnGBMk8ZhoKEoMr5zO4XusnQ 9ReZzqhUV9Zym2fmAqCJyTxwTGrXdNsUqsXU74GS7PZKrGhzqrnCg+VFF8fwUutoVZby wlj0VlMPbXuvUw9B97VBdq3v7AG7XG+mcq5pn08UqK9c6CaiWN31jY218+jjb9eOiuiS NIYQ== X-Gm-Message-State: AOAM530z5hgRZ8aDi/6Xm8kBenCIqABJemrSwpuwA5uH4cgxM1tiXDI/ bAhIbkn7LvgZgswt6soGkRn9hupZHbPVuI3qGvqdSDv6aAV8k+roh5/MldKqq07+7WLEpnB/ulK kkTKqfup+l28jGScx4/381bUHrfJau5LzhVigb9ppAZzyJDbKGnbw1MDkruQMhBO1U0fr/QhP3n A= X-Received: by 2002:adf:f543:0:b0:20d:80e:dde with SMTP id j3-20020adff543000000b0020d080e0ddemr416223wrp.269.1654104736798; Wed, 01 Jun 2022 10:32:16 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyFt4kSB0J1yMSflWtg8+2t1z+6EiKuq0CkHuJQlcL8A8zszR+zmZxYet5a5WuR7xmVQm2Mtg== X-Received: by 2002:adf:f543:0:b0:20d:80e:dde with SMTP id j3-20020adff543000000b0020d080e0ddemr416198wrp.269.1654104736545; Wed, 01 Jun 2022 10:32:16 -0700 (PDT) Received: from minerva.home (205.pool92-176-231.dynamic.orange.es. [92.176.231.205]) by smtp.gmail.com with ESMTPSA id l14-20020a05600c2cce00b0039751bb8c62sm6525625wmc.24.2022.06.01.10.32.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 01 Jun 2022 10:32:16 -0700 (PDT) From: Javier Martinez Canillas To: linux-kernel@vger.kernel.org Cc: Lennart Poettering , OGAWA Hirofumi , Colin Walters , Peter Jones , Alberto Ruiz , Christian Kellner , Chung-Chiang Cheng , Muhammad Usama Anjum , Alexander Larsson , Javier Martinez Canillas Subject: [PATCH v4 1/4] fat: add a vfat_rename2() and make existing .rename callback a helper Date: Wed, 1 Jun 2022 19:32:01 +0200 Message-Id: <20220601173204.1372569-2-javierm@redhat.com> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220601173204.1372569-1-javierm@redhat.com> References: <20220601173204.1372569-1-javierm@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Currently vfat only supports the RENAME_NOREPLACE flag which is handled by the virtual file system layer but doesn't support the RENAME_EXCHANGE flag. Add a vfat_rename2() function to be used as the .rename callback and move the current vfat_rename() handler to a helper. This is in preparation for implementing the RENAME_NOREPLACE flag using a different helper function. Signed-off-by: Javier Martinez Canillas --- (no changes since v1) fs/fat/namei_vfat.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c index c573314806cf..88ccb2ee3537 100644 --- a/fs/fat/namei_vfat.c +++ b/fs/fat/namei_vfat.c @@ -889,9 +889,8 @@ static int vfat_mkdir(struct user_namespace *mnt_userns= , struct inode *dir, return err; } =20 -static int vfat_rename(struct user_namespace *mnt_userns, struct inode *ol= d_dir, - struct dentry *old_dentry, struct inode *new_dir, - struct dentry *new_dentry, unsigned int flags) +static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry, + struct inode *new_dir, struct dentry *new_dentry) { struct buffer_head *dotdot_bh; struct msdos_dir_entry *dotdot_de; @@ -902,9 +901,6 @@ static int vfat_rename(struct user_namespace *mnt_usern= s, struct inode *old_dir, int err, is_dir, update_dotdot, corrupt =3D 0; struct super_block *sb =3D old_dir->i_sb; =20 - if (flags & ~RENAME_NOREPLACE) - return -EINVAL; - old_sinfo.bh =3D sinfo.bh =3D dotdot_bh =3D NULL; old_inode =3D d_inode(old_dentry); new_inode =3D d_inode(new_dentry); @@ -1021,13 +1017,24 @@ static int vfat_rename(struct user_namespace *mnt_u= serns, struct inode *old_dir, goto out; } =20 +static int vfat_rename2(struct user_namespace *mnt_userns, struct inode *o= ld_dir, + struct dentry *old_dentry, struct inode *new_dir, + struct dentry *new_dentry, unsigned int flags) +{ + if (flags & ~RENAME_NOREPLACE) + return -EINVAL; + + /* VFS already handled RENAME_NOREPLACE, handle it as a normal rename */ + return vfat_rename(old_dir, old_dentry, new_dir, new_dentry); +} + static const struct inode_operations vfat_dir_inode_operations =3D { .create =3D vfat_create, .lookup =3D vfat_lookup, .unlink =3D vfat_unlink, .mkdir =3D vfat_mkdir, .rmdir =3D vfat_rmdir, - .rename =3D vfat_rename, + .rename =3D vfat_rename2, .setattr =3D fat_setattr, .getattr =3D fat_getattr, .update_time =3D fat_update_time, --=20 2.36.1 From nobody Tue Apr 28 10:33:29 2026 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 E55DFC433EF for ; Wed, 1 Jun 2022 17:32:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1349814AbiFARcb (ORCPT ); Wed, 1 Jun 2022 13:32:31 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57260 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1356338AbiFARcW (ORCPT ); Wed, 1 Jun 2022 13:32:22 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 3B5F3488AB for ; Wed, 1 Jun 2022 10:32:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1654104740; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=jrVbGdfcjLY3mxRjbqeWGmJJMVLxqZJaLyqpgAFIX+U=; b=cN9xMcSwY9vtorrs3dnTT/9lcgVscCAhDjorHGXJdxts2RDSHlXMSnWrIQdrlY12UF+Yuz RfZ8EYl7H7yU0qnTiHsynzlIn/7ZNdNh3nIHThWRjhx/PNW4w5AsBpSNJLflGtQVeUiRhA usmFvf6H52P5ybFi5rhS5rB3etM1CMI= Received: from mail-wm1-f69.google.com (mail-wm1-f69.google.com [209.85.128.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-605-_QZ0llhvMLOiz78yZtWgFw-1; Wed, 01 Jun 2022 13:32:19 -0400 X-MC-Unique: _QZ0llhvMLOiz78yZtWgFw-1 Received: by mail-wm1-f69.google.com with SMTP id l31-20020a05600c1d1f00b003974df9b91cso3699465wms.8 for ; Wed, 01 Jun 2022 10:32:19 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=jrVbGdfcjLY3mxRjbqeWGmJJMVLxqZJaLyqpgAFIX+U=; b=ySssnbZ8oVHQUluMkEVMImUQz/upwKj1JLz3McUjnRWLn73BqIhDGdIZssit9Otm4D Ko7ywMCzwutj/d6amM1LLycbuipHn6avikVgqFsWqpMvjNiI6kjg0GUDukMhXzApvl7Y fjOA4OpeNqDw/Vzian7MSVnLIkhSFtGihmY+CZJ4s9C0j0gw/hFGUXVV0Bk9XQLNhWBA 2H42Ms+pSLsaYxIY+IsBEiHAooP11ev3QnQG3Cg6ghBVlII2e5CQI8wx2gI2NrFc7/Jp RJvhrB0d8mtHAFKRqTtgf9aaGeMUs2HfaSnBi/e8o8LP6w0YWnrEI2XuC+qph8qEx6OX jsnw== X-Gm-Message-State: AOAM530vf1hnUI4lYhUHZ1U4bA+QpYFRWOGZGqkGx5FuLaY193kpHIIn BmaWWCoNVCvyyfN9pJZGKtIZHrvxIAv0KOy7g1rLpVi0Cjiv3fZj8rfQWnvM0Irutm7W9Vad4Nb HjgF4CPlB4UWFVAqBxCA70zUeRHkaYxXAqngjo8XdwibYgo9C3sba36QgPZaZCrA1xeaKysWvwX c= X-Received: by 2002:a05:600c:20d:b0:397:3971:909e with SMTP id 13-20020a05600c020d00b003973971909emr401804wmi.203.1654104738035; Wed, 01 Jun 2022 10:32:18 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxw+cYU/LJ8Wt2DU50OcaCh4bKwl012dX9vMFIEr9kUUmXM0MCNkqN732dY/jI9kAeBpub0OQ== X-Received: by 2002:a05:600c:20d:b0:397:3971:909e with SMTP id 13-20020a05600c020d00b003973971909emr401760wmi.203.1654104737583; Wed, 01 Jun 2022 10:32:17 -0700 (PDT) Received: from minerva.home (205.pool92-176-231.dynamic.orange.es. [92.176.231.205]) by smtp.gmail.com with ESMTPSA id l14-20020a05600c2cce00b0039751bb8c62sm6525625wmc.24.2022.06.01.10.32.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 01 Jun 2022 10:32:17 -0700 (PDT) From: Javier Martinez Canillas To: linux-kernel@vger.kernel.org Cc: Lennart Poettering , OGAWA Hirofumi , Colin Walters , Peter Jones , Alberto Ruiz , Christian Kellner , Chung-Chiang Cheng , Muhammad Usama Anjum , Alexander Larsson , Javier Martinez Canillas Subject: [PATCH v4 2/4] fat: factor out reusable code in vfat_rename() as helper functions Date: Wed, 1 Jun 2022 19:32:02 +0200 Message-Id: <20220601173204.1372569-3-javierm@redhat.com> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220601173204.1372569-1-javierm@redhat.com> References: <20220601173204.1372569-1-javierm@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" From: OGAWA Hirofumi The vfat_rename() function is quite big and there are code blocks that can be moved into helper functions. This not only simplify the implementation of that function but also allows these helpers to be reused. For example, the helpers can be used by the handler of the RENAME_EXCHANGE flag once this is implemented in a subsequent patch. Signed-off-by: OGAWA Hirofumi Signed-off-by: Javier Martinez Canillas --- Changes in v4: - Add new patch from OGAWA Hirofumi to use the helpers in vfat_rename(). fs/fat/namei_vfat.c | 89 +++++++++++++++++++++++++++++---------------- 1 file changed, 57 insertions(+), 32 deletions(-) diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c index 88ccb2ee3537..9c04053a8f1c 100644 --- a/fs/fat/namei_vfat.c +++ b/fs/fat/namei_vfat.c @@ -889,16 +889,55 @@ static int vfat_mkdir(struct user_namespace *mnt_user= ns, struct inode *dir, return err; } =20 +static int vfat_get_dotdot_de(struct inode *inode, struct buffer_head **bh, + struct msdos_dir_entry **de) +{ + if (S_ISDIR(inode->i_mode)) { + if (fat_get_dotdot_entry(inode, bh, de)) + return -EIO; + } + return 0; +} + +static int vfat_sync_ipos(struct inode *dir, struct inode *inode) +{ + if (IS_DIRSYNC(dir)) + return fat_sync_inode(inode); + mark_inode_dirty(inode); + return 0; +} + +static int vfat_update_dotdot_de(struct inode *dir, struct inode *inode, + struct buffer_head *dotdot_bh, + struct msdos_dir_entry *dotdot_de) +{ + fat_set_start(dotdot_de, MSDOS_I(dir)->i_logstart); + mark_buffer_dirty_inode(dotdot_bh, inode); + if (IS_DIRSYNC(dir)) + return sync_dirty_buffer(dotdot_bh); + return 0; +} + +static void vfat_update_dir_metadata(struct inode *dir, struct timespec64 = *ts) +{ + inode_inc_iversion(dir); + fat_truncate_time(dir, ts, S_CTIME | S_MTIME); + if (IS_DIRSYNC(dir)) + (void)fat_sync_inode(dir); + else + mark_inode_dirty(dir); +} + static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry) { struct buffer_head *dotdot_bh; - struct msdos_dir_entry *dotdot_de; + struct msdos_dir_entry *dotdot_de =3D NULL; struct inode *old_inode, *new_inode; struct fat_slot_info old_sinfo, sinfo; struct timespec64 ts; loff_t new_i_pos; - int err, is_dir, update_dotdot, corrupt =3D 0; + int err, is_dir, corrupt =3D 0; struct super_block *sb =3D old_dir->i_sb; =20 old_sinfo.bh =3D sinfo.bh =3D dotdot_bh =3D NULL; @@ -909,15 +948,13 @@ static int vfat_rename(struct inode *old_dir, struct = dentry *old_dentry, if (err) goto out; =20 - is_dir =3D S_ISDIR(old_inode->i_mode); - update_dotdot =3D (is_dir && old_dir !=3D new_dir); - if (update_dotdot) { - if (fat_get_dotdot_entry(old_inode, &dotdot_bh, &dotdot_de)) { - err =3D -EIO; + if (old_dir !=3D new_dir) { + err =3D vfat_get_dotdot_de(old_inode, &dotdot_bh, &dotdot_de); + if (err) goto out; - } } =20 + is_dir =3D S_ISDIR(old_inode->i_mode); ts =3D current_time(old_dir); if (new_inode) { if (is_dir) { @@ -938,21 +975,15 @@ static int vfat_rename(struct inode *old_dir, struct = dentry *old_dentry, =20 fat_detach(old_inode); fat_attach(old_inode, new_i_pos); - if (IS_DIRSYNC(new_dir)) { - err =3D fat_sync_inode(old_inode); - if (err) - goto error_inode; - } else - mark_inode_dirty(old_inode); + err =3D vfat_sync_ipos(new_dir, old_inode); + if (err) + goto error_inode; =20 - if (update_dotdot) { - fat_set_start(dotdot_de, MSDOS_I(new_dir)->i_logstart); - mark_buffer_dirty_inode(dotdot_bh, old_inode); - if (IS_DIRSYNC(new_dir)) { - err =3D sync_dirty_buffer(dotdot_bh); - if (err) - goto error_dotdot; - } + if (dotdot_de) { + err =3D vfat_update_dotdot_de(new_dir, old_inode, dotdot_bh, + dotdot_de); + if (err) + goto error_dotdot; drop_nlink(old_dir); if (!new_inode) inc_nlink(new_dir); @@ -962,12 +993,7 @@ static int vfat_rename(struct inode *old_dir, struct d= entry *old_dentry, old_sinfo.bh =3D NULL; if (err) goto error_dotdot; - inode_inc_iversion(old_dir); - fat_truncate_time(old_dir, &ts, S_CTIME|S_MTIME); - if (IS_DIRSYNC(old_dir)) - (void)fat_sync_inode(old_dir); - else - mark_inode_dirty(old_dir); + vfat_update_dir_metadata(old_dir, &ts); =20 if (new_inode) { drop_nlink(new_inode); @@ -987,10 +1013,9 @@ static int vfat_rename(struct inode *old_dir, struct = dentry *old_dentry, /* data cluster is shared, serious corruption */ corrupt =3D 1; =20 - if (update_dotdot) { - fat_set_start(dotdot_de, MSDOS_I(old_dir)->i_logstart); - mark_buffer_dirty_inode(dotdot_bh, old_inode); - corrupt |=3D sync_dirty_buffer(dotdot_bh); + if (dotdot_de) { + corrupt |=3D vfat_update_dotdot_de(old_dir, old_inode, dotdot_bh, + dotdot_de); } error_inode: fat_detach(old_inode); --=20 2.36.1 From nobody Tue Apr 28 10:33:29 2026 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 81B21C43334 for ; Wed, 1 Jun 2022 17:32:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1356362AbiFARcg (ORCPT ); Wed, 1 Jun 2022 13:32:36 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57422 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1356342AbiFARcX (ORCPT ); Wed, 1 Jun 2022 13:32:23 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 7E0C94926A for ; Wed, 1 Jun 2022 10:32:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1654104741; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=m6eMKpD/mGKmJJS6uppDKQiAUieabwGpSUh8uzV1ii0=; b=S4FqCAVDuwhwPK9Eywr6Kge+7n6E7II0YQV7jH47QbLHRvd+iX3GQ+0lH+/0bBt2/7D7QO W1vAtAVa6orZqmIkf3778+K0+ZOUmWFNSf9bo+64QiPnPOca0LQcSt4vIHZqwWJu7m3qCC LASRZMcSEC5cpl82l+M4EW+kBLCC5Sc= Received: from mail-wm1-f71.google.com (mail-wm1-f71.google.com [209.85.128.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-346-cOY_Ac33N4GftXHycbzdQw-1; Wed, 01 Jun 2022 13:32:20 -0400 X-MC-Unique: cOY_Ac33N4GftXHycbzdQw-1 Received: by mail-wm1-f71.google.com with SMTP id u12-20020a05600c19cc00b0038ec265155fso3704022wmq.6 for ; Wed, 01 Jun 2022 10:32:20 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=m6eMKpD/mGKmJJS6uppDKQiAUieabwGpSUh8uzV1ii0=; b=ZivUaxN4vZEih2HV6bAh9mJJjC/0znuHFPmCUFWuUd8h7u4KUDL4RC2jcmtKnIWlxE mVet9HR+zchEl9eBLPB7ziFZD4WvVI4HYWpz9kMJ3ST/j7Bxv270hqn2fhvDwFt9heNJ 6lhw7WtPo2tl+OG4aIWg+yrbhFXfNKoKFQm1lp8ReQ53CgeDqsCGUF947Q8dsdOD6MRs +ywfoRCUImMdzgx/XkX3RBbBFCpPKoliWPDAo08p5NwLYWbcvwqRSO3d45G4TA8Z8tyA snOlFfBfLK7O+AKiPH+8ECmPR62O3vpqqHtWSZR9JvheE0mUCNwKEcNrhYIVSiQhiZ2e ZUEw== X-Gm-Message-State: AOAM533CjNsD++cR4qdQnzu9GD/xNJPeBtRiFb1dC9Qh17HBd7WlXk3M aBYEzZiRwJwjH7afCgznlO3DCUvaSoE3WRMgwVswbVT+nPZ99MsWXvOaBfekwu4UxI4XAks0vsD 1WS9U9bJdGRV1xSNX0YGEWDdZsrDSMVTe5liRu+/si7OQC4YunEggcocM6tFdkYHfOfnrDFZGGL w= X-Received: by 2002:a7b:c5d0:0:b0:389:fe85:3d79 with SMTP id n16-20020a7bc5d0000000b00389fe853d79mr30081532wmk.77.1654104739077; Wed, 01 Jun 2022 10:32:19 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzg1Ay7mO1KlJaXVQExeECd7gxByNNKImo1aPTamB1fVDaJXVOZ8+IMcN90vhEGo5MIz333KA== X-Received: by 2002:a7b:c5d0:0:b0:389:fe85:3d79 with SMTP id n16-20020a7bc5d0000000b00389fe853d79mr30081498wmk.77.1654104738745; Wed, 01 Jun 2022 10:32:18 -0700 (PDT) Received: from minerva.home (205.pool92-176-231.dynamic.orange.es. [92.176.231.205]) by smtp.gmail.com with ESMTPSA id l14-20020a05600c2cce00b0039751bb8c62sm6525625wmc.24.2022.06.01.10.32.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 01 Jun 2022 10:32:18 -0700 (PDT) From: Javier Martinez Canillas To: linux-kernel@vger.kernel.org Cc: Lennart Poettering , OGAWA Hirofumi , Colin Walters , Peter Jones , Alberto Ruiz , Christian Kellner , Chung-Chiang Cheng , Muhammad Usama Anjum , Alexander Larsson , Javier Martinez Canillas Subject: [PATCH v4 3/4] fat: add renameat2 RENAME_EXCHANGE flag support Date: Wed, 1 Jun 2022 19:32:03 +0200 Message-Id: <20220601173204.1372569-4-javierm@redhat.com> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220601173204.1372569-1-javierm@redhat.com> References: <20220601173204.1372569-1-javierm@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The renameat2 RENAME_EXCHANGE flag allows to atomically exchange two paths but is currently not supported by the Linux vfat filesystem driver. Add a vfat_rename_exchange() helper function that implements this support. The super block lock is acquired during the operation to ensure atomicity, and in the error path actions made are reversed also with the mutex held. It makes the operation as transactional as possible, within the limitation impossed by vfat due not having a journal with logs to replay. Signed-off-by: Javier Martinez Canillas --- Changes in v4: - Rebase the patch on top of OGAWA Hirofumi proposed changes. - Drop iversion increment for old and new file inodes (OGAWA Hirofumi). Changes in v2: - Only update the new_dir inode version and timestamps if !=3D old_dir (Alex Larsson). - Add some helper functions to avoid duplicating code (OGAWA Hirofumi). - Use braces for multi-lines blocks even if are one statement (OGAWA Hirofu= mi). - Mention in commit message that the operation is as transactional as possi= ble but within the vfat limitations of not having a journal (Colin Walters). fs/fat/namei_vfat.c | 114 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 113 insertions(+), 1 deletion(-) diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c index 9c04053a8f1c..725ab9404c53 100644 --- a/fs/fat/namei_vfat.c +++ b/fs/fat/namei_vfat.c @@ -1042,13 +1042,125 @@ static int vfat_rename(struct inode *old_dir, stru= ct dentry *old_dentry, goto out; } =20 +static void vfat_exchange_ipos(struct inode *old_inode, struct inode *new_= inode, + loff_t old_i_pos, loff_t new_i_pos) +{ + fat_detach(old_inode); + fat_detach(new_inode); + fat_attach(old_inode, new_i_pos); + fat_attach(new_inode, old_i_pos); +} + +static int vfat_rename_exchange(struct inode *old_dir, struct dentry *old_= dentry, + struct inode *new_dir, struct dentry *new_dentry) +{ + struct buffer_head *old_dotdot_bh =3D NULL, *new_dotdot_bh =3D NULL; + struct msdos_dir_entry *old_dotdot_de =3D NULL, *new_dotdot_de =3D NULL; + struct inode *old_inode, *new_inode; + struct timespec64 ts =3D current_time(old_dir); + loff_t old_i_pos, new_i_pos; + int err, corrupt =3D 0; + struct super_block *sb =3D old_dir->i_sb; + + old_inode =3D d_inode(old_dentry); + new_inode =3D d_inode(new_dentry); + + /* Acquire super block lock for the operation to be atomic */ + mutex_lock(&MSDOS_SB(sb)->s_lock); + + /* if directories are not the same, get ".." info to update */ + if (old_dir !=3D new_dir) { + err =3D vfat_get_dotdot_de(old_inode, &old_dotdot_bh, + &old_dotdot_de); + if (err) + goto out; + + err =3D vfat_get_dotdot_de(new_inode, &new_dotdot_bh, + &new_dotdot_de); + if (err) + goto out; + } + + old_i_pos =3D MSDOS_I(old_inode)->i_pos; + new_i_pos =3D MSDOS_I(new_inode)->i_pos; + + vfat_exchange_ipos(old_inode, new_inode, old_i_pos, new_i_pos); + + err =3D vfat_sync_ipos(old_dir, new_inode); + if (err) + goto error_exchange; + err =3D vfat_sync_ipos(new_dir, old_inode); + if (err) + goto error_exchange; + + /* update ".." directory entry info */ + if (old_dotdot_de) { + err =3D vfat_update_dotdot_de(new_dir, old_inode, old_dotdot_bh, + old_dotdot_de); + if (err) + goto error_old_dotdot; + drop_nlink(old_dir); + inc_nlink(new_dir); + } + + if (new_dotdot_de) { + err =3D vfat_update_dotdot_de(old_dir, new_inode, new_dotdot_bh, + new_dotdot_de); + if (err) + goto error_new_dotdot; + drop_nlink(new_dir); + inc_nlink(old_dir); + } + + vfat_update_dir_metadata(old_dir, &ts); + /* if directories are not the same, update new_dir as well */ + if (old_dir !=3D new_dir) + vfat_update_dir_metadata(new_dir, &ts); + +out: + brelse(old_dotdot_bh); + brelse(new_dotdot_bh); + mutex_unlock(&MSDOS_SB(sb)->s_lock); + + return err; + +error_new_dotdot: + if (new_dotdot_de) { + corrupt |=3D vfat_update_dotdot_de(new_dir, new_inode, + new_dotdot_bh, new_dotdot_de); + } + +error_old_dotdot: + if (old_dotdot_de) { + corrupt |=3D vfat_update_dotdot_de(old_dir, old_inode, + old_dotdot_bh, old_dotdot_de); + } + +error_exchange: + vfat_exchange_ipos(old_inode, new_inode, new_i_pos, old_i_pos); + corrupt |=3D vfat_sync_ipos(new_dir, new_inode); + corrupt |=3D vfat_sync_ipos(old_dir, old_inode); + + if (corrupt < 0) { + fat_fs_error(new_dir->i_sb, + "%s: Filesystem corrupted (i_pos %lld, %lld)", + __func__, old_i_pos, new_i_pos); + } + goto out; +} + static int vfat_rename2(struct user_namespace *mnt_userns, struct inode *o= ld_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry, unsigned int flags) { - if (flags & ~RENAME_NOREPLACE) + if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE)) return -EINVAL; =20 + if (flags & RENAME_EXCHANGE) { + return vfat_rename_exchange(old_dir, old_dentry, + new_dir, new_dentry); + } + /* VFS already handled RENAME_NOREPLACE, handle it as a normal rename */ return vfat_rename(old_dir, old_dentry, new_dir, new_dentry); } --=20 2.36.1 From nobody Tue Apr 28 10:33:29 2026 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 D19BEC43334 for ; Wed, 1 Jun 2022 17:32:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1356353AbiFARck (ORCPT ); Wed, 1 Jun 2022 13:32:40 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57980 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1356354AbiFARcc (ORCPT ); Wed, 1 Jun 2022 13:32:32 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id A712249F81 for ; Wed, 1 Jun 2022 10:32:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1654104743; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=hugwPpklhru4dTxd3ocCNrmQ6SYV0EWcsILpPv9gcg0=; b=hHPE7/1OLlNg05yEh+BoRtY8l+AYRbnmWAqfNmvm22qNx2kM+XJO0GSlAVVNxUUD6VyDLa P/I9jgcII3Us12p9JT3XjGBrfZUFPJQ4aFGtObMsz85XoxfE0SZMamM+n8Nu0SG0NMUbmb /H6rBMl5fB7wpN+um6wNO/Qhk/8NJXM= Received: from mail-wr1-f69.google.com (mail-wr1-f69.google.com [209.85.221.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-637-ux8i_AxmMy-7n33ICd6bXA-1; Wed, 01 Jun 2022 13:32:22 -0400 X-MC-Unique: ux8i_AxmMy-7n33ICd6bXA-1 Received: by mail-wr1-f69.google.com with SMTP id v4-20020adfebc4000000b002102c69be5eso423211wrn.13 for ; Wed, 01 Jun 2022 10:32:22 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=hugwPpklhru4dTxd3ocCNrmQ6SYV0EWcsILpPv9gcg0=; b=hE5xpZh8YqxHYcKyStQnSoIse66h+QnOoMTJVB0v2tpt16odMadu4UYnbZ8Fxfz215 gTvG5UelXpIQ/sesqD4LMMXKoZKZeEiTB0uTkEenZEaIjbGUrEE1hk3dXZTaSZbL0E6w zewGRjBUoVLKttdKJ9YDm8jKCo4Rnua4FS2VJoCPfaEwyNbYNqs7CCAKD+2WiLJlc0MR P3455ye8J2oypGxqlbajm1O01LdxdPbyMMETjMhTAabnyG52U0ClGm2qz9NKl7NfpQ2b zsMPxYqL0SX5qCDfcy5ajU2AduFTHNcihyjdeebRfxRZo8MSwDCQUowyQStO/Gm99Zer pPoA== X-Gm-Message-State: AOAM531O7JbCcPm5Rs8ubT3isSV9cbCnxR9BeJVUzjtGjovA7GgN+JUk OXnagw6yYtQoL+ViAmTiGpKCZwSTzdxlqW1HrzS+GoG6oijSjbF6PHnpwoOXUSF0xs5w3akafyz k881qWYD1ZKAD0AHH+qFkRBHQ72XRW76ahQbmkCfIe8miD9JyXzNBGh0vFwA1WxOesftPD9x/BO U= X-Received: by 2002:a05:6000:1151:b0:210:155b:1e19 with SMTP id d17-20020a056000115100b00210155b1e19mr456700wrx.162.1654104740486; Wed, 01 Jun 2022 10:32:20 -0700 (PDT) X-Google-Smtp-Source: ABdhPJz0hkc5+wfvuMUiTucRLtZ8Fr/dpg6giOVsF56AEdMDV1s/qULqcNdEdrquqVFcFq31cGQtUQ== X-Received: by 2002:a05:6000:1151:b0:210:155b:1e19 with SMTP id d17-20020a056000115100b00210155b1e19mr456667wrx.162.1654104740202; Wed, 01 Jun 2022 10:32:20 -0700 (PDT) Received: from minerva.home (205.pool92-176-231.dynamic.orange.es. [92.176.231.205]) by smtp.gmail.com with ESMTPSA id l14-20020a05600c2cce00b0039751bb8c62sm6525625wmc.24.2022.06.01.10.32.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 01 Jun 2022 10:32:19 -0700 (PDT) From: Javier Martinez Canillas To: linux-kernel@vger.kernel.org Cc: Lennart Poettering , OGAWA Hirofumi , Colin Walters , Peter Jones , Alberto Ruiz , Christian Kellner , Chung-Chiang Cheng , Muhammad Usama Anjum , Alexander Larsson , Javier Martinez Canillas , Shuah Khan , linux-kselftest@vger.kernel.org Subject: [PATCH v4 4/4] selftests/filesystems: add a vfat RENAME_EXCHANGE test Date: Wed, 1 Jun 2022 19:32:04 +0200 Message-Id: <20220601173204.1372569-5-javierm@redhat.com> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220601173204.1372569-1-javierm@redhat.com> References: <20220601173204.1372569-1-javierm@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Add a test for the renameat2 RENAME_EXCHANGE support in vfat, but split it in a tool that just does the rename exchange and a script that is run by the kselftests framework on `make TARGETS=3D"filesystems/fat" kselftest`. That way the script can be easily extended to test other file operations. The script creates a 1 MiB disk image, that is then formated with a vfat filesystem and mounted using a loop device. That way all file operations are done on an ephemeral filesystem. Signed-off-by: Javier Martinez Canillas Acked-by: Muhammad Usama Anjum --- Changes in v4: - Add Muhammad Usama Anjum Acked-by tag. Changes in v3: - Add a .gitignore for the rename_exchange binary (Muhammad Usama Anjum). - Include $(KHDR_INCLUDES) instead of hardcoding a relative path in Makefile (Muhammad Usama Anjum). Changes in v2: - Call sync to flush the page cache before checking the file contents (Alex Larsson). MAINTAINERS | 1 + tools/testing/selftests/Makefile | 1 + .../selftests/filesystems/fat/.gitignore | 2 + .../selftests/filesystems/fat/Makefile | 7 ++ .../testing/selftests/filesystems/fat/config | 2 + .../filesystems/fat/rename_exchange.c | 37 +++++++++ .../filesystems/fat/run_fat_tests.sh | 82 +++++++++++++++++++ 7 files changed, 132 insertions(+) create mode 100644 tools/testing/selftests/filesystems/fat/.gitignore create mode 100644 tools/testing/selftests/filesystems/fat/Makefile create mode 100644 tools/testing/selftests/filesystems/fat/config create mode 100644 tools/testing/selftests/filesystems/fat/rename_exchange= .c create mode 100755 tools/testing/selftests/filesystems/fat/run_fat_tests.sh diff --git a/MAINTAINERS b/MAINTAINERS index 4fdbbd6c1984..158771bb7755 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -20841,6 +20841,7 @@ M: OGAWA Hirofumi S: Maintained F: Documentation/filesystems/vfat.rst F: fs/fat/ +F: tools/testing/selftests/filesystems/fat/ =20 VFIO DRIVER M: Alex Williamson diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Mak= efile index 0aedcd76cf0f..fc59ad849a90 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile @@ -16,6 +16,7 @@ TARGETS +=3D exec TARGETS +=3D filesystems TARGETS +=3D filesystems/binderfs TARGETS +=3D filesystems/epoll +TARGETS +=3D filesystems/fat TARGETS +=3D firmware TARGETS +=3D fpu TARGETS +=3D ftrace diff --git a/tools/testing/selftests/filesystems/fat/.gitignore b/tools/tes= ting/selftests/filesystems/fat/.gitignore new file mode 100644 index 000000000000..b89920ed841c --- /dev/null +++ b/tools/testing/selftests/filesystems/fat/.gitignore @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0-only +rename_exchange diff --git a/tools/testing/selftests/filesystems/fat/Makefile b/tools/testi= ng/selftests/filesystems/fat/Makefile new file mode 100644 index 000000000000..902033f6ef09 --- /dev/null +++ b/tools/testing/selftests/filesystems/fat/Makefile @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0 + +TEST_PROGS :=3D run_fat_tests.sh +TEST_GEN_PROGS_EXTENDED :=3D rename_exchange +CFLAGS +=3D -O2 -g -Wall $(KHDR_INCLUDES) + +include ../../lib.mk diff --git a/tools/testing/selftests/filesystems/fat/config b/tools/testing= /selftests/filesystems/fat/config new file mode 100644 index 000000000000..6cf95e787a17 --- /dev/null +++ b/tools/testing/selftests/filesystems/fat/config @@ -0,0 +1,2 @@ +CONFIG_BLK_DEV_LOOP=3Dy +CONFIG_VFAT_FS=3Dy diff --git a/tools/testing/selftests/filesystems/fat/rename_exchange.c b/to= ols/testing/selftests/filesystems/fat/rename_exchange.c new file mode 100644 index 000000000000..e488ad354fce --- /dev/null +++ b/tools/testing/selftests/filesystems/fat/rename_exchange.c @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Program that atomically exchanges two paths using + * the renameat2() system call RENAME_EXCHANGE flag. + * + * Copyright 2022 Red Hat Inc. + * Author: Javier Martinez Canillas + */ + +#define _GNU_SOURCE +#include +#include +#include + +void print_usage(const char *program) +{ + printf("Usage: %s [oldpath] [newpath]\n", program); + printf("Atomically exchange oldpath and newpath\n"); +} + +int main(int argc, char *argv[]) +{ + int ret; + + if (argc !=3D 3) { + print_usage(argv[0]); + exit(EXIT_FAILURE); + } + + ret =3D renameat2(AT_FDCWD, argv[1], AT_FDCWD, argv[2], RENAME_EXCHANGE); + if (ret) { + perror("rename exchange failed"); + exit(EXIT_FAILURE); + } + + exit(EXIT_SUCCESS); +} diff --git a/tools/testing/selftests/filesystems/fat/run_fat_tests.sh b/too= ls/testing/selftests/filesystems/fat/run_fat_tests.sh new file mode 100755 index 000000000000..7f35dc3d15df --- /dev/null +++ b/tools/testing/selftests/filesystems/fat/run_fat_tests.sh @@ -0,0 +1,82 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# +# Run filesystem operations tests on an 1 MiB disk image that is formatted= with +# a vfat filesystem and mounted in a temporary directory using a loop devi= ce. +# +# Copyright 2022 Red Hat Inc. +# Author: Javier Martinez Canillas + +set -e +set -u +set -o pipefail + +BASE_DIR=3D"$(dirname $0)" +TMP_DIR=3D"$(mktemp -d /tmp/fat_tests_tmp.XXXX)" +IMG_PATH=3D"${TMP_DIR}/fat.img" +MNT_PATH=3D"${TMP_DIR}/mnt" + +cleanup() +{ + mountpoint -q "${MNT_PATH}" && unmount_image + rm -rf "${TMP_DIR}" +} +trap cleanup SIGINT SIGTERM EXIT + +create_loopback() +{ + touch "${IMG_PATH}" + chattr +C "${IMG_PATH}" >/dev/null 2>&1 || true + + truncate -s 1M "${IMG_PATH}" + mkfs.vfat "${IMG_PATH}" >/dev/null 2>&1 +} + +mount_image() +{ + mkdir -p "${MNT_PATH}" + sudo mount -o loop "${IMG_PATH}" "${MNT_PATH}" +} + +rename_exchange_test() +{ + local rename_exchange=3D"${BASE_DIR}/rename_exchange" + local old_path=3D"${MNT_PATH}/old_file" + local new_path=3D"${MNT_PATH}/new_file" + + echo old | sudo tee "${old_path}" >/dev/null 2>&1 + echo new | sudo tee "${new_path}" >/dev/null 2>&1 + sudo "${rename_exchange}" "${old_path}" "${new_path}" >/dev/null 2>&1 + sudo sync -f "${MNT_PATH}" + grep new "${old_path}" >/dev/null 2>&1 + grep old "${new_path}" >/dev/null 2>&1 +} + +rename_exchange_subdir_test() +{ + local rename_exchange=3D"${BASE_DIR}/rename_exchange" + local dir_path=3D"${MNT_PATH}/subdir" + local old_path=3D"${MNT_PATH}/old_file" + local new_path=3D"${dir_path}/new_file" + + sudo mkdir -p "${dir_path}" + echo old | sudo tee "${old_path}" >/dev/null 2>&1 + echo new | sudo tee "${new_path}" >/dev/null 2>&1 + sudo "${rename_exchange}" "${old_path}" "${new_path}" >/dev/null 2>&1 + sudo sync -f "${MNT_PATH}" + grep new "${old_path}" >/dev/null 2>&1 + grep old "${new_path}" >/dev/null 2>&1 +} + +unmount_image() +{ + sudo umount "${MNT_PATH}" &> /dev/null +} + +create_loopback +mount_image +rename_exchange_test +rename_exchange_subdir_test +unmount_image + +exit 0 --=20 2.36.1