From patchwork Fri Dec 30 22:17:18 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13085344 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 25620C4332F for ; Sat, 31 Dec 2022 01:05:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235846AbiLaBF2 (ORCPT ); Fri, 30 Dec 2022 20:05:28 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40514 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235779AbiLaBF1 (ORCPT ); Fri, 30 Dec 2022 20:05:27 -0500 Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A10AC1DF10 for ; Fri, 30 Dec 2022 17:05:26 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 5CE10B81DE6 for ; Sat, 31 Dec 2022 01:05:25 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 21781C433EF; Sat, 31 Dec 2022 01:05:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1672448724; bh=CnwnnU4y5oIN7jIJL4JAch/MzwrsNkqYAcvtqkLjWC0=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=O+5rxEV9MfM8hldHb3ypFbolc/ZeUwkScf3EIGjA3SBpx4lZVxb5gWduF963k7QUb MqrlWSToyHdv/rat/HRyvFIR+xM83ZBsLs5pCS+IdJwSbRnjZzn/HU2WIcZEYfe3Tn z7/D61pQRpr0w5byM7Q4HUaVipdaYCEw/C8ksK48YPr1fm8P2vN3pwU6ezmTkFdzqF fuzdHNuwm+TorMfPm+g2ZublPt7Rb6/1V/BD2OAbmjDDyb7KY9/mRlVgSCcdTivMJe 8sl51gvIO/mVCbwibne8o5XP23zWdAIt6qsZapy/qm6FtUKKGUSzVmiP3U46CUP0s9 pxXK2H84a3NEw== Subject: [PATCH 01/20] xfs: move inode copy-on-write predicates to xfs_inode.[ch] From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Date: Fri, 30 Dec 2022 14:17:18 -0800 Message-ID: <167243863844.707335.18204528114075088956.stgit@magnolia> In-Reply-To: <167243863809.707335.15895322495460356300.stgit@magnolia> References: <167243863809.707335.15895322495460356300.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Move these inode predicate functions to xfs_inode.[ch] since they're not reflink functions. Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_inode.c | 7 +++++++ fs/xfs/xfs_inode.h | 7 +++++++ fs/xfs/xfs_reflink.h | 10 ---------- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index af4ac808a0e0..abf8844df017 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -3859,3 +3859,10 @@ xfs_inode_alloc_unitsize( return XFS_FSB_TO_B(ip->i_mount, blocks); } + +bool +xfs_is_always_cow_inode( + struct xfs_inode *ip) +{ + return ip->i_mount->m_always_cow && xfs_has_reflink(ip->i_mount); +} diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index be704174fa4f..926f2d74413c 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -276,6 +276,13 @@ static inline bool xfs_is_metadata_inode(struct xfs_inode *ip) xfs_is_quota_inode(&mp->m_sb, ip->i_ino); } +bool xfs_is_always_cow_inode(struct xfs_inode *ip); + +static inline bool xfs_is_cow_inode(struct xfs_inode *ip) +{ + return xfs_is_reflink_inode(ip) || xfs_is_always_cow_inode(ip); +} + /* * Check if an inode has any data in the COW fork. This might be often false * even for inodes with the reflink flag when there is no pending COW operation. diff --git a/fs/xfs/xfs_reflink.h b/fs/xfs/xfs_reflink.h index 65c5dfe17ecf..fb55e4ce49fa 100644 --- a/fs/xfs/xfs_reflink.h +++ b/fs/xfs/xfs_reflink.h @@ -6,16 +6,6 @@ #ifndef __XFS_REFLINK_H #define __XFS_REFLINK_H 1 -static inline bool xfs_is_always_cow_inode(struct xfs_inode *ip) -{ - return ip->i_mount->m_always_cow && xfs_has_reflink(ip->i_mount); -} - -static inline bool xfs_is_cow_inode(struct xfs_inode *ip) -{ - return xfs_is_reflink_inode(ip) || xfs_is_always_cow_inode(ip); -} - extern int xfs_reflink_trim_around_shared(struct xfs_inode *ip, struct xfs_bmbt_irec *irec, bool *shared); int xfs_bmap_trim_cow(struct xfs_inode *ip, struct xfs_bmbt_irec *imap, From patchwork Fri Dec 30 22:17:18 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13085345 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 F262BC4332F for ; Sat, 31 Dec 2022 01:05:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235735AbiLaBFm (ORCPT ); Fri, 30 Dec 2022 20:05:42 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40532 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235779AbiLaBFl (ORCPT ); Fri, 30 Dec 2022 20:05:41 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AA2491DDE4 for ; Fri, 30 Dec 2022 17:05:40 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 4783D61D33 for ; Sat, 31 Dec 2022 01:05:40 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id A5DEEC433D2; Sat, 31 Dec 2022 01:05:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1672448739; bh=XdpvGRV9WB9ZqwfELpTJM9zIM+ySxXLtK1IuKZrHDW4=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=QDZjUOUEsky/OoIC1M24Qg2BWDbJh+nfpGOTjTb3qbl9FbznxMxd8rmR/d3nKrmZC /eDoBYLvR/IXN+hnXyLUXx4s3Ea0n73sHbzytpC30ierVhX8AHnQtwIGswE0OwK9U2 GddKR5CfIhveH4hgDBBN+3McM0O0IYwvnJ2+5aeXkUaQYtzsGFK+BxK54PKsA1QIeL TLG+1+/0oevmcL/XPZZf/mef4hhG5alEeeam1RniMm1Y2WttY5Vjft2CJ7xk8T6d3d Q42ortzQkBLt2s0c7WGqq3ivldjC5lOxXeRYPCHLaA8WdtKhbU6HcLOztZc/2IcbPw rE35fxiG4S0uA== Subject: [PATCH 02/20] xfs: hoist extent size helpers to libxfs From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Date: Fri, 30 Dec 2022 14:17:18 -0800 Message-ID: <167243863859.707335.7535230585116837700.stgit@magnolia> In-Reply-To: <167243863809.707335.15895322495460356300.stgit@magnolia> References: <167243863809.707335.15895322495460356300.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Move the extent size helpers to xfs_bmap.c in libxfs since they're used there already. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_bmap.c | 41 +++++++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_bmap.h | 3 +++ fs/xfs/xfs_inode.c | 43 ------------------------------------------- fs/xfs/xfs_inode.h | 3 --- fs/xfs/xfs_iops.c | 1 + 5 files changed, 45 insertions(+), 46 deletions(-) diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 0dfa84993a9e..5224e3fcce83 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -6413,3 +6413,44 @@ xfs_bmap_query_all( return xfs_btree_query_all(cur, xfs_bmap_query_range_helper, &query); } + +/* Helper function to extract extent size hint from inode */ +xfs_extlen_t +xfs_get_extsz_hint( + struct xfs_inode *ip) +{ + /* + * No point in aligning allocations if we need to COW to actually + * write to them. + */ + if (xfs_is_always_cow_inode(ip)) + return 0; + if ((ip->i_diflags & XFS_DIFLAG_EXTSIZE) && ip->i_extsize) + return ip->i_extsize; + if (XFS_IS_REALTIME_INODE(ip)) + return ip->i_mount->m_sb.sb_rextsize; + return 0; +} + +/* + * Helper function to extract CoW extent size hint from inode. + * Between the extent size hint and the CoW extent size hint, we + * return the greater of the two. If the value is zero (automatic), + * use the default size. + */ +xfs_extlen_t +xfs_get_cowextsz_hint( + struct xfs_inode *ip) +{ + xfs_extlen_t a, b; + + a = 0; + if (ip->i_diflags2 & XFS_DIFLAG2_COWEXTSIZE) + a = ip->i_cowextsize; + b = xfs_get_extsz_hint(ip); + + a = max(a, b); + if (a == 0) + return XFS_DEFAULT_COWEXTSZ_HINT; + return a; +} diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h index 9559f7174bba..d870c6a62e40 100644 --- a/fs/xfs/libxfs/xfs_bmap.h +++ b/fs/xfs/libxfs/xfs_bmap.h @@ -292,4 +292,7 @@ typedef int (*xfs_bmap_query_range_fn)( int xfs_bmap_query_all(struct xfs_btree_cur *cur, xfs_bmap_query_range_fn fn, void *priv); +xfs_extlen_t xfs_get_extsz_hint(struct xfs_inode *ip); +xfs_extlen_t xfs_get_cowextsz_hint(struct xfs_inode *ip); + #endif /* __XFS_BMAP_H__ */ diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index abf8844df017..a4a3ca9a3ea6 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -45,49 +45,6 @@ struct kmem_cache *xfs_inode_cache; STATIC int xfs_iunlink_remove(struct xfs_trans *tp, struct xfs_perag *pag, struct xfs_inode *); -/* - * helper function to extract extent size hint from inode - */ -xfs_extlen_t -xfs_get_extsz_hint( - struct xfs_inode *ip) -{ - /* - * No point in aligning allocations if we need to COW to actually - * write to them. - */ - if (xfs_is_always_cow_inode(ip)) - return 0; - if ((ip->i_diflags & XFS_DIFLAG_EXTSIZE) && ip->i_extsize) - return ip->i_extsize; - if (XFS_IS_REALTIME_INODE(ip)) - return ip->i_mount->m_sb.sb_rextsize; - return 0; -} - -/* - * Helper function to extract CoW extent size hint from inode. - * Between the extent size hint and the CoW extent size hint, we - * return the greater of the two. If the value is zero (automatic), - * use the default size. - */ -xfs_extlen_t -xfs_get_cowextsz_hint( - struct xfs_inode *ip) -{ - xfs_extlen_t a, b; - - a = 0; - if (ip->i_diflags2 & XFS_DIFLAG2_COWEXTSIZE) - a = ip->i_cowextsize; - b = xfs_get_extsz_hint(ip); - - a = max(a, b); - if (a == 0) - return XFS_DEFAULT_COWEXTSZ_HINT; - return a; -} - /* * These two are wrapper routines around the xfs_ilock() routine used to * centralize some grungy code. They are used in places that wish to lock the diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 926f2d74413c..adcdc369396a 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -532,9 +532,6 @@ int xfs_iflush_cluster(struct xfs_buf *); void xfs_lock_two_inodes(struct xfs_inode *ip0, uint ip0_mode, struct xfs_inode *ip1, uint ip1_mode); -xfs_extlen_t xfs_get_extsz_hint(struct xfs_inode *ip); -xfs_extlen_t xfs_get_cowextsz_hint(struct xfs_inode *ip); - int xfs_init_new_inode(struct user_namespace *mnt_userns, struct xfs_trans *tp, struct xfs_inode *pip, xfs_ino_t ino, umode_t mode, xfs_nlink_t nlink, dev_t rdev, prid_t prid, bool init_xattrs, diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index a24bf6bb5094..80f881c69336 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -25,6 +25,7 @@ #include "xfs_error.h" #include "xfs_ioctl.h" #include "xfs_xattr.h" +#include "xfs_bmap.h" #include #include From patchwork Fri Dec 30 22:17:18 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13085346 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 88CEDC4332F for ; Sat, 31 Dec 2022 01:05:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235779AbiLaBF6 (ORCPT ); Fri, 30 Dec 2022 20:05:58 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40792 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235809AbiLaBF5 (ORCPT ); Fri, 30 Dec 2022 20:05:57 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 50A7F64E5 for ; Fri, 30 Dec 2022 17:05:56 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id E445061D33 for ; Sat, 31 Dec 2022 01:05:55 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4CEC6C433D2; Sat, 31 Dec 2022 01:05:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1672448755; bh=Mg/5ahLDD7yE2ihNwf7IYfDSC+XL9Ed3+mItZ0Qvdws=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=MhDiswVF2LdVB50bSASnCUuKbUt2cZJGnZlS/EpF0l/Am3EPwfOfN/s+x37C/v+YU Id/jINbNRqW7aPIDScFychzGlCx01SJO+pC00Zxw4Vpmtw6vGyd3507AGJU0ilIxTJ hFY7sbHa0eLv0ntdqmEhsz5uMTAihZ3ry/bo18MZB9+NjCIxqn07jtFoIPE6eCf5oy uuK6lDfp7ZFUIxFO6W9rsDdyVzmBaCj4GuYl8Eg1OxkP9i3MT88lG1RosMimTptwak U5Zjfj4eO14ICH/v86MZDDAg7AbY+RYGLFrzqW/j+WeHXUN0sX0O5Ra98ExVGOlt8J SuCL6DDidtpUg== Subject: [PATCH 03/20] xfs: hoist inode flag conversion functions to libxfs From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Date: Fri, 30 Dec 2022 14:17:18 -0800 Message-ID: <167243863874.707335.4877917404492106021.stgit@magnolia> In-Reply-To: <167243863809.707335.15895322495460356300.stgit@magnolia> References: <167243863809.707335.15895322495460356300.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Hoist the inode flag conversion functions into libxfs so that we can keep them in sync. Do this by creating a new xfs_inode_util.c file in libxfs. Signed-off-by: Darrick J. Wong --- fs/xfs/Makefile | 1 fs/xfs/libxfs/xfs_bmap.c | 1 fs/xfs/libxfs/xfs_inode_util.c | 124 ++++++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_inode_util.h | 14 +++++ fs/xfs/xfs_inode.c | 49 ---------------- fs/xfs/xfs_inode.h | 2 - fs/xfs/xfs_ioctl.c | 60 ------------------- 7 files changed, 141 insertions(+), 110 deletions(-) create mode 100644 fs/xfs/libxfs/xfs_inode_util.c create mode 100644 fs/xfs/libxfs/xfs_inode_util.h diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index 33b1ea3e6e6b..dac4165b02c0 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile @@ -39,6 +39,7 @@ xfs-y += $(addprefix libxfs/, \ xfs_iext_tree.o \ xfs_inode_fork.o \ xfs_inode_buf.o \ + xfs_inode_util.o \ xfs_log_rlimit.o \ xfs_ag_resv.o \ xfs_rmap.o \ diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 5224e3fcce83..a372618ce393 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -38,6 +38,7 @@ #include "xfs_iomap.h" #include "xfs_health.h" #include "xfs_symlink_remote.h" +#include "xfs_inode_util.h" struct kmem_cache *xfs_bmap_intent_cache; diff --git a/fs/xfs/libxfs/xfs_inode_util.c b/fs/xfs/libxfs/xfs_inode_util.c new file mode 100644 index 000000000000..ed5e1a9b4b8c --- /dev/null +++ b/fs/xfs/libxfs/xfs_inode_util.c @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2000-2006 Silicon Graphics, Inc. + * All Rights Reserved. + */ +#include "xfs.h" +#include "xfs_fs.h" +#include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" +#include "xfs_sb.h" +#include "xfs_mount.h" +#include "xfs_inode.h" +#include "xfs_inode_util.h" + +uint16_t +xfs_flags2diflags( + struct xfs_inode *ip, + unsigned int xflags) +{ + /* can't set PREALLOC this way, just preserve it */ + uint16_t di_flags = + (ip->i_diflags & XFS_DIFLAG_PREALLOC); + + if (xflags & FS_XFLAG_IMMUTABLE) + di_flags |= XFS_DIFLAG_IMMUTABLE; + if (xflags & FS_XFLAG_APPEND) + di_flags |= XFS_DIFLAG_APPEND; + if (xflags & FS_XFLAG_SYNC) + di_flags |= XFS_DIFLAG_SYNC; + if (xflags & FS_XFLAG_NOATIME) + di_flags |= XFS_DIFLAG_NOATIME; + if (xflags & FS_XFLAG_NODUMP) + di_flags |= XFS_DIFLAG_NODUMP; + if (xflags & FS_XFLAG_NODEFRAG) + di_flags |= XFS_DIFLAG_NODEFRAG; + if (xflags & FS_XFLAG_FILESTREAM) + di_flags |= XFS_DIFLAG_FILESTREAM; + if (S_ISDIR(VFS_I(ip)->i_mode)) { + if (xflags & FS_XFLAG_RTINHERIT) + di_flags |= XFS_DIFLAG_RTINHERIT; + if (xflags & FS_XFLAG_NOSYMLINKS) + di_flags |= XFS_DIFLAG_NOSYMLINKS; + if (xflags & FS_XFLAG_EXTSZINHERIT) + di_flags |= XFS_DIFLAG_EXTSZINHERIT; + if (xflags & FS_XFLAG_PROJINHERIT) + di_flags |= XFS_DIFLAG_PROJINHERIT; + } else if (S_ISREG(VFS_I(ip)->i_mode)) { + if (xflags & FS_XFLAG_REALTIME) + di_flags |= XFS_DIFLAG_REALTIME; + if (xflags & FS_XFLAG_EXTSIZE) + di_flags |= XFS_DIFLAG_EXTSIZE; + } + + return di_flags; +} + +uint64_t +xfs_flags2diflags2( + struct xfs_inode *ip, + unsigned int xflags) +{ + uint64_t di_flags2 = + (ip->i_diflags2 & (XFS_DIFLAG2_REFLINK | + XFS_DIFLAG2_BIGTIME | + XFS_DIFLAG2_NREXT64)); + + if (xflags & FS_XFLAG_DAX) + di_flags2 |= XFS_DIFLAG2_DAX; + if (xflags & FS_XFLAG_COWEXTSIZE) + di_flags2 |= XFS_DIFLAG2_COWEXTSIZE; + + return di_flags2; +} + +uint32_t +xfs_ip2xflags( + struct xfs_inode *ip) +{ + uint32_t flags = 0; + + if (ip->i_diflags & XFS_DIFLAG_ANY) { + if (ip->i_diflags & XFS_DIFLAG_REALTIME) + flags |= FS_XFLAG_REALTIME; + if (ip->i_diflags & XFS_DIFLAG_PREALLOC) + flags |= FS_XFLAG_PREALLOC; + if (ip->i_diflags & XFS_DIFLAG_IMMUTABLE) + flags |= FS_XFLAG_IMMUTABLE; + if (ip->i_diflags & XFS_DIFLAG_APPEND) + flags |= FS_XFLAG_APPEND; + if (ip->i_diflags & XFS_DIFLAG_SYNC) + flags |= FS_XFLAG_SYNC; + if (ip->i_diflags & XFS_DIFLAG_NOATIME) + flags |= FS_XFLAG_NOATIME; + if (ip->i_diflags & XFS_DIFLAG_NODUMP) + flags |= FS_XFLAG_NODUMP; + if (ip->i_diflags & XFS_DIFLAG_RTINHERIT) + flags |= FS_XFLAG_RTINHERIT; + if (ip->i_diflags & XFS_DIFLAG_PROJINHERIT) + flags |= FS_XFLAG_PROJINHERIT; + if (ip->i_diflags & XFS_DIFLAG_NOSYMLINKS) + flags |= FS_XFLAG_NOSYMLINKS; + if (ip->i_diflags & XFS_DIFLAG_EXTSIZE) + flags |= FS_XFLAG_EXTSIZE; + if (ip->i_diflags & XFS_DIFLAG_EXTSZINHERIT) + flags |= FS_XFLAG_EXTSZINHERIT; + if (ip->i_diflags & XFS_DIFLAG_NODEFRAG) + flags |= FS_XFLAG_NODEFRAG; + if (ip->i_diflags & XFS_DIFLAG_FILESTREAM) + flags |= FS_XFLAG_FILESTREAM; + } + + if (ip->i_diflags2 & XFS_DIFLAG2_ANY) { + if (ip->i_diflags2 & XFS_DIFLAG2_DAX) + flags |= FS_XFLAG_DAX; + if (ip->i_diflags2 & XFS_DIFLAG2_COWEXTSIZE) + flags |= FS_XFLAG_COWEXTSIZE; + } + + if (xfs_inode_has_attr_fork(ip)) + flags |= FS_XFLAG_HASATTR; + return flags; +} diff --git a/fs/xfs/libxfs/xfs_inode_util.h b/fs/xfs/libxfs/xfs_inode_util.h new file mode 100644 index 000000000000..6ad1898a0f73 --- /dev/null +++ b/fs/xfs/libxfs/xfs_inode_util.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. + * All Rights Reserved. + */ +#ifndef __XFS_INODE_UTIL_H__ +#define __XFS_INODE_UTIL_H__ + +uint16_t xfs_flags2diflags(struct xfs_inode *ip, unsigned int xflags); +uint64_t xfs_flags2diflags2(struct xfs_inode *ip, unsigned int xflags); +uint32_t xfs_dic2xflags(struct xfs_inode *ip); +uint32_t xfs_ip2xflags(struct xfs_inode *ip); + +#endif /* __XFS_INODE_UTIL_H__ */ diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index a4a3ca9a3ea6..cd1d742a8a81 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -544,55 +544,6 @@ xfs_lock_two_inodes( } } -uint -xfs_ip2xflags( - struct xfs_inode *ip) -{ - uint flags = 0; - - if (ip->i_diflags & XFS_DIFLAG_ANY) { - if (ip->i_diflags & XFS_DIFLAG_REALTIME) - flags |= FS_XFLAG_REALTIME; - if (ip->i_diflags & XFS_DIFLAG_PREALLOC) - flags |= FS_XFLAG_PREALLOC; - if (ip->i_diflags & XFS_DIFLAG_IMMUTABLE) - flags |= FS_XFLAG_IMMUTABLE; - if (ip->i_diflags & XFS_DIFLAG_APPEND) - flags |= FS_XFLAG_APPEND; - if (ip->i_diflags & XFS_DIFLAG_SYNC) - flags |= FS_XFLAG_SYNC; - if (ip->i_diflags & XFS_DIFLAG_NOATIME) - flags |= FS_XFLAG_NOATIME; - if (ip->i_diflags & XFS_DIFLAG_NODUMP) - flags |= FS_XFLAG_NODUMP; - if (ip->i_diflags & XFS_DIFLAG_RTINHERIT) - flags |= FS_XFLAG_RTINHERIT; - if (ip->i_diflags & XFS_DIFLAG_PROJINHERIT) - flags |= FS_XFLAG_PROJINHERIT; - if (ip->i_diflags & XFS_DIFLAG_NOSYMLINKS) - flags |= FS_XFLAG_NOSYMLINKS; - if (ip->i_diflags & XFS_DIFLAG_EXTSIZE) - flags |= FS_XFLAG_EXTSIZE; - if (ip->i_diflags & XFS_DIFLAG_EXTSZINHERIT) - flags |= FS_XFLAG_EXTSZINHERIT; - if (ip->i_diflags & XFS_DIFLAG_NODEFRAG) - flags |= FS_XFLAG_NODEFRAG; - if (ip->i_diflags & XFS_DIFLAG_FILESTREAM) - flags |= FS_XFLAG_FILESTREAM; - } - - if (ip->i_diflags2 & XFS_DIFLAG2_ANY) { - if (ip->i_diflags2 & XFS_DIFLAG2_DAX) - flags |= FS_XFLAG_DAX; - if (ip->i_diflags2 & XFS_DIFLAG2_COWEXTSIZE) - flags |= FS_XFLAG_COWEXTSIZE; - } - - if (xfs_inode_has_attr_fork(ip)) - flags |= FS_XFLAG_HASATTR; - return flags; -} - /* * Lookups up an inode from "name". If ci_name is not NULL, then a CI match * is allowed, otherwise it has to be an exact match. If a CI match is found, diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index adcdc369396a..2f6072d78444 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -8,6 +8,7 @@ #include "xfs_inode_buf.h" #include "xfs_inode_fork.h" +#include "xfs_inode_util.h" /* * Kernel only inode definitions @@ -518,7 +519,6 @@ bool xfs_isilocked(struct xfs_inode *, uint); uint xfs_ilock_data_map_shared(struct xfs_inode *); uint xfs_ilock_attr_map_shared(struct xfs_inode *); -uint xfs_ip2xflags(struct xfs_inode *); int xfs_ifree(struct xfs_trans *, struct xfs_inode *); int xfs_itruncate_extents_flags(struct xfs_trans **, struct xfs_inode *, int, xfs_fsize_t, int); diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index df6601eda7ec..615fd1e4a611 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -1055,66 +1055,6 @@ xfs_fileattr_get( return 0; } -STATIC uint16_t -xfs_flags2diflags( - struct xfs_inode *ip, - unsigned int xflags) -{ - /* can't set PREALLOC this way, just preserve it */ - uint16_t di_flags = - (ip->i_diflags & XFS_DIFLAG_PREALLOC); - - if (xflags & FS_XFLAG_IMMUTABLE) - di_flags |= XFS_DIFLAG_IMMUTABLE; - if (xflags & FS_XFLAG_APPEND) - di_flags |= XFS_DIFLAG_APPEND; - if (xflags & FS_XFLAG_SYNC) - di_flags |= XFS_DIFLAG_SYNC; - if (xflags & FS_XFLAG_NOATIME) - di_flags |= XFS_DIFLAG_NOATIME; - if (xflags & FS_XFLAG_NODUMP) - di_flags |= XFS_DIFLAG_NODUMP; - if (xflags & FS_XFLAG_NODEFRAG) - di_flags |= XFS_DIFLAG_NODEFRAG; - if (xflags & FS_XFLAG_FILESTREAM) - di_flags |= XFS_DIFLAG_FILESTREAM; - if (S_ISDIR(VFS_I(ip)->i_mode)) { - if (xflags & FS_XFLAG_RTINHERIT) - di_flags |= XFS_DIFLAG_RTINHERIT; - if (xflags & FS_XFLAG_NOSYMLINKS) - di_flags |= XFS_DIFLAG_NOSYMLINKS; - if (xflags & FS_XFLAG_EXTSZINHERIT) - di_flags |= XFS_DIFLAG_EXTSZINHERIT; - if (xflags & FS_XFLAG_PROJINHERIT) - di_flags |= XFS_DIFLAG_PROJINHERIT; - } else if (S_ISREG(VFS_I(ip)->i_mode)) { - if (xflags & FS_XFLAG_REALTIME) - di_flags |= XFS_DIFLAG_REALTIME; - if (xflags & FS_XFLAG_EXTSIZE) - di_flags |= XFS_DIFLAG_EXTSIZE; - } - - return di_flags; -} - -STATIC uint64_t -xfs_flags2diflags2( - struct xfs_inode *ip, - unsigned int xflags) -{ - uint64_t di_flags2 = - (ip->i_diflags2 & (XFS_DIFLAG2_REFLINK | - XFS_DIFLAG2_BIGTIME | - XFS_DIFLAG2_NREXT64)); - - if (xflags & FS_XFLAG_DAX) - di_flags2 |= XFS_DIFLAG2_DAX; - if (xflags & FS_XFLAG_COWEXTSIZE) - di_flags2 |= XFS_DIFLAG2_COWEXTSIZE; - - return di_flags2; -} - static int xfs_ioctl_setattr_xflags( struct xfs_trans *tp, From patchwork Fri Dec 30 22:17:18 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13085347 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 B0C40C4332F for ; Sat, 31 Dec 2022 01:06:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235857AbiLaBGN (ORCPT ); Fri, 30 Dec 2022 20:06:13 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40814 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235809AbiLaBGM (ORCPT ); Fri, 30 Dec 2022 20:06:12 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D276064F9 for ; Fri, 30 Dec 2022 17:06:11 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 72C3D61D33 for ; Sat, 31 Dec 2022 01:06:11 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id D1038C433EF; Sat, 31 Dec 2022 01:06:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1672448770; bh=jmAyw5GmyH2zqW2aAmCcqVxubT1Dk2vXyMCuAnh2CrM=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=TK92Xyf0v8vi6XmZT6uIKezWBnL6aZuy+TDRjjVR678CE2ublRllIjOoyjMfrKKLW dqu0y4rRkkGQtmCnCcgdeknfqePbSvJm9AhynMEIZIP6g2lfryhyF8M7smjHNggkRb IMtUAN7YsEGdj0TtBdgVHgIb7F5vUmQofF3p8G7uIIzl8OrJZFtBd//d1LCobyULds 41CoGiqr4ZZ1vmvpnSqStS+fN7Tlh+z+I/wWaZd+O+QrXi4tfSTNEdyo9FNvK9lGoA 4NAkO9JSaGVGjckCQZjg9YB0i3UKxdPjRxHh68ZcLGELXOprSHOxMpn32RQc+iSSs2 ts62TridvVMUA== Subject: [PATCH 04/20] xfs: hoist project id get/set functions to libxfs From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Date: Fri, 30 Dec 2022 14:17:18 -0800 Message-ID: <167243863889.707335.1570079499343467331.stgit@magnolia> In-Reply-To: <167243863809.707335.15895322495460356300.stgit@magnolia> References: <167243863809.707335.15895322495460356300.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Move the project id get and set functions into libxfs. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_inode_util.c | 11 +++++++++++ fs/xfs/libxfs/xfs_inode_util.h | 2 ++ fs/xfs/xfs_inode.h | 9 --------- fs/xfs/xfs_linux.h | 2 -- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/fs/xfs/libxfs/xfs_inode_util.c b/fs/xfs/libxfs/xfs_inode_util.c index ed5e1a9b4b8c..2624d18922c0 100644 --- a/fs/xfs/libxfs/xfs_inode_util.c +++ b/fs/xfs/libxfs/xfs_inode_util.c @@ -122,3 +122,14 @@ xfs_ip2xflags( flags |= FS_XFLAG_HASATTR; return flags; } + +#define XFS_PROJID_DEFAULT 0 + +prid_t +xfs_get_initial_prid(struct xfs_inode *dp) +{ + if (dp->i_diflags & XFS_DIFLAG_PROJINHERIT) + return dp->i_projid; + + return XFS_PROJID_DEFAULT; +} diff --git a/fs/xfs/libxfs/xfs_inode_util.h b/fs/xfs/libxfs/xfs_inode_util.h index 6ad1898a0f73..f7e4d5a8235d 100644 --- a/fs/xfs/libxfs/xfs_inode_util.h +++ b/fs/xfs/libxfs/xfs_inode_util.h @@ -11,4 +11,6 @@ uint64_t xfs_flags2diflags2(struct xfs_inode *ip, unsigned int xflags); uint32_t xfs_dic2xflags(struct xfs_inode *ip); uint32_t xfs_ip2xflags(struct xfs_inode *ip); +prid_t xfs_get_initial_prid(struct xfs_inode *dp); + #endif /* __XFS_INODE_UTIL_H__ */ diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 2f6072d78444..4803904686f5 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -255,15 +255,6 @@ xfs_iflags_test_and_set(xfs_inode_t *ip, unsigned short flags) return ret; } -static inline prid_t -xfs_get_initial_prid(struct xfs_inode *dp) -{ - if (dp->i_diflags & XFS_DIFLAG_PROJINHERIT) - return dp->i_projid; - - return XFS_PROJID_DEFAULT; -} - static inline bool xfs_is_reflink_inode(struct xfs_inode *ip) { return ip->i_diflags2 & XFS_DIFLAG2_REFLINK; diff --git a/fs/xfs/xfs_linux.h b/fs/xfs/xfs_linux.h index 7e9bf03c80a3..2cdb3411aabb 100644 --- a/fs/xfs/xfs_linux.h +++ b/fs/xfs/xfs_linux.h @@ -134,8 +134,6 @@ typedef __u32 xfs_nlink_t; */ #define __this_address ({ __label__ __here; __here: barrier(); &&__here; }) -#define XFS_PROJID_DEFAULT 0 - #define howmany(x, y) (((x)+((y)-1))/(y)) static inline void delay(long ticks) From patchwork Fri Dec 30 22:17:19 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13085348 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 59C41C4332F for ; Sat, 31 Dec 2022 01:06:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235900AbiLaBG3 (ORCPT ); Fri, 30 Dec 2022 20:06:29 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40850 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235809AbiLaBG2 (ORCPT ); Fri, 30 Dec 2022 20:06:28 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7205164E5 for ; Fri, 30 Dec 2022 17:06:27 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id F32E861D30 for ; Sat, 31 Dec 2022 01:06:26 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 609CCC433EF; Sat, 31 Dec 2022 01:06:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1672448786; bh=/Hzg1eitKeaWuD22u5EPXcIKtbW3bIbstHP6Nec1ZJc=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=nLVsxZWDZHXv2QFQ7e3QhBIu6KoCazaGegffq/PjCezQRPGTr0QZN0L2y/UrQhX9y KqH3NYc7UIfJUrYQQpV1gXKdpZKXf+xgfV/A43886AWCFrM5m24Yp6uw6NqQgpWwMs at89m4Le0mfM2Nu03O6P3iyyXA6VkYx8iiudnzjvlifBCZqwti5DF4zZlwkNm8MFAw QHHi7fhk7QH/88GL+0fFCcgcl/+XXQuZ9r8adbZdr5nxRwlXBODRgPyncNLwJjbH1O Eh3N73/odHS99xucUnAGQarUP/e7Di4axeEaMZPz4yxAmCQaHQhicGQ+0yFBjS79Cg ihLbwEJud3eeQ== Subject: [PATCH 05/20] xfs: pack icreate initialization parameters into a separate structure From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Date: Fri, 30 Dec 2022 14:17:19 -0800 Message-ID: <167243863904.707335.15969998887616204747.stgit@magnolia> In-Reply-To: <167243863809.707335.15895322495460356300.stgit@magnolia> References: <167243863809.707335.15895322495460356300.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Callers that want to create an inode currently pass all possible file attribute values for the new inode into xfs_init_new_inode as ten separate parameters. This causes two code maintenance issues: first, we have large multi-line call sites which programmers must read carefully to make sure they did not accidentally invert a value. Second, all three file id parameters must be passed separately to the quota functions; any discrepancy results in quota count errors. Clean this up by creating a new icreate_args structure to hold all this information, some helpers to initialize them properly, and make the callers pass this structure through to the creation function, whose name we shorten to xfs_icreate. This eliminates the issues, enables us to keep the inode init code in sync with userspace via libxfs, and is needed for future metadata directory tree management. (A subsequent cleanup will also fix the quota alloc calls.) Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_inode_util.h | 31 +++++++++++++ fs/xfs/scrub/tempfile.c | 13 +++-- fs/xfs/xfs_inode.c | 99 ++++++++++++++++++++++++++++------------ fs/xfs/xfs_inode.h | 10 ++-- fs/xfs/xfs_qm.c | 8 ++- fs/xfs/xfs_symlink.c | 14 +++--- 6 files changed, 127 insertions(+), 48 deletions(-) diff --git a/fs/xfs/libxfs/xfs_inode_util.h b/fs/xfs/libxfs/xfs_inode_util.h index f7e4d5a8235d..466f0767ab5d 100644 --- a/fs/xfs/libxfs/xfs_inode_util.h +++ b/fs/xfs/libxfs/xfs_inode_util.h @@ -13,4 +13,35 @@ uint32_t xfs_ip2xflags(struct xfs_inode *ip); prid_t xfs_get_initial_prid(struct xfs_inode *dp); +/* + * Initial ids, link count, device number, and mode of a new inode. + * + * Due to our only partial reliance on the VFS to propagate uid and gid values + * according to accepted Unix behaviors, callers must initialize mnt_userns to + * the appropriate namespace, uid to fsuid_into_mnt(), and gid to + * fsgid_into_mnt() to get the correct inheritance behaviors when + * XFS_MOUNT_GRPID is set. Use the xfs_ialloc_inherit_args() helper. + * + * To override the default ids, use the FORCE flags defined below. + */ +struct xfs_icreate_args { + struct user_namespace *mnt_userns; + struct xfs_inode *pip; /* parent inode or null */ + + kuid_t uid; + kgid_t gid; + prid_t prid; + + xfs_nlink_t nlink; + dev_t rdev; + + umode_t mode; + +#define XFS_ICREATE_ARGS_FORCE_UID (1 << 0) +#define XFS_ICREATE_ARGS_FORCE_GID (1 << 1) +#define XFS_ICREATE_ARGS_FORCE_MODE (1 << 2) +#define XFS_ICREATE_ARGS_INIT_XATTRS (1 << 3) + uint16_t flags; +}; + #endif /* __XFS_INODE_UTIL_H__ */ diff --git a/fs/xfs/scrub/tempfile.c b/fs/xfs/scrub/tempfile.c index e5087f14343b..2c630a5e23ea 100644 --- a/fs/xfs/scrub/tempfile.c +++ b/fs/xfs/scrub/tempfile.c @@ -40,6 +40,7 @@ xrep_tempfile_create( struct xfs_scrub *sc, uint16_t mode) { + struct xfs_icreate_args args = { .pip = sc->mp->m_rootip, }; struct xfs_mount *mp = sc->mp; struct xfs_trans *tp = NULL; struct xfs_dquot *udqp = NULL; @@ -60,12 +61,15 @@ xrep_tempfile_create( ASSERT(sc->tp == NULL); ASSERT(sc->tempip == NULL); + /* Force everything to have the root ids and mode we want. */ + xfs_icreate_args_rootfile(&args, mode); + /* * Make sure that we have allocated dquot(s) on disk. The temporary * inode should be completely root owned so that we don't fail due to * quota limits. */ - error = xfs_qm_vop_dqalloc(dp, GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, 0, + error = xfs_qm_vop_dqalloc(dp, args.uid, args.gid, args.prid, XFS_QMOPT_QUOTALL, &udqp, &gdqp, &pdqp); if (error) return error; @@ -87,14 +91,11 @@ xrep_tempfile_create( error = xfs_dialloc(&tp, dp->i_ino, mode, &ino); if (error) goto out_trans_cancel; - error = xfs_init_new_inode(&init_user_ns, tp, dp, ino, mode, 0, 0, - 0, false, &sc->tempip); + error = xfs_icreate(tp, ino, &args, &sc->tempip); if (error) goto out_trans_cancel; - /* Change the ownership of the inode to root. */ - VFS_I(sc->tempip)->i_uid = GLOBAL_ROOT_UID; - VFS_I(sc->tempip)->i_gid = GLOBAL_ROOT_GID; + /* We don't touch file data, so drop the realtime flags. */ sc->tempip->i_diflags &= ~(XFS_DIFLAG_REALTIME | XFS_DIFLAG_RTINHERIT); xfs_trans_log_inode(tp, sc->tempip, XFS_ILOG_CORE); diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index cd1d742a8a81..ffbf504891aa 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -679,18 +679,13 @@ xfs_inode_inherit_flags2( * caller locked exclusively. */ int -xfs_init_new_inode( - struct user_namespace *mnt_userns, +xfs_icreate( struct xfs_trans *tp, - struct xfs_inode *pip, xfs_ino_t ino, - umode_t mode, - xfs_nlink_t nlink, - dev_t rdev, - prid_t prid, - bool init_xattrs, + const struct xfs_icreate_args *args, struct xfs_inode **ipp) { + struct xfs_inode *pip = args->pip; struct inode *dir = pip ? VFS_I(pip) : NULL; struct xfs_mount *mp = tp->t_mountp; struct xfs_inode *ip; @@ -723,16 +718,16 @@ xfs_init_new_inode( ASSERT(ip != NULL); inode = VFS_I(ip); - set_nlink(inode, nlink); - inode->i_rdev = rdev; - ip->i_projid = prid; + set_nlink(inode, args->nlink); + inode->i_rdev = args->rdev; + ip->i_projid = args->prid; if (dir && !(dir->i_mode & S_ISGID) && xfs_has_grpid(mp)) { - inode_fsuid_set(inode, mnt_userns); + inode_fsuid_set(inode, args->mnt_userns); inode->i_gid = dir->i_gid; - inode->i_mode = mode; + inode->i_mode = args->mode; } else { - inode_init_owner(mnt_userns, inode, dir, mode); + inode_init_owner(args->mnt_userns, inode, dir, args->mode); } /* @@ -741,9 +736,21 @@ xfs_init_new_inode( * (and only if the irix_sgid_inherit compatibility variable is set). */ if (irix_sgid_inherit && (inode->i_mode & S_ISGID) && - !vfsgid_in_group_p(i_gid_into_vfsgid(mnt_userns, inode))) + !vfsgid_in_group_p(i_gid_into_vfsgid(args->mnt_userns, inode))) inode->i_mode &= ~S_ISGID; + /* struct copies */ + if (args->flags & XFS_ICREATE_ARGS_FORCE_UID) + inode->i_uid = args->uid; + else + ASSERT(uid_eq(inode->i_uid, args->uid)); + if (args->flags & XFS_ICREATE_ARGS_FORCE_GID) + inode->i_gid = args->gid; + else if (!pip || !XFS_INHERIT_GID(pip)) + ASSERT(gid_eq(inode->i_gid, args->gid)); + if (args->flags & XFS_ICREATE_ARGS_FORCE_MODE) + inode->i_mode = args->mode; + ip->i_disk_size = 0; ip->i_df.if_nextents = 0; ASSERT(ip->i_nblocks == 0); @@ -763,7 +770,7 @@ xfs_init_new_inode( } flags = XFS_ILOG_CORE; - switch (mode & S_IFMT) { + switch (args->mode & S_IFMT) { case S_IFIFO: case S_IFCHR: case S_IFBLK: @@ -796,7 +803,8 @@ xfs_init_new_inode( * this saves us from needing to run a separate transaction to set the * fork offset in the immediate future. */ - if (init_xattrs && xfs_has_attr(mp)) { + if ((args->flags & XFS_ICREATE_ARGS_INIT_XATTRS) && + xfs_has_attr(mp)) { ip->i_forkoff = xfs_default_attroffset(ip) >> 3; xfs_ifork_init_attr(ip, XFS_DINODE_FMT_EXTENTS, 0); } @@ -814,6 +822,38 @@ xfs_init_new_inode( return 0; } +/* Set up inode attributes for newly created children of a directory. */ +void +xfs_icreate_args_inherit( + struct xfs_icreate_args *args, + struct xfs_inode *dp, + struct user_namespace *mnt_userns, + umode_t mode) +{ + args->mnt_userns = mnt_userns; + args->pip = dp; + args->uid = mapped_fsuid(mnt_userns, &init_user_ns); + args->gid = mapped_fsgid(mnt_userns, &init_user_ns); + args->prid = xfs_get_initial_prid(dp); + args->mode = mode; +} + +/* Set up inode attributes for newly created internal files. */ +void +xfs_icreate_args_rootfile( + struct xfs_icreate_args *args, + umode_t mode) +{ + args->mnt_userns = &init_user_ns; + args->uid = GLOBAL_ROOT_UID; + args->gid = GLOBAL_ROOT_GID; + args->prid = 0; + args->mode = mode; + args->flags = XFS_ICREATE_ARGS_FORCE_UID | + XFS_ICREATE_ARGS_FORCE_GID | + XFS_ICREATE_ARGS_FORCE_MODE; +} + /* * Decrement the link count on an inode & log the change. If this causes the * link count to go to zero, move the inode to AGI unlinked list so that it can @@ -970,13 +1010,16 @@ xfs_create( bool init_xattrs, xfs_inode_t **ipp) { + struct xfs_icreate_args args = { + .rdev = rdev, + .nlink = S_ISDIR(mode) ? 2 : 1, + }; int is_dir = S_ISDIR(mode); struct xfs_mount *mp = dp->i_mount; struct xfs_inode *ip = NULL; struct xfs_trans *tp = NULL; int error; bool unlock_dp_on_error = false; - prid_t prid; struct xfs_dquot *udqp = NULL; struct xfs_dquot *gdqp = NULL; struct xfs_dquot *pdqp = NULL; @@ -989,13 +1032,14 @@ xfs_create( if (xfs_is_shutdown(mp)) return -EIO; - prid = xfs_get_initial_prid(dp); + xfs_icreate_args_inherit(&args, dp, mnt_userns, mode); + if (init_xattrs) + args.flags |= XFS_ICREATE_ARGS_INIT_XATTRS; /* * Make sure that we have allocated dquot(s) on disk. */ - error = xfs_qm_vop_dqalloc(dp, mapped_fsuid(mnt_userns, &init_user_ns), - mapped_fsgid(mnt_userns, &init_user_ns), prid, + error = xfs_qm_vop_dqalloc(dp, args.uid, args.gid, args.prid, XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp, &pdqp); if (error) @@ -1036,8 +1080,7 @@ xfs_create( */ error = xfs_dialloc(&tp, dp->i_ino, mode, &ino); if (!error) - error = xfs_init_new_inode(mnt_userns, tp, dp, ino, mode, - is_dir ? 2 : 1, rdev, prid, init_xattrs, &ip); + error = xfs_icreate(tp, ino, &args, &ip); if (error) goto out_trans_cancel; @@ -1133,11 +1176,11 @@ xfs_create_tmpfile( umode_t mode, struct xfs_inode **ipp) { + struct xfs_icreate_args args = { NULL }; struct xfs_mount *mp = dp->i_mount; struct xfs_inode *ip = NULL; struct xfs_trans *tp = NULL; int error; - prid_t prid; struct xfs_dquot *udqp = NULL; struct xfs_dquot *gdqp = NULL; struct xfs_dquot *pdqp = NULL; @@ -1148,13 +1191,12 @@ xfs_create_tmpfile( if (xfs_is_shutdown(mp)) return -EIO; - prid = xfs_get_initial_prid(dp); + xfs_icreate_args_inherit(&args, dp, mnt_userns, mode); /* * Make sure that we have allocated dquot(s) on disk. */ - error = xfs_qm_vop_dqalloc(dp, mapped_fsuid(mnt_userns, &init_user_ns), - mapped_fsgid(mnt_userns, &init_user_ns), prid, + error = xfs_qm_vop_dqalloc(dp, args.uid, args.gid, args.prid, XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp, &pdqp); if (error) @@ -1170,8 +1212,7 @@ xfs_create_tmpfile( error = xfs_dialloc(&tp, dp->i_ino, mode, &ino); if (!error) - error = xfs_init_new_inode(mnt_userns, tp, dp, ino, mode, - 0, 0, prid, false, &ip); + error = xfs_icreate(tp, ino, &args, &ip); if (error) goto out_trans_cancel; diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 4803904686f5..cb627543e9fb 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -523,10 +523,8 @@ int xfs_iflush_cluster(struct xfs_buf *); void xfs_lock_two_inodes(struct xfs_inode *ip0, uint ip0_mode, struct xfs_inode *ip1, uint ip1_mode); -int xfs_init_new_inode(struct user_namespace *mnt_userns, struct xfs_trans *tp, - struct xfs_inode *pip, xfs_ino_t ino, umode_t mode, - xfs_nlink_t nlink, dev_t rdev, prid_t prid, bool init_xattrs, - struct xfs_inode **ipp); +int xfs_icreate(struct xfs_trans *tp, xfs_ino_t ino, + const struct xfs_icreate_args *args, struct xfs_inode **ipp); static inline int xfs_itruncate_extents( @@ -626,4 +624,8 @@ void xfs_nlink_hook_del(struct xfs_mount *mp, struct xfs_nlink_hook *hook); # define xfs_nlink_dirent_delta(dp, ip, delta, name) ((void)0) #endif /* CONFIG_XFS_LIVE_HOOKS */ +void xfs_icreate_args_inherit(struct xfs_icreate_args *args, struct xfs_inode *dp, + struct user_namespace *mnt_userns, umode_t mode); +void xfs_icreate_args_rootfile(struct xfs_icreate_args *args, umode_t mode); + #endif /* __XFS_INODE_H__ */ diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c index 59ace2eedf69..da6c6f0e1ced 100644 --- a/fs/xfs/xfs_qm.c +++ b/fs/xfs/xfs_qm.c @@ -791,12 +791,16 @@ xfs_qm_qino_alloc( return error; if (need_alloc) { + struct xfs_icreate_args args = { + .nlink = 1, + }; xfs_ino_t ino; + xfs_icreate_args_rootfile(&args, S_IFREG); + error = xfs_dialloc(&tp, 0, S_IFREG, &ino); if (!error) - error = xfs_init_new_inode(&init_user_ns, tp, NULL, ino, - S_IFREG, 1, 0, 0, false, ipp); + error = xfs_icreate(tp, ino, &args, ipp); if (error) { xfs_trans_cancel(tp); return error; diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c index 8cf69ca4bd7c..c27bf49de7bf 100644 --- a/fs/xfs/xfs_symlink.c +++ b/fs/xfs/xfs_symlink.c @@ -88,6 +88,9 @@ xfs_symlink( umode_t mode, struct xfs_inode **ipp) { + struct xfs_icreate_args args = { + .nlink = 1, + }; struct xfs_mount *mp = dp->i_mount; struct xfs_trans *tp = NULL; struct xfs_inode *ip = NULL; @@ -95,7 +98,6 @@ xfs_symlink( int pathlen; bool unlock_dp_on_error = false; xfs_filblks_t fs_blocks; - prid_t prid; struct xfs_dquot *udqp = NULL; struct xfs_dquot *gdqp = NULL; struct xfs_dquot *pdqp = NULL; @@ -117,13 +119,13 @@ xfs_symlink( return -ENAMETOOLONG; ASSERT(pathlen > 0); - prid = xfs_get_initial_prid(dp); + xfs_icreate_args_inherit(&args, dp, mnt_userns, + S_IFLNK | (mode & ~S_IFMT)); /* * Make sure that we have allocated dquot(s) on disk. */ - error = xfs_qm_vop_dqalloc(dp, mapped_fsuid(mnt_userns, &init_user_ns), - mapped_fsgid(mnt_userns, &init_user_ns), prid, + error = xfs_qm_vop_dqalloc(dp, args.uid, args.gid, args.prid, XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp, &pdqp); if (error) @@ -160,9 +162,7 @@ xfs_symlink( */ error = xfs_dialloc(&tp, dp->i_ino, S_IFLNK, &ino); if (!error) - error = xfs_init_new_inode(mnt_userns, tp, dp, ino, - S_IFLNK | (mode & ~S_IFMT), 1, 0, prid, - false, &ip); + error = xfs_icreate(tp, ino, &args, &ip); if (error) goto out_trans_cancel; From patchwork Fri Dec 30 22:17:19 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13085349 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 665D4C4332F for ; Sat, 31 Dec 2022 01:06:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235910AbiLaBGq (ORCPT ); Fri, 30 Dec 2022 20:06:46 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40880 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235809AbiLaBGp (ORCPT ); Fri, 30 Dec 2022 20:06:45 -0500 Received: from ams.source.kernel.org (ams.source.kernel.org [145.40.68.75]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 969D52DF9 for ; Fri, 30 Dec 2022 17:06:44 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 48752B81DF9 for ; Sat, 31 Dec 2022 01:06:43 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id E0F56C433D2; Sat, 31 Dec 2022 01:06:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1672448802; bh=bK+rZrpSEjIwHetom15pPw1EiIzBU/FSEr2ingZnJnk=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=WaI0NqZ9GofNaJtFkUeovq8WKCL9DM9pNorB4AFGkFLw4oBThPae7fR1gn/v+OoIs ObX0Nis0nFAc/iUUSbiiq0xHGI8JY1SgvJNVp/4WnIucZiTd6D71oUOI/wnc7kFmJA axI9sTPUVYu9kEAq9UhYcBUjdTs29gwFi3byPaQNL88hSLxgPg9WVpzWavG0CANYIB GGyBaF74M3M5SHkEoL1xT5SLv1sXHLt7CB9+s2AQo6uXFDZvnmoT/ZWwEPZesMucMt M7wqFKX2gRrF9cax1yiYe7gnJokANyvjQNUjXpxLg4SJs4+3GaqbEIZfXr4EIANV9C ac4FulpE2B+ZA== Subject: [PATCH 06/20] xfs: implement atime updates in xfs_trans_ichgtime From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Date: Fri, 30 Dec 2022 14:17:19 -0800 Message-ID: <167243863918.707335.13942694678423467250.stgit@magnolia> In-Reply-To: <167243863809.707335.15895322495460356300.stgit@magnolia> References: <167243863809.707335.15895322495460356300.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Enable xfs_trans_ichgtime to change the inode access time so that we can use this function to set inode times when allocating inodes instead of open-coding it. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_shared.h | 1 + fs/xfs/libxfs/xfs_trans_inode.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/fs/xfs/libxfs/xfs_shared.h b/fs/xfs/libxfs/xfs_shared.h index 5127fa88531f..acf527eb0e1c 100644 --- a/fs/xfs/libxfs/xfs_shared.h +++ b/fs/xfs/libxfs/xfs_shared.h @@ -137,6 +137,7 @@ void xfs_log_get_max_trans_res(struct xfs_mount *mp, #define XFS_ICHGTIME_MOD 0x1 /* data fork modification timestamp */ #define XFS_ICHGTIME_CHG 0x2 /* inode field change timestamp */ #define XFS_ICHGTIME_CREATE 0x4 /* inode create timestamp */ +#define XFS_ICHGTIME_ACCESS 0x8 /* last access timestamp */ /* Computed inode geometry for the filesystem. */ struct xfs_ino_geometry { diff --git a/fs/xfs/libxfs/xfs_trans_inode.c b/fs/xfs/libxfs/xfs_trans_inode.c index 8b5547073379..6a3a869635bf 100644 --- a/fs/xfs/libxfs/xfs_trans_inode.c +++ b/fs/xfs/libxfs/xfs_trans_inode.c @@ -69,6 +69,8 @@ xfs_trans_ichgtime( inode->i_mtime = tv; if (flags & XFS_ICHGTIME_CHG) inode->i_ctime = tv; + if (flags & XFS_ICHGTIME_ACCESS) + inode->i_atime = tv; if (flags & XFS_ICHGTIME_CREATE) ip->i_crtime = tv; } From patchwork Fri Dec 30 22:17:19 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13085350 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 25A3FC4332F for ; Sat, 31 Dec 2022 01:07:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235809AbiLaBHC (ORCPT ); Fri, 30 Dec 2022 20:07:02 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40928 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235913AbiLaBHB (ORCPT ); Fri, 30 Dec 2022 20:07:01 -0500 Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 220651573A for ; Fri, 30 Dec 2022 17:07:00 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id CF7E3B81DE6 for ; Sat, 31 Dec 2022 01:06:58 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8A7ADC433EF; Sat, 31 Dec 2022 01:06:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1672448817; bh=hy3vBtUlSK3owKpnKRIUO+0a115PSlhduXNOVthMFGQ=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=PnBbHHh/mzCbsrlEjKqOnogmcj24o588Vf3PxkVMRa41n9e/Uj5hk0P9ON6Wex2CD Tr8dOXg3y3tirDtJ2Y4hfpUM02KSaszWAEI3r4PukUVCThMPTc3KJ/d9tTgCC+rVZD BIYYxjGaD4091nRCFUCjVc5Jaa9ffzf0hZq5htecOShSDUfWzLpx66g7C1t1GcEgTY k5ZS8PxEKFxBeMSoCoeEkolaNmjz3OMQ0JbgKv7HVzamRZKP/QUW+HuEyxjvvE78fM kXKSDLfPKEVLYKuUSN/+j994aefoi4ISe75jnkDx+p9ulBttS3pA7lRBydB9+97pzd Oal/U1GMTz+Uw== Subject: [PATCH 07/20] xfs: use xfs_trans_ichgtime to set times when allocating inode From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Date: Fri, 30 Dec 2022 14:17:19 -0800 Message-ID: <167243863932.707335.13862526907703121698.stgit@magnolia> In-Reply-To: <167243863809.707335.15895322495460356300.stgit@magnolia> References: <167243863809.707335.15895322495460356300.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Use xfs_trans_ichgtime to set the inode times when allocating an inode, instead of open-coding them here. Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_inode.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index ffbf504891aa..7a634a1ea111 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -689,10 +689,11 @@ xfs_icreate( struct inode *dir = pip ? VFS_I(pip) : NULL; struct xfs_mount *mp = tp->t_mountp; struct xfs_inode *ip; - unsigned int flags; - int error; - struct timespec64 tv; struct inode *inode; + unsigned int flags; + int times = XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG | + XFS_ICHGTIME_ACCESS; + int error; /* * Protect against obviously corrupt allocation btree records. Later @@ -755,20 +756,17 @@ xfs_icreate( ip->i_df.if_nextents = 0; ASSERT(ip->i_nblocks == 0); - tv = current_time(inode); - inode->i_mtime = tv; - inode->i_atime = tv; - inode->i_ctime = tv; - ip->i_extsize = 0; ip->i_diflags = 0; if (xfs_has_v3inodes(mp)) { inode_set_iversion(inode, 1); ip->i_cowextsize = 0; - ip->i_crtime = tv; + times |= XFS_ICHGTIME_CREATE; } + xfs_trans_ichgtime(tp, ip, times); + flags = XFS_ILOG_CORE; switch (args->mode & S_IFMT) { case S_IFIFO: From patchwork Fri Dec 30 22:17:19 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13085351 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 1F1B4C4332F for ; Sat, 31 Dec 2022 01:07:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235913AbiLaBHQ (ORCPT ); Fri, 30 Dec 2022 20:07:16 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40946 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235933AbiLaBHP (ORCPT ); Fri, 30 Dec 2022 20:07:15 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 222A715F3F for ; Fri, 30 Dec 2022 17:07:14 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id B25EC61D03 for ; Sat, 31 Dec 2022 01:07:13 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1A09EC433D2; Sat, 31 Dec 2022 01:07:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1672448833; bh=54/Oe335M0PgDjW+vctb7QIGbdsV77/I3s6CjrVt4+o=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=bS8LBBc8sXjWYemmvjIYckGXt3rcd83p7LS3vsiYYq4Mm6pRUWDiPA330EK5OkC0V T5ZP8ppPTX9DOuGRWRJQlMR64GkssXMUp6CV9q1m2ZFaxX5gP0l7ZYcs55+5ZjP4ga yEO4wqLp/Hul9Nmy95xrJEG6JWvErQIfvhNn/rbRb8+/y3gAJbJUMKOe4gx3iMriQd rme7NUd1PsK2BcFaH4KHM6exWoLwRK9cVnY9JZo1FMKFNlypnJIyB0BkLQzt5QJN6M GTshKW6muRPJ5B9PamN5kTKsMuHWPy3iwpMzao0BYBsFLP/ZNx+DZG2Xe0QunPbxYa HBOmlnLHqfO0Q== Subject: [PATCH 08/20] xfs: split new inode creation into two pieces From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Date: Fri, 30 Dec 2022 14:17:19 -0800 Message-ID: <167243863946.707335.1074883601333784409.stgit@magnolia> In-Reply-To: <167243863809.707335.15895322495460356300.stgit@magnolia> References: <167243863809.707335.15895322495460356300.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong There are two parts to initializing a newly allocated inode: setting up the incore structures, and initializing the new inode core based on the parent inode and the current user's environment. The initialization code is not specific to the kernel, so we would like to share that with userspace by hoisting it to libxfs. Therefore, split xfs_icreate into separate functions to prepare for the next few patches. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_ialloc.c | 20 ++++++++++++- fs/xfs/xfs_inode.c | 66 ++++++++++++++++++++------------------------ 2 files changed, 48 insertions(+), 38 deletions(-) diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c index ecf53198907f..d4c202da84cb 100644 --- a/fs/xfs/libxfs/xfs_ialloc.c +++ b/fs/xfs/libxfs/xfs_ialloc.c @@ -1870,9 +1870,25 @@ xfs_dialloc( } xfs_perag_put(pag); } + if (error) + goto out; - if (!error) - *new_ino = ino; + /* + * Protect against obviously corrupt allocation btree records. Later + * xfs_iget checks will catch re-allocation of other active in-memory + * and on-disk inodes. If we don't catch reallocating the parent inode + * here we will deadlock in xfs_iget() so we have to do these checks + * first. + */ + if (ino == parent || !xfs_verify_dir_ino(mp, ino)) { + xfs_alert(mp, "Allocated a known in-use inode 0x%llx!", ino); + xfs_ag_mark_sick(pag, XFS_SICK_AG_INOBT); + error = -EFSCORRUPTED; + goto out; + } + + *new_ino = ino; +out: xfs_perag_put(pag); return error; } diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 7a634a1ea111..1352599fee4c 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -674,51 +674,21 @@ xfs_inode_inherit_flags2( } } -/* - * Initialise a newly allocated inode and return the in-core inode to the - * caller locked exclusively. - */ -int -xfs_icreate( +/* Initialise an inode's attributes. */ +static void +xfs_inode_init( struct xfs_trans *tp, - xfs_ino_t ino, const struct xfs_icreate_args *args, - struct xfs_inode **ipp) + struct xfs_inode *ip) { struct xfs_inode *pip = args->pip; struct inode *dir = pip ? VFS_I(pip) : NULL; struct xfs_mount *mp = tp->t_mountp; - struct xfs_inode *ip; - struct inode *inode; + struct inode *inode = VFS_I(ip); unsigned int flags; int times = XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG | XFS_ICHGTIME_ACCESS; - int error; - /* - * Protect against obviously corrupt allocation btree records. Later - * xfs_iget checks will catch re-allocation of other active in-memory - * and on-disk inodes. If we don't catch reallocating the parent inode - * here we will deadlock in xfs_iget() so we have to do these checks - * first. - */ - if ((pip && ino == pip->i_ino) || !xfs_verify_dir_ino(mp, ino)) { - xfs_alert(mp, "Allocated a known in-use inode 0x%llx!", ino); - xfs_agno_mark_sick(mp, XFS_INO_TO_AGNO(mp, ino), - XFS_SICK_AG_INOBT); - return -EFSCORRUPTED; - } - - /* - * Get the in-core inode with the lock held exclusively to prevent - * others from looking at until we're done. - */ - error = xfs_iget(mp, tp, ino, XFS_IGET_CREATE, XFS_ILOCK_EXCL, &ip); - if (error) - return error; - - ASSERT(ip != NULL); - inode = VFS_I(ip); set_nlink(inode, args->nlink); inode->i_rdev = args->rdev; ip->i_projid = args->prid; @@ -815,8 +785,32 @@ xfs_icreate( /* now that we have an i_mode we can setup the inode structure */ xfs_setup_inode(ip); +} - *ipp = ip; +/* + * Initialise a newly allocated inode and return the in-core inode to the + * caller locked exclusively. + */ +int +xfs_icreate( + struct xfs_trans *tp, + xfs_ino_t ino, + const struct xfs_icreate_args *args, + struct xfs_inode **ipp) +{ + struct xfs_mount *mp = tp->t_mountp; + int error; + + /* + * Get the in-core inode with the lock held exclusively to prevent + * others from looking at until we're done. + */ + error = xfs_iget(mp, tp, ino, XFS_IGET_CREATE, XFS_ILOCK_EXCL, ipp); + if (error) + return error; + + ASSERT(*ipp != NULL); + xfs_inode_init(tp, args, *ipp); return 0; } From patchwork Fri Dec 30 22:17:19 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13085352 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 D568DC4332F for ; Sat, 31 Dec 2022 01:07:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235998AbiLaBHc (ORCPT ); Fri, 30 Dec 2022 20:07:32 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41008 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235902AbiLaBHb (ORCPT ); Fri, 30 Dec 2022 20:07:31 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AC5B2186E8 for ; Fri, 30 Dec 2022 17:07:29 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 3A9EC61D33 for ; Sat, 31 Dec 2022 01:07:29 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 988ABC433D2; Sat, 31 Dec 2022 01:07:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1672448848; bh=F5SU62ZhG7Ny3K8VBDdZOrPK3M/90vlDNDDAuslZbSQ=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=qWQlYZq9fA4ZlGQUysGRHpkTbiUm+vIE+UgRQ1B5I++rGffUCZTsPkQ0UM6MztU1i R8Wkrh9O76fhHMIU0sKp5Q5w1E64EN0AmjBptiGkQt49X/kmLAiaFn2XwI3/ayMxA0 r+hzAcnsntyTltj4o6U4XK/L5jo7sx8Qkca2LG+Jl1xpnp8tBK17e8nF2fjDTJInlS sS18SPdav3+5Rrv5LjCEzt9yLTfMxt8ajADBrRaL103UcYUxPQsM+JWb7LVtRPXber 8wXE5ddwuTlVNeQ2SkyjIiw9nzrTkqE8IFZO7H3vqDOUJ+kZFp6w5qlKd2J/dAovhV 1T8Zf+seUhskw== Subject: [PATCH 09/20] xfs: hoist new inode initialization functions to libxfs From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Date: Fri, 30 Dec 2022 14:17:19 -0800 Message-ID: <167243863959.707335.16099575596205543812.stgit@magnolia> In-Reply-To: <167243863809.707335.15895322495460356300.stgit@magnolia> References: <167243863809.707335.15895322495460356300.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Move all the code that initializes a new inode's attributes from the icreate_args structure and the parent directory into libxfs. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_inode_util.c | 201 ++++++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_inode_util.h | 21 ++++ fs/xfs/libxfs/xfs_shared.h | 8 -- fs/xfs/xfs_inode.c | 198 +-------------------------------------- fs/xfs/xfs_inode.h | 1 fs/xfs/xfs_trans.h | 1 6 files changed, 228 insertions(+), 202 deletions(-) diff --git a/fs/xfs/libxfs/xfs_inode_util.c b/fs/xfs/libxfs/xfs_inode_util.c index 2624d18922c0..5c9954dd20b3 100644 --- a/fs/xfs/libxfs/xfs_inode_util.c +++ b/fs/xfs/libxfs/xfs_inode_util.c @@ -3,6 +3,7 @@ * Copyright (c) 2000-2006 Silicon Graphics, Inc. * All Rights Reserved. */ +#include #include "xfs.h" #include "xfs_fs.h" #include "xfs_shared.h" @@ -13,6 +14,10 @@ #include "xfs_mount.h" #include "xfs_inode.h" #include "xfs_inode_util.h" +#include "xfs_trans.h" +#include "xfs_ialloc.h" +#include "xfs_health.h" +#include "xfs_bmap.h" uint16_t xfs_flags2diflags( @@ -133,3 +138,199 @@ xfs_get_initial_prid(struct xfs_inode *dp) return XFS_PROJID_DEFAULT; } + +/* Propagate di_flags from a parent inode to a child inode. */ +static inline void +xfs_inode_inherit_flags( + struct xfs_inode *ip, + const struct xfs_inode *pip) +{ + unsigned int di_flags = 0; + xfs_failaddr_t failaddr; + umode_t mode = VFS_I(ip)->i_mode; + + if (S_ISDIR(mode)) { + if (pip->i_diflags & XFS_DIFLAG_RTINHERIT) + di_flags |= XFS_DIFLAG_RTINHERIT; + if (pip->i_diflags & XFS_DIFLAG_EXTSZINHERIT) { + di_flags |= XFS_DIFLAG_EXTSZINHERIT; + ip->i_extsize = pip->i_extsize; + } + if (pip->i_diflags & XFS_DIFLAG_PROJINHERIT) + di_flags |= XFS_DIFLAG_PROJINHERIT; + } else if (S_ISREG(mode)) { + if ((pip->i_diflags & XFS_DIFLAG_RTINHERIT) && + xfs_has_realtime(ip->i_mount)) + di_flags |= XFS_DIFLAG_REALTIME; + if (pip->i_diflags & XFS_DIFLAG_EXTSZINHERIT) { + di_flags |= XFS_DIFLAG_EXTSIZE; + ip->i_extsize = pip->i_extsize; + } + } + if ((pip->i_diflags & XFS_DIFLAG_NOATIME) && + xfs_inherit_noatime) + di_flags |= XFS_DIFLAG_NOATIME; + if ((pip->i_diflags & XFS_DIFLAG_NODUMP) && + xfs_inherit_nodump) + di_flags |= XFS_DIFLAG_NODUMP; + if ((pip->i_diflags & XFS_DIFLAG_SYNC) && + xfs_inherit_sync) + di_flags |= XFS_DIFLAG_SYNC; + if ((pip->i_diflags & XFS_DIFLAG_NOSYMLINKS) && + xfs_inherit_nosymlinks) + di_flags |= XFS_DIFLAG_NOSYMLINKS; + if ((pip->i_diflags & XFS_DIFLAG_NODEFRAG) && + xfs_inherit_nodefrag) + di_flags |= XFS_DIFLAG_NODEFRAG; + if (pip->i_diflags & XFS_DIFLAG_FILESTREAM) + di_flags |= XFS_DIFLAG_FILESTREAM; + + ip->i_diflags |= di_flags; + + /* + * Inode verifiers on older kernels only check that the extent size + * hint is an integer multiple of the rt extent size on realtime files. + * They did not check the hint alignment on a directory with both + * rtinherit and extszinherit flags set. If the misaligned hint is + * propagated from a directory into a new realtime file, new file + * allocations will fail due to math errors in the rt allocator and/or + * trip the verifiers. Validate the hint settings in the new file so + * that we don't let broken hints propagate. + */ + failaddr = xfs_inode_validate_extsize(ip->i_mount, ip->i_extsize, + VFS_I(ip)->i_mode, ip->i_diflags); + if (failaddr) { + ip->i_diflags &= ~(XFS_DIFLAG_EXTSIZE | + XFS_DIFLAG_EXTSZINHERIT); + ip->i_extsize = 0; + } +} + +/* Propagate di_flags2 from a parent inode to a child inode. */ +static inline void +xfs_inode_inherit_flags2( + struct xfs_inode *ip, + const struct xfs_inode *pip) +{ + xfs_failaddr_t failaddr; + + if (pip->i_diflags2 & XFS_DIFLAG2_COWEXTSIZE) { + ip->i_diflags2 |= XFS_DIFLAG2_COWEXTSIZE; + ip->i_cowextsize = pip->i_cowextsize; + } + if (pip->i_diflags2 & XFS_DIFLAG2_DAX) + ip->i_diflags2 |= XFS_DIFLAG2_DAX; + + /* Don't let invalid cowextsize hints propagate. */ + failaddr = xfs_inode_validate_cowextsize(ip->i_mount, ip->i_cowextsize, + VFS_I(ip)->i_mode, ip->i_diflags, ip->i_diflags2); + if (failaddr) { + ip->i_diflags2 &= ~XFS_DIFLAG2_COWEXTSIZE; + ip->i_cowextsize = 0; + } +} + +/* Initialise an inode's attributes. */ +void +xfs_inode_init( + struct xfs_trans *tp, + const struct xfs_icreate_args *args, + struct xfs_inode *ip) +{ + struct xfs_inode *pip = args->pip; + struct inode *dir = pip ? VFS_I(pip) : NULL; + struct xfs_mount *mp = tp->t_mountp; + struct inode *inode = VFS_I(ip); + unsigned int flags; + int times = XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG | + XFS_ICHGTIME_ACCESS; + + set_nlink(inode, args->nlink); + inode->i_rdev = args->rdev; + ip->i_projid = args->prid; + + if (dir && !(dir->i_mode & S_ISGID) && xfs_has_grpid(mp)) { + inode_fsuid_set(inode, args->mnt_userns); + inode->i_gid = dir->i_gid; + inode->i_mode = args->mode; + } else { + inode_init_owner(args->mnt_userns, inode, dir, args->mode); + } + xfs_inode_sgid_inherit(args, ip); + + /* struct copies */ + if (args->flags & XFS_ICREATE_ARGS_FORCE_UID) + inode->i_uid = args->uid; + else + ASSERT(uid_eq(inode->i_uid, args->uid)); + if (args->flags & XFS_ICREATE_ARGS_FORCE_GID) + inode->i_gid = args->gid; + else if (!pip || !XFS_INHERIT_GID(pip)) + ASSERT(gid_eq(inode->i_gid, args->gid)); + if (args->flags & XFS_ICREATE_ARGS_FORCE_MODE) + inode->i_mode = args->mode; + + ip->i_disk_size = 0; + ip->i_df.if_nextents = 0; + ASSERT(ip->i_nblocks == 0); + + ip->i_extsize = 0; + ip->i_diflags = 0; + + if (xfs_has_v3inodes(mp)) { + inode_set_iversion(inode, 1); + ip->i_cowextsize = 0; + times |= XFS_ICHGTIME_CREATE; + } + + xfs_trans_ichgtime(tp, ip, times); + + flags = XFS_ILOG_CORE; + switch (args->mode & S_IFMT) { + case S_IFIFO: + case S_IFCHR: + case S_IFBLK: + case S_IFSOCK: + ip->i_df.if_format = XFS_DINODE_FMT_DEV; + flags |= XFS_ILOG_DEV; + break; + case S_IFREG: + case S_IFDIR: + if (pip && (pip->i_diflags & XFS_DIFLAG_ANY)) + xfs_inode_inherit_flags(ip, pip); + if (pip && (pip->i_diflags2 & XFS_DIFLAG2_ANY)) + xfs_inode_inherit_flags2(ip, pip); + fallthrough; + case S_IFLNK: + ip->i_df.if_format = XFS_DINODE_FMT_EXTENTS; + ip->i_df.if_bytes = 0; + ip->i_df.if_u1.if_root = NULL; + break; + default: + ASSERT(0); + } + + /* + * If we need to create attributes immediately after allocating the + * inode, initialise an empty attribute fork right now. We use the + * default fork offset for attributes here as we don't know exactly what + * size or how many attributes we might be adding. We can do this + * safely here because we know the data fork is completely empty and + * this saves us from needing to run a separate transaction to set the + * fork offset in the immediate future. + */ + if ((args->flags & XFS_ICREATE_ARGS_INIT_XATTRS) && + xfs_has_attr(mp)) { + ip->i_forkoff = xfs_default_attroffset(ip) >> 3; + xfs_ifork_init_attr(ip, XFS_DINODE_FMT_EXTENTS, 0); + } + + /* + * Log the new values stuffed into the inode. + */ + xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); + xfs_trans_log_inode(tp, ip, flags); + + /* now that we have an i_mode we can setup the inode structure */ + xfs_setup_inode(ip); +} diff --git a/fs/xfs/libxfs/xfs_inode_util.h b/fs/xfs/libxfs/xfs_inode_util.h index 466f0767ab5d..a73ccaea5582 100644 --- a/fs/xfs/libxfs/xfs_inode_util.h +++ b/fs/xfs/libxfs/xfs_inode_util.h @@ -44,4 +44,25 @@ struct xfs_icreate_args { uint16_t flags; }; +/* + * Flags for xfs_trans_ichgtime(). + */ +#define XFS_ICHGTIME_MOD 0x1 /* data fork modification timestamp */ +#define XFS_ICHGTIME_CHG 0x2 /* inode field change timestamp */ +#define XFS_ICHGTIME_CREATE 0x4 /* inode create timestamp */ +#define XFS_ICHGTIME_ACCESS 0x8 /* last access timestamp */ +void xfs_trans_ichgtime(struct xfs_trans *tp, struct xfs_inode *ip, int flags); + +void xfs_inode_init(struct xfs_trans *tp, const struct xfs_icreate_args *args, + struct xfs_inode *ip); + +/* The libxfs client must provide this group of helper functions. */ + +/* Handle legacy Irix sgid inheritance quirks. */ +void xfs_inode_sgid_inherit(const struct xfs_icreate_args *args, + struct xfs_inode *ip); + +/* Initialize the incore inode. */ +void xfs_setup_inode(struct xfs_inode *ip); + #endif /* __XFS_INODE_UTIL_H__ */ diff --git a/fs/xfs/libxfs/xfs_shared.h b/fs/xfs/libxfs/xfs_shared.h index acf527eb0e1c..46754fe57361 100644 --- a/fs/xfs/libxfs/xfs_shared.h +++ b/fs/xfs/libxfs/xfs_shared.h @@ -131,14 +131,6 @@ void xfs_log_get_max_trans_res(struct xfs_mount *mp, #define XFS_RCBAG_BTREE_REF 1 #define XFS_SSB_REF 0 -/* - * Flags for xfs_trans_ichgtime(). - */ -#define XFS_ICHGTIME_MOD 0x1 /* data fork modification timestamp */ -#define XFS_ICHGTIME_CHG 0x2 /* inode field change timestamp */ -#define XFS_ICHGTIME_CREATE 0x4 /* inode create timestamp */ -#define XFS_ICHGTIME_ACCESS 0x8 /* last access timestamp */ - /* Computed inode geometry for the filesystem. */ struct xfs_ino_geometry { /* Maximum inode count in this filesystem. */ diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 1352599fee4c..270e81e12015 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -39,6 +39,7 @@ #include "xfs_ag.h" #include "xfs_log_priv.h" #include "xfs_health.h" +#include "xfs_inode_util.h" struct kmem_cache *xfs_inode_cache; @@ -583,123 +584,12 @@ xfs_lookup( return error; } -/* Propagate di_flags from a parent inode to a child inode. */ -static void -xfs_inode_inherit_flags( - struct xfs_inode *ip, - const struct xfs_inode *pip) +void +xfs_inode_sgid_inherit( + const struct xfs_icreate_args *args, + struct xfs_inode *ip) { - unsigned int di_flags = 0; - xfs_failaddr_t failaddr; - umode_t mode = VFS_I(ip)->i_mode; - - if (S_ISDIR(mode)) { - if (pip->i_diflags & XFS_DIFLAG_RTINHERIT) - di_flags |= XFS_DIFLAG_RTINHERIT; - if (pip->i_diflags & XFS_DIFLAG_EXTSZINHERIT) { - di_flags |= XFS_DIFLAG_EXTSZINHERIT; - ip->i_extsize = pip->i_extsize; - } - if (pip->i_diflags & XFS_DIFLAG_PROJINHERIT) - di_flags |= XFS_DIFLAG_PROJINHERIT; - } else if (S_ISREG(mode)) { - if ((pip->i_diflags & XFS_DIFLAG_RTINHERIT) && - xfs_has_realtime(ip->i_mount)) - di_flags |= XFS_DIFLAG_REALTIME; - if (pip->i_diflags & XFS_DIFLAG_EXTSZINHERIT) { - di_flags |= XFS_DIFLAG_EXTSIZE; - ip->i_extsize = pip->i_extsize; - } - } - if ((pip->i_diflags & XFS_DIFLAG_NOATIME) && - xfs_inherit_noatime) - di_flags |= XFS_DIFLAG_NOATIME; - if ((pip->i_diflags & XFS_DIFLAG_NODUMP) && - xfs_inherit_nodump) - di_flags |= XFS_DIFLAG_NODUMP; - if ((pip->i_diflags & XFS_DIFLAG_SYNC) && - xfs_inherit_sync) - di_flags |= XFS_DIFLAG_SYNC; - if ((pip->i_diflags & XFS_DIFLAG_NOSYMLINKS) && - xfs_inherit_nosymlinks) - di_flags |= XFS_DIFLAG_NOSYMLINKS; - if ((pip->i_diflags & XFS_DIFLAG_NODEFRAG) && - xfs_inherit_nodefrag) - di_flags |= XFS_DIFLAG_NODEFRAG; - if (pip->i_diflags & XFS_DIFLAG_FILESTREAM) - di_flags |= XFS_DIFLAG_FILESTREAM; - - ip->i_diflags |= di_flags; - - /* - * Inode verifiers on older kernels only check that the extent size - * hint is an integer multiple of the rt extent size on realtime files. - * They did not check the hint alignment on a directory with both - * rtinherit and extszinherit flags set. If the misaligned hint is - * propagated from a directory into a new realtime file, new file - * allocations will fail due to math errors in the rt allocator and/or - * trip the verifiers. Validate the hint settings in the new file so - * that we don't let broken hints propagate. - */ - failaddr = xfs_inode_validate_extsize(ip->i_mount, ip->i_extsize, - VFS_I(ip)->i_mode, ip->i_diflags); - if (failaddr) { - ip->i_diflags &= ~(XFS_DIFLAG_EXTSIZE | - XFS_DIFLAG_EXTSZINHERIT); - ip->i_extsize = 0; - } -} - -/* Propagate di_flags2 from a parent inode to a child inode. */ -static void -xfs_inode_inherit_flags2( - struct xfs_inode *ip, - const struct xfs_inode *pip) -{ - xfs_failaddr_t failaddr; - - if (pip->i_diflags2 & XFS_DIFLAG2_COWEXTSIZE) { - ip->i_diflags2 |= XFS_DIFLAG2_COWEXTSIZE; - ip->i_cowextsize = pip->i_cowextsize; - } - if (pip->i_diflags2 & XFS_DIFLAG2_DAX) - ip->i_diflags2 |= XFS_DIFLAG2_DAX; - - /* Don't let invalid cowextsize hints propagate. */ - failaddr = xfs_inode_validate_cowextsize(ip->i_mount, ip->i_cowextsize, - VFS_I(ip)->i_mode, ip->i_diflags, ip->i_diflags2); - if (failaddr) { - ip->i_diflags2 &= ~XFS_DIFLAG2_COWEXTSIZE; - ip->i_cowextsize = 0; - } -} - -/* Initialise an inode's attributes. */ -static void -xfs_inode_init( - struct xfs_trans *tp, - const struct xfs_icreate_args *args, - struct xfs_inode *ip) -{ - struct xfs_inode *pip = args->pip; - struct inode *dir = pip ? VFS_I(pip) : NULL; - struct xfs_mount *mp = tp->t_mountp; - struct inode *inode = VFS_I(ip); - unsigned int flags; - int times = XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG | - XFS_ICHGTIME_ACCESS; - - set_nlink(inode, args->nlink); - inode->i_rdev = args->rdev; - ip->i_projid = args->prid; - - if (dir && !(dir->i_mode & S_ISGID) && xfs_has_grpid(mp)) { - inode_fsuid_set(inode, args->mnt_userns); - inode->i_gid = dir->i_gid; - inode->i_mode = args->mode; - } else { - inode_init_owner(args->mnt_userns, inode, dir, args->mode); - } + struct inode *inode = VFS_I(ip); /* * If the group ID of the new file does not match the effective group @@ -709,82 +599,6 @@ xfs_inode_init( if (irix_sgid_inherit && (inode->i_mode & S_ISGID) && !vfsgid_in_group_p(i_gid_into_vfsgid(args->mnt_userns, inode))) inode->i_mode &= ~S_ISGID; - - /* struct copies */ - if (args->flags & XFS_ICREATE_ARGS_FORCE_UID) - inode->i_uid = args->uid; - else - ASSERT(uid_eq(inode->i_uid, args->uid)); - if (args->flags & XFS_ICREATE_ARGS_FORCE_GID) - inode->i_gid = args->gid; - else if (!pip || !XFS_INHERIT_GID(pip)) - ASSERT(gid_eq(inode->i_gid, args->gid)); - if (args->flags & XFS_ICREATE_ARGS_FORCE_MODE) - inode->i_mode = args->mode; - - ip->i_disk_size = 0; - ip->i_df.if_nextents = 0; - ASSERT(ip->i_nblocks == 0); - - ip->i_extsize = 0; - ip->i_diflags = 0; - - if (xfs_has_v3inodes(mp)) { - inode_set_iversion(inode, 1); - ip->i_cowextsize = 0; - times |= XFS_ICHGTIME_CREATE; - } - - xfs_trans_ichgtime(tp, ip, times); - - flags = XFS_ILOG_CORE; - switch (args->mode & S_IFMT) { - case S_IFIFO: - case S_IFCHR: - case S_IFBLK: - case S_IFSOCK: - ip->i_df.if_format = XFS_DINODE_FMT_DEV; - flags |= XFS_ILOG_DEV; - break; - case S_IFREG: - case S_IFDIR: - if (pip && (pip->i_diflags & XFS_DIFLAG_ANY)) - xfs_inode_inherit_flags(ip, pip); - if (pip && (pip->i_diflags2 & XFS_DIFLAG2_ANY)) - xfs_inode_inherit_flags2(ip, pip); - fallthrough; - case S_IFLNK: - ip->i_df.if_format = XFS_DINODE_FMT_EXTENTS; - ip->i_df.if_bytes = 0; - ip->i_df.if_u1.if_root = NULL; - break; - default: - ASSERT(0); - } - - /* - * If we need to create attributes immediately after allocating the - * inode, initialise an empty attribute fork right now. We use the - * default fork offset for attributes here as we don't know exactly what - * size or how many attributes we might be adding. We can do this - * safely here because we know the data fork is completely empty and - * this saves us from needing to run a separate transaction to set the - * fork offset in the immediate future. - */ - if ((args->flags & XFS_ICREATE_ARGS_INIT_XATTRS) && - xfs_has_attr(mp)) { - ip->i_forkoff = xfs_default_attroffset(ip) >> 3; - xfs_ifork_init_attr(ip, XFS_DINODE_FMT_EXTENTS, 0); - } - - /* - * Log the new values stuffed into the inode. - */ - xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); - xfs_trans_log_inode(tp, ip, flags); - - /* now that we have an i_mode we can setup the inode structure */ - xfs_setup_inode(ip); } /* diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index cb627543e9fb..cb4e5114bac4 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -542,7 +542,6 @@ int xfs_break_layouts(struct inode *inode, uint *iolock, enum layout_break_reason reason); /* from xfs_iops.c */ -extern void xfs_setup_inode(struct xfs_inode *ip); extern void xfs_setup_iops(struct xfs_inode *ip); extern void xfs_diflags_to_iflags(struct xfs_inode *ip, bool init); diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index a43d6465b9d4..0a9ec6929bbc 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h @@ -228,7 +228,6 @@ void xfs_trans_stale_inode_buf(xfs_trans_t *, struct xfs_buf *); bool xfs_trans_ordered_buf(xfs_trans_t *, struct xfs_buf *); void xfs_trans_dquot_buf(xfs_trans_t *, struct xfs_buf *, uint); void xfs_trans_inode_alloc_buf(xfs_trans_t *, struct xfs_buf *); -void xfs_trans_ichgtime(struct xfs_trans *, struct xfs_inode *, int); void xfs_trans_ijoin(struct xfs_trans *, struct xfs_inode *, uint); void xfs_trans_log_buf(struct xfs_trans *, struct xfs_buf *, uint, uint); From patchwork Fri Dec 30 22:17:19 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13085353 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 D4906C4332F for ; Sat, 31 Dec 2022 01:07:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236001AbiLaBHt (ORCPT ); Fri, 30 Dec 2022 20:07:49 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41148 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235902AbiLaBHs (ORCPT ); Fri, 30 Dec 2022 20:07:48 -0500 Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B29911DF18 for ; Fri, 30 Dec 2022 17:07:46 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 707B0B81DF9 for ; Sat, 31 Dec 2022 01:07:45 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3357FC433EF; Sat, 31 Dec 2022 01:07:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1672448864; bh=u3762SEX3HjXqekFYzffjbmIVKDfvo1RdEy7TYxunjM=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=i4cKyEFf2+37q3vZalOaSCTGL4+6SkDTBOLjIxJcB2zNIaJZs1inKoE6aUrQMcYoJ b3xv4BzKCeLeRe4shb8YbvJ3yeXq3RPr82oL2vJMW0/xGvhvrTmWVcb5GlJGKfb5MB o9gW3x7gUjNoiR4URaFE0yXNhzi5WB9QQmlwBP1FtbJcAdkGLhZaxzpwpvb6OVMAgG ksljgL4hQ7jC6sTHBX1hYujCd45q+7MVwjeO1Pd0hjsB7hFIOAq2x/oEtEM0a0MDKB d7j6qWd1MYVrlgVZLM5PUJgmTgqN8F84ZqWpFx0t4j0MMPibWNIhipUuQmQmtHtyvK 0IGGjrnkewJ/Q== Subject: [PATCH 10/20] xfs: push xfs_icreate_args creation out of xfs_create* From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Date: Fri, 30 Dec 2022 14:17:19 -0800 Message-ID: <167243863973.707335.4090548610585011757.stgit@magnolia> In-Reply-To: <167243863809.707335.15895322495460356300.stgit@magnolia> References: <167243863809.707335.15895322495460356300.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Move the initialization of the xfs_icreate_args structure out of xfs_create and xfs_create_tempfile into their callers so that we can set the new inode's attributes in one place and pass that through instead of open coding the collection of attributes all over the code. Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_inode.c | 59 +++++++++++++++++++++++----------------------------- fs/xfs/xfs_inode.h | 9 ++++---- fs/xfs/xfs_iops.c | 50 +++++++++++++++++++++++++++----------------- 3 files changed, 61 insertions(+), 57 deletions(-) diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 270e81e12015..5350c55ac25f 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -808,44 +808,34 @@ xfs_nlink_hook_del( int xfs_create( - struct user_namespace *mnt_userns, - xfs_inode_t *dp, + struct xfs_inode *dp, struct xfs_name *name, - umode_t mode, - dev_t rdev, - bool init_xattrs, - xfs_inode_t **ipp) + const struct xfs_icreate_args *args, + struct xfs_inode **ipp) { - struct xfs_icreate_args args = { - .rdev = rdev, - .nlink = S_ISDIR(mode) ? 2 : 1, - }; - int is_dir = S_ISDIR(mode); struct xfs_mount *mp = dp->i_mount; struct xfs_inode *ip = NULL; struct xfs_trans *tp = NULL; - int error; - bool unlock_dp_on_error = false; struct xfs_dquot *udqp = NULL; struct xfs_dquot *gdqp = NULL; struct xfs_dquot *pdqp = NULL; struct xfs_trans_res *tres; - uint resblks; xfs_ino_t ino; + bool unlock_dp_on_error = false; + bool is_dir = S_ISDIR(args->mode); + uint resblks; + int error; + ASSERT(args->pip == dp); trace_xfs_create(dp, name); if (xfs_is_shutdown(mp)) return -EIO; - xfs_icreate_args_inherit(&args, dp, mnt_userns, mode); - if (init_xattrs) - args.flags |= XFS_ICREATE_ARGS_INIT_XATTRS; - /* * Make sure that we have allocated dquot(s) on disk. */ - error = xfs_qm_vop_dqalloc(dp, args.uid, args.gid, args.prid, + error = xfs_qm_vop_dqalloc(dp, args->uid, args->gid, args->prid, XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp, &pdqp); if (error) @@ -884,9 +874,9 @@ xfs_create( * entry pointing to them, but a directory also the "." entry * pointing to itself. */ - error = xfs_dialloc(&tp, dp->i_ino, mode, &ino); + error = xfs_dialloc(&tp, dp->i_ino, args->mode, &ino); if (!error) - error = xfs_icreate(tp, ino, &args, &ip); + error = xfs_icreate(tp, ino, args, &ip); if (error) goto out_trans_cancel; @@ -977,32 +967,31 @@ xfs_create( int xfs_create_tmpfile( - struct user_namespace *mnt_userns, struct xfs_inode *dp, - umode_t mode, + const struct xfs_icreate_args *args, struct xfs_inode **ipp) { - struct xfs_icreate_args args = { NULL }; struct xfs_mount *mp = dp->i_mount; struct xfs_inode *ip = NULL; struct xfs_trans *tp = NULL; - int error; struct xfs_dquot *udqp = NULL; struct xfs_dquot *gdqp = NULL; struct xfs_dquot *pdqp = NULL; struct xfs_trans_res *tres; - uint resblks; xfs_ino_t ino; + uint resblks; + int error; + + ASSERT(args->nlink == 0); + ASSERT(args->pip == dp); if (xfs_is_shutdown(mp)) return -EIO; - xfs_icreate_args_inherit(&args, dp, mnt_userns, mode); - /* * Make sure that we have allocated dquot(s) on disk. */ - error = xfs_qm_vop_dqalloc(dp, args.uid, args.gid, args.prid, + error = xfs_qm_vop_dqalloc(dp, args->uid, args->gid, args->prid, XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp, &pdqp); if (error) @@ -1016,9 +1005,9 @@ xfs_create_tmpfile( if (error) goto out_release_dquots; - error = xfs_dialloc(&tp, dp->i_ino, mode, &ino); + error = xfs_dialloc(&tp, dp->i_ino, args->mode, &ino); if (!error) - error = xfs_icreate(tp, ino, &args, &ip); + error = xfs_icreate(tp, ino, args, &ip); if (error) goto out_trans_cancel; @@ -2750,12 +2739,16 @@ xfs_rename_alloc_whiteout( struct xfs_inode *dp, struct xfs_inode **wip) { + struct xfs_icreate_args args = { + .nlink = 0, + }; struct xfs_inode *tmpfile; struct qstr name; int error; - error = xfs_create_tmpfile(mnt_userns, dp, S_IFCHR | WHITEOUT_MODE, - &tmpfile); + xfs_icreate_args_inherit(&args, dp, mnt_userns, S_IFCHR | WHITEOUT_MODE); + + error = xfs_create_tmpfile(dp, &args, &tmpfile); if (error) return error; diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index cb4e5114bac4..9617079f0a73 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -485,12 +485,11 @@ int xfs_release(struct xfs_inode *ip); void xfs_inactive(struct xfs_inode *ip); int xfs_lookup(struct xfs_inode *dp, const struct xfs_name *name, struct xfs_inode **ipp, struct xfs_name *ci_name); -int xfs_create(struct user_namespace *mnt_userns, - struct xfs_inode *dp, struct xfs_name *name, - umode_t mode, dev_t rdev, bool need_xattr, +int xfs_create(struct xfs_inode *dp, struct xfs_name *name, + const struct xfs_icreate_args *iargs, struct xfs_inode **ipp); -int xfs_create_tmpfile(struct user_namespace *mnt_userns, - struct xfs_inode *dp, umode_t mode, +int xfs_create_tmpfile(struct xfs_inode *dp, + const struct xfs_icreate_args *iargs, struct xfs_inode **ipp); int xfs_remove(struct xfs_inode *dp, struct xfs_name *name, struct xfs_inode *ip); diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index 80f881c69336..d580bf591d73 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -165,44 +165,56 @@ xfs_create_need_xattr( STATIC int xfs_generic_create( struct user_namespace *mnt_userns, - struct inode *dir, - struct dentry *dentry, - umode_t mode, - dev_t rdev, - struct file *tmpfile) /* unnamed file */ + struct inode *dir, + struct dentry *dentry, + umode_t mode, + dev_t rdev, + struct file *tmpfile) /* unnamed file */ { - struct inode *inode; - struct xfs_inode *ip = NULL; - struct posix_acl *default_acl, *acl; - struct xfs_name name; - int error; + struct xfs_icreate_args args = { + .rdev = rdev, + }; + struct inode *inode; + struct xfs_inode *ip = NULL; + struct posix_acl *default_acl, *acl; + struct xfs_name name; + int error; + + xfs_icreate_args_inherit(&args, XFS_I(dir), mnt_userns, mode); + if (tmpfile) + args.nlink = 0; + else if (S_ISDIR(mode)) + args.nlink = 2; + else + args.nlink = 1; /* * Irix uses Missed'em'V split, but doesn't want to see * the upper 5 bits of (14bit) major. */ - if (S_ISCHR(mode) || S_ISBLK(mode)) { - if (unlikely(!sysv_valid_dev(rdev) || MAJOR(rdev) & ~0x1ff)) + if (S_ISCHR(args.mode) || S_ISBLK(args.mode)) { + if (unlikely(!sysv_valid_dev(args.rdev) || + MAJOR(args.rdev) & ~0x1ff)) return -EINVAL; } else { - rdev = 0; + args.rdev = 0; } - error = posix_acl_create(dir, &mode, &default_acl, &acl); + error = posix_acl_create(dir, &args.mode, &default_acl, &acl); if (error) return error; /* Verify mode is valid also for tmpfile case */ - error = xfs_dentry_mode_to_name(&name, dentry, mode); + error = xfs_dentry_mode_to_name(&name, dentry, args.mode); if (unlikely(error)) goto out_free_acl; if (!tmpfile) { - error = xfs_create(mnt_userns, XFS_I(dir), &name, mode, rdev, - xfs_create_need_xattr(dir, default_acl, acl), - &ip); + if (xfs_create_need_xattr(dir, default_acl, acl)) + args.flags |= XFS_ICREATE_ARGS_INIT_XATTRS; + error = xfs_create(XFS_I(dir), &name, &args, &ip); } else { - error = xfs_create_tmpfile(mnt_userns, XFS_I(dir), mode, &ip); + error = xfs_create_tmpfile(XFS_I(dir), &args, &ip); } if (unlikely(error)) goto out_free_acl; From patchwork Fri Dec 30 22:17:19 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13085354 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 41AD4C4332F for ; Sat, 31 Dec 2022 01:08:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236002AbiLaBIE (ORCPT ); Fri, 30 Dec 2022 20:08:04 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41248 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235902AbiLaBID (ORCPT ); Fri, 30 Dec 2022 20:08:03 -0500 Received: from ams.source.kernel.org (ams.source.kernel.org [145.40.68.75]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 506BA1573A for ; Fri, 30 Dec 2022 17:08:02 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 0C996B81D68 for ; Sat, 31 Dec 2022 01:08:01 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id BDA9AC433EF; Sat, 31 Dec 2022 01:07:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1672448879; bh=lwioL8W9ZJ7M7InmKZSRhkaWAgihqA1xRwT1HjQkQvg=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=CWSEncBODh1ISVRYhEDsuO1QD27B9mDG4Q1kk63GjGTAnz/nBHYC9NAP+ip0uhnkR EDJ0HrORIVoik9IHIVUg0UiC43PnAkgZ1WhgolY0rn2LdZ407DeFHxxuTSSZ2pNIS8 c3xGQ4wb7RekVjbJUobttGitXaYutpone0zg8BPpqzL3biW0aj0pyoyqMDq+nY48uo XdeFiswb4szm+swAAE7qW5vQceeGjXwK3ejaH9P+NuLKahwNjv+KyGB4wxIocJjfkB CtLszRdM0yFUuLsTw5ZuBuOlhGzXWjIz6HCrrNgYoq/fYYpFsC6QVIQ5A0m1c7UVSJ +oAU8OMFS3vbA== Subject: [PATCH 11/20] xfs: wrap inode creation dqalloc calls From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Date: Fri, 30 Dec 2022 14:17:19 -0800 Message-ID: <167243863987.707335.4838141657069838555.stgit@magnolia> In-Reply-To: <167243863809.707335.15895322495460356300.stgit@magnolia> References: <167243863809.707335.15895322495460356300.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Create a helper that calls dqalloc to allocate and grab a reference to dquots for the user, group, and project ids listed in an icreate structure. This simplifies the creat-related dqalloc callsites scattered around the code base. Signed-off-by: Darrick J. Wong --- fs/xfs/scrub/tempfile.c | 9 ++++----- fs/xfs/xfs_inode.c | 38 ++++++++++++++++++++++++++------------ fs/xfs/xfs_inode.h | 3 +++ fs/xfs/xfs_symlink.c | 10 ++++------ 4 files changed, 37 insertions(+), 23 deletions(-) diff --git a/fs/xfs/scrub/tempfile.c b/fs/xfs/scrub/tempfile.c index 2c630a5e23ea..6efaab50440f 100644 --- a/fs/xfs/scrub/tempfile.c +++ b/fs/xfs/scrub/tempfile.c @@ -43,9 +43,9 @@ xrep_tempfile_create( struct xfs_icreate_args args = { .pip = sc->mp->m_rootip, }; struct xfs_mount *mp = sc->mp; struct xfs_trans *tp = NULL; - struct xfs_dquot *udqp = NULL; - struct xfs_dquot *gdqp = NULL; - struct xfs_dquot *pdqp = NULL; + struct xfs_dquot *udqp; + struct xfs_dquot *gdqp; + struct xfs_dquot *pdqp; struct xfs_trans_res *tres; struct xfs_inode *dp = mp->m_rootip; xfs_ino_t ino; @@ -69,8 +69,7 @@ xrep_tempfile_create( * inode should be completely root owned so that we don't fail due to * quota limits. */ - error = xfs_qm_vop_dqalloc(dp, args.uid, args.gid, args.prid, - XFS_QMOPT_QUOTALL, &udqp, &gdqp, &pdqp); + error = xfs_icreate_dqalloc(&args, &udqp, &gdqp, &pdqp); if (error) return error; diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 5350c55ac25f..db1f521ac6d0 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -806,6 +806,24 @@ xfs_nlink_hook_del( # define xfs_nlink_backref_delta(dp, ip, delta) ((void)0) #endif /* CONFIG_XFS_LIVE_HOOKS */ +int +xfs_icreate_dqalloc( + const struct xfs_icreate_args *args, + struct xfs_dquot **udqpp, + struct xfs_dquot **gdqpp, + struct xfs_dquot **pdqpp) +{ + unsigned int flags = XFS_QMOPT_QUOTALL; + + *udqpp = *gdqpp = *pdqpp = NULL; + + if (!(args->flags & XFS_ICREATE_ARGS_FORCE_GID)) + flags |= XFS_QMOPT_INHERIT; + + return xfs_qm_vop_dqalloc(args->pip, args->uid, args->gid, args->prid, + flags, udqpp, gdqpp, pdqpp); +} + int xfs_create( struct xfs_inode *dp, @@ -816,9 +834,9 @@ xfs_create( struct xfs_mount *mp = dp->i_mount; struct xfs_inode *ip = NULL; struct xfs_trans *tp = NULL; - struct xfs_dquot *udqp = NULL; - struct xfs_dquot *gdqp = NULL; - struct xfs_dquot *pdqp = NULL; + struct xfs_dquot *udqp; + struct xfs_dquot *gdqp; + struct xfs_dquot *pdqp; struct xfs_trans_res *tres; xfs_ino_t ino; bool unlock_dp_on_error = false; @@ -835,9 +853,7 @@ xfs_create( /* * Make sure that we have allocated dquot(s) on disk. */ - error = xfs_qm_vop_dqalloc(dp, args->uid, args->gid, args->prid, - XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, - &udqp, &gdqp, &pdqp); + error = xfs_icreate_dqalloc(args, &udqp, &gdqp, &pdqp); if (error) return error; @@ -974,9 +990,9 @@ xfs_create_tmpfile( struct xfs_mount *mp = dp->i_mount; struct xfs_inode *ip = NULL; struct xfs_trans *tp = NULL; - struct xfs_dquot *udqp = NULL; - struct xfs_dquot *gdqp = NULL; - struct xfs_dquot *pdqp = NULL; + struct xfs_dquot *udqp; + struct xfs_dquot *gdqp; + struct xfs_dquot *pdqp; struct xfs_trans_res *tres; xfs_ino_t ino; uint resblks; @@ -991,9 +1007,7 @@ xfs_create_tmpfile( /* * Make sure that we have allocated dquot(s) on disk. */ - error = xfs_qm_vop_dqalloc(dp, args->uid, args->gid, args->prid, - XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, - &udqp, &gdqp, &pdqp); + error = xfs_icreate_dqalloc(args, &udqp, &gdqp, &pdqp); if (error) return error; diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 9617079f0a73..b99c62f14919 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -625,5 +625,8 @@ void xfs_nlink_hook_del(struct xfs_mount *mp, struct xfs_nlink_hook *hook); void xfs_icreate_args_inherit(struct xfs_icreate_args *args, struct xfs_inode *dp, struct user_namespace *mnt_userns, umode_t mode); void xfs_icreate_args_rootfile(struct xfs_icreate_args *args, umode_t mode); +int xfs_icreate_dqalloc(const struct xfs_icreate_args *args, + struct xfs_dquot **udqpp, struct xfs_dquot **gdqpp, + struct xfs_dquot **pdqpp); #endif /* __XFS_INODE_H__ */ diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c index c27bf49de7bf..6dc15f125895 100644 --- a/fs/xfs/xfs_symlink.c +++ b/fs/xfs/xfs_symlink.c @@ -98,9 +98,9 @@ xfs_symlink( int pathlen; bool unlock_dp_on_error = false; xfs_filblks_t fs_blocks; - struct xfs_dquot *udqp = NULL; - struct xfs_dquot *gdqp = NULL; - struct xfs_dquot *pdqp = NULL; + struct xfs_dquot *udqp; + struct xfs_dquot *gdqp; + struct xfs_dquot *pdqp; uint resblks; xfs_ino_t ino; @@ -125,9 +125,7 @@ xfs_symlink( /* * Make sure that we have allocated dquot(s) on disk. */ - error = xfs_qm_vop_dqalloc(dp, args.uid, args.gid, args.prid, - XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, - &udqp, &gdqp, &pdqp); + error = xfs_icreate_dqalloc(&args, &udqp, &gdqp, &pdqp); if (error) return error; From patchwork Fri Dec 30 22:17:20 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13085355 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 1690BC4332F for ; Sat, 31 Dec 2022 01:08:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235902AbiLaBIV (ORCPT ); Fri, 30 Dec 2022 20:08:21 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41292 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235933AbiLaBIU (ORCPT ); Fri, 30 Dec 2022 20:08:20 -0500 Received: from ams.source.kernel.org (ams.source.kernel.org [145.40.68.75]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0CE621573A for ; Fri, 30 Dec 2022 17:08:18 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 9235BB81DCA for ; Sat, 31 Dec 2022 01:08:16 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4D1EDC433D2; Sat, 31 Dec 2022 01:08:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1672448895; bh=1EeOU69l/0KeeDxkYP9TsNZrPzyh6HN+E/gVubojDOg=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=TYLOvo8xtFoBGWQdx/LSY5Mhf+D2qDnv/z6RjhXxM89SX6MbN7k3YGIYxZ6ut8nai 3T+piL7/y/dG7fzcuaNkTmRKk1XLP5TaKVCf8NK/MFnQQWUEIJTY5YEfd+3S3kYdn7 tZ/1Zsu8NYn4vNbPO4+viMHWuOv/GYr3smxYppksYnDtY0CuJkEAZ142DJ810j84+H WSex3I6z9Xp5CgdarcaPBvbAzaMGaYrueYgWIaqanYsa4lwbB0Yp8fD+ylFJeVv3ur rEd1zGMj94BZGhlTAaxL86Oy73Hc4Mu+ioS5cFGbKLOfs8mC415Kxdndcu22J2XaMf ZvmlsyTlmlAMw== Subject: [PATCH 12/20] xfs: hoist xfs_iunlink to libxfs From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Date: Fri, 30 Dec 2022 14:17:20 -0800 Message-ID: <167243864001.707335.15849086365597867277.stgit@magnolia> In-Reply-To: <167243863809.707335.15895322495460356300.stgit@magnolia> References: <167243863809.707335.15895322495460356300.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Move xfs_iunlink and xfs_iunlink_remove to libxfs. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_inode_util.c | 276 ++++++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_inode_util.h | 4 + fs/xfs/xfs_inode.c | 275 ---------------------------------------- fs/xfs/xfs_inode.h | 1 4 files changed, 280 insertions(+), 276 deletions(-) diff --git a/fs/xfs/libxfs/xfs_inode_util.c b/fs/xfs/libxfs/xfs_inode_util.c index 5c9954dd20b3..0c3ac4b07cc5 100644 --- a/fs/xfs/libxfs/xfs_inode_util.c +++ b/fs/xfs/libxfs/xfs_inode_util.c @@ -18,6 +18,10 @@ #include "xfs_ialloc.h" #include "xfs_health.h" #include "xfs_bmap.h" +#include "xfs_error.h" +#include "xfs_trace.h" +#include "xfs_ag.h" +#include "xfs_iunlink_item.h" uint16_t xfs_flags2diflags( @@ -334,3 +338,275 @@ xfs_inode_init( /* now that we have an i_mode we can setup the inode structure */ xfs_setup_inode(ip); } + +/* + * In-Core Unlinked List Lookups + * ============================= + * + * Every inode is supposed to be reachable from some other piece of metadata + * with the exception of the root directory. Inodes with a connection to a + * file descriptor but not linked from anywhere in the on-disk directory tree + * are collectively known as unlinked inodes, though the filesystem itself + * maintains links to these inodes so that on-disk metadata are consistent. + * + * XFS implements a per-AG on-disk hash table of unlinked inodes. The AGI + * header contains a number of buckets that point to an inode, and each inode + * record has a pointer to the next inode in the hash chain. This + * singly-linked list causes scaling problems in the iunlink remove function + * because we must walk that list to find the inode that points to the inode + * being removed from the unlinked hash bucket list. + * + * Hence we keep an in-memory double linked list to link each inode on an + * unlinked list. Because there are 64 unlinked lists per AGI, keeping pointer + * based lists would require having 64 list heads in the perag, one for each + * list. This is expensive in terms of memory (think millions of AGs) and cache + * misses on lookups. Instead, use the fact that inodes on the unlinked list + * must be referenced at the VFS level to keep them on the list and hence we + * have an existence guarantee for inodes on the unlinked list. + * + * Given we have an existence guarantee, we can use lockless inode cache lookups + * to resolve aginos to xfs inodes. This means we only need 8 bytes per inode + * for the double linked unlinked list, and we don't need any extra locking to + * keep the list safe as all manipulations are done under the AGI buffer lock. + * Keeping the list up to date does not require memory allocation, just finding + * the XFS inode and updating the next/prev unlinked list aginos. + */ + +/* Update the prev pointer of the next agino. */ +static int +xfs_iunlink_update_backref( + struct xfs_perag *pag, + xfs_agino_t prev_agino, + xfs_agino_t next_agino) +{ + struct xfs_inode *ip; + + /* No update necessary if we are at the end of the list. */ + if (next_agino == NULLAGINO) + return 0; + + ip = xfs_iunlink_lookup(pag, next_agino); + if (!ip) { + xfs_ag_mark_sick(pag, XFS_SICK_AG_AGI); + return -EFSCORRUPTED; + } + + ip->i_prev_unlinked = prev_agino; + return 0; +} + +/* + * Point the AGI unlinked bucket at an inode and log the results. The caller + * is responsible for validating the old value. + */ +STATIC int +xfs_iunlink_update_bucket( + struct xfs_trans *tp, + struct xfs_perag *pag, + struct xfs_buf *agibp, + unsigned int bucket_index, + xfs_agino_t new_agino) +{ + struct xfs_agi *agi = agibp->b_addr; + xfs_agino_t old_value; + int offset; + + ASSERT(xfs_verify_agino_or_null(pag, new_agino)); + + old_value = be32_to_cpu(agi->agi_unlinked[bucket_index]); + trace_xfs_iunlink_update_bucket(tp->t_mountp, pag->pag_agno, bucket_index, + old_value, new_agino); + + /* + * We should never find the head of the list already set to the value + * passed in because either we're adding or removing ourselves from the + * head of the list. + */ + if (old_value == new_agino) { + xfs_buf_mark_corrupt(agibp); + xfs_ag_mark_sick(pag, XFS_SICK_AG_AGI); + return -EFSCORRUPTED; + } + + agi->agi_unlinked[bucket_index] = cpu_to_be32(new_agino); + offset = offsetof(struct xfs_agi, agi_unlinked) + + (sizeof(xfs_agino_t) * bucket_index); + xfs_trans_log_buf(tp, agibp, offset, offset + sizeof(xfs_agino_t) - 1); + return 0; +} + +static int +xfs_iunlink_insert_inode( + struct xfs_trans *tp, + struct xfs_perag *pag, + struct xfs_buf *agibp, + struct xfs_inode *ip) +{ + struct xfs_mount *mp = tp->t_mountp; + struct xfs_agi *agi = agibp->b_addr; + xfs_agino_t next_agino; + xfs_agino_t agino = XFS_INO_TO_AGINO(mp, ip->i_ino); + short bucket_index = agino % XFS_AGI_UNLINKED_BUCKETS; + int error; + + /* + * Get the index into the agi hash table for the list this inode will + * go on. Make sure the pointer isn't garbage and that this inode + * isn't already on the list. + */ + next_agino = be32_to_cpu(agi->agi_unlinked[bucket_index]); + if (next_agino == agino || + !xfs_verify_agino_or_null(pag, next_agino)) { + xfs_buf_mark_corrupt(agibp); + xfs_ag_mark_sick(pag, XFS_SICK_AG_AGI); + return -EFSCORRUPTED; + } + + /* + * Update the prev pointer in the next inode to point back to this + * inode. + */ + error = xfs_iunlink_update_backref(pag, agino, next_agino); + if (error) + return error; + + if (next_agino != NULLAGINO) { + /* + * There is already another inode in the bucket, so point this + * inode to the current head of the list. + */ + error = xfs_iunlink_log_inode(tp, ip, pag, next_agino); + if (error) + return error; + ip->i_next_unlinked = next_agino; + } + + /* Point the head of the list to point to this inode. */ + ip->i_prev_unlinked = NULLAGINO; + return xfs_iunlink_update_bucket(tp, pag, agibp, bucket_index, agino); +} + +/* + * This is called when the inode's link count has gone to 0 or we are creating + * a tmpfile via O_TMPFILE. The inode @ip must have nlink == 0. + * + * We place the on-disk inode on a list in the AGI. It will be pulled from this + * list when the inode is freed. + */ +int +xfs_iunlink( + struct xfs_trans *tp, + struct xfs_inode *ip) +{ + struct xfs_mount *mp = tp->t_mountp; + struct xfs_perag *pag; + struct xfs_buf *agibp; + int error; + + ASSERT(VFS_I(ip)->i_nlink == 0); + ASSERT(VFS_I(ip)->i_mode != 0); + trace_xfs_iunlink(ip); + + pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino)); + + /* Get the agi buffer first. It ensures lock ordering on the list. */ + error = xfs_read_agi(pag, tp, &agibp); + if (error) + goto out; + + error = xfs_iunlink_insert_inode(tp, pag, agibp, ip); +out: + xfs_perag_put(pag); + return error; +} + +static int +xfs_iunlink_remove_inode( + struct xfs_trans *tp, + struct xfs_perag *pag, + struct xfs_buf *agibp, + struct xfs_inode *ip) +{ + struct xfs_mount *mp = tp->t_mountp; + struct xfs_agi *agi = agibp->b_addr; + xfs_agino_t agino = XFS_INO_TO_AGINO(mp, ip->i_ino); + xfs_agino_t head_agino; + short bucket_index = agino % XFS_AGI_UNLINKED_BUCKETS; + int error; + + trace_xfs_iunlink_remove(ip); + + /* + * Get the index into the agi hash table for the list this inode will + * go on. Make sure the head pointer isn't garbage. + */ + head_agino = be32_to_cpu(agi->agi_unlinked[bucket_index]); + if (!xfs_verify_agino(pag, head_agino)) { + XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, + agi, sizeof(*agi)); + xfs_ag_mark_sick(pag, XFS_SICK_AG_AGI); + return -EFSCORRUPTED; + } + + /* + * Set our inode's next_unlinked pointer to NULL and then return + * the old pointer value so that we can update whatever was previous + * to us in the list to point to whatever was next in the list. + */ + error = xfs_iunlink_log_inode(tp, ip, pag, NULLAGINO); + if (error) + return error; + + /* + * Update the prev pointer in the next inode to point back to previous + * inode in the chain. + */ + error = xfs_iunlink_update_backref(pag, ip->i_prev_unlinked, + ip->i_next_unlinked); + if (error) + return error; + + if (head_agino != agino) { + struct xfs_inode *prev_ip; + + prev_ip = xfs_iunlink_lookup(pag, ip->i_prev_unlinked); + if (!prev_ip) { + xfs_inode_mark_sick(ip, XFS_SICK_INO_CORE); + return -EFSCORRUPTED; + } + + error = xfs_iunlink_log_inode(tp, prev_ip, pag, + ip->i_next_unlinked); + prev_ip->i_next_unlinked = ip->i_next_unlinked; + } else { + /* Point the head of the list to the next unlinked inode. */ + error = xfs_iunlink_update_bucket(tp, pag, agibp, bucket_index, + ip->i_next_unlinked); + } + + ip->i_next_unlinked = NULLAGINO; + ip->i_prev_unlinked = 0; + return error; +} + +/* + * Pull the on-disk inode from the AGI unlinked list. + */ +int +xfs_iunlink_remove( + struct xfs_trans *tp, + struct xfs_perag *pag, + struct xfs_inode *ip) +{ + struct xfs_buf *agibp; + int error; + + trace_xfs_iunlink_remove(ip); + + /* Get the agi buffer first. It ensures lock ordering on the list. */ + error = xfs_read_agi(pag, tp, &agibp); + if (error) + return error; + + return xfs_iunlink_remove_inode(tp, pag, agibp, ip); +} diff --git a/fs/xfs/libxfs/xfs_inode_util.h b/fs/xfs/libxfs/xfs_inode_util.h index a73ccaea5582..e15cf94e0943 100644 --- a/fs/xfs/libxfs/xfs_inode_util.h +++ b/fs/xfs/libxfs/xfs_inode_util.h @@ -56,6 +56,10 @@ void xfs_trans_ichgtime(struct xfs_trans *tp, struct xfs_inode *ip, int flags); void xfs_inode_init(struct xfs_trans *tp, const struct xfs_icreate_args *args, struct xfs_inode *ip); +int xfs_iunlink(struct xfs_trans *tp, struct xfs_inode *ip); +int xfs_iunlink_remove(struct xfs_trans *tp, struct xfs_perag *pag, + struct xfs_inode *ip); + /* The libxfs client must provide this group of helper functions. */ /* Handle legacy Irix sgid inheritance quirks. */ diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index db1f521ac6d0..f69423504216 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -43,9 +43,6 @@ struct kmem_cache *xfs_inode_cache; -STATIC int xfs_iunlink_remove(struct xfs_trans *tp, struct xfs_perag *pag, - struct xfs_inode *); - /* * These two are wrapper routines around the xfs_ilock() routine used to * centralize some grungy code. They are used in places that wish to lock the @@ -1729,39 +1726,6 @@ xfs_inactive( xfs_qm_dqdetach(ip); } -/* - * In-Core Unlinked List Lookups - * ============================= - * - * Every inode is supposed to be reachable from some other piece of metadata - * with the exception of the root directory. Inodes with a connection to a - * file descriptor but not linked from anywhere in the on-disk directory tree - * are collectively known as unlinked inodes, though the filesystem itself - * maintains links to these inodes so that on-disk metadata are consistent. - * - * XFS implements a per-AG on-disk hash table of unlinked inodes. The AGI - * header contains a number of buckets that point to an inode, and each inode - * record has a pointer to the next inode in the hash chain. This - * singly-linked list causes scaling problems in the iunlink remove function - * because we must walk that list to find the inode that points to the inode - * being removed from the unlinked hash bucket list. - * - * Hence we keep an in-memory double linked list to link each inode on an - * unlinked list. Because there are 64 unlinked lists per AGI, keeping pointer - * based lists would require having 64 list heads in the perag, one for each - * list. This is expensive in terms of memory (think millions of AGs) and cache - * misses on lookups. Instead, use the fact that inodes on the unlinked list - * must be referenced at the VFS level to keep them on the list and hence we - * have an existence guarantee for inodes on the unlinked list. - * - * Given we have an existence guarantee, we can use lockless inode cache lookups - * to resolve aginos to xfs inodes. This means we only need 8 bytes per inode - * for the double linked unlinked list, and we don't need any extra locking to - * keep the list safe as all manipulations are done under the AGI buffer lock. - * Keeping the list up to date does not require memory allocation, just finding - * the XFS inode and updating the next/prev unlinked list aginos. - */ - /* * Find an inode on the unlinked list. This does not take references to the * inode as we have existence guarantees by holding the AGI buffer lock and that @@ -1791,245 +1755,6 @@ xfs_iunlink_lookup( return ip; } -/* Update the prev pointer of the next agino. */ -static int -xfs_iunlink_update_backref( - struct xfs_perag *pag, - xfs_agino_t prev_agino, - xfs_agino_t next_agino) -{ - struct xfs_inode *ip; - - /* No update necessary if we are at the end of the list. */ - if (next_agino == NULLAGINO) - return 0; - - ip = xfs_iunlink_lookup(pag, next_agino); - if (!ip) { - xfs_ag_mark_sick(pag, XFS_SICK_AG_AGI); - return -EFSCORRUPTED; - } - - ip->i_prev_unlinked = prev_agino; - return 0; -} - -/* - * Point the AGI unlinked bucket at an inode and log the results. The caller - * is responsible for validating the old value. - */ -STATIC int -xfs_iunlink_update_bucket( - struct xfs_trans *tp, - struct xfs_perag *pag, - struct xfs_buf *agibp, - unsigned int bucket_index, - xfs_agino_t new_agino) -{ - struct xfs_agi *agi = agibp->b_addr; - xfs_agino_t old_value; - int offset; - - ASSERT(xfs_verify_agino_or_null(pag, new_agino)); - - old_value = be32_to_cpu(agi->agi_unlinked[bucket_index]); - trace_xfs_iunlink_update_bucket(tp->t_mountp, pag->pag_agno, bucket_index, - old_value, new_agino); - - /* - * We should never find the head of the list already set to the value - * passed in because either we're adding or removing ourselves from the - * head of the list. - */ - if (old_value == new_agino) { - xfs_buf_mark_corrupt(agibp); - xfs_ag_mark_sick(pag, XFS_SICK_AG_AGI); - return -EFSCORRUPTED; - } - - agi->agi_unlinked[bucket_index] = cpu_to_be32(new_agino); - offset = offsetof(struct xfs_agi, agi_unlinked) + - (sizeof(xfs_agino_t) * bucket_index); - xfs_trans_log_buf(tp, agibp, offset, offset + sizeof(xfs_agino_t) - 1); - return 0; -} - -static int -xfs_iunlink_insert_inode( - struct xfs_trans *tp, - struct xfs_perag *pag, - struct xfs_buf *agibp, - struct xfs_inode *ip) -{ - struct xfs_mount *mp = tp->t_mountp; - struct xfs_agi *agi = agibp->b_addr; - xfs_agino_t next_agino; - xfs_agino_t agino = XFS_INO_TO_AGINO(mp, ip->i_ino); - short bucket_index = agino % XFS_AGI_UNLINKED_BUCKETS; - int error; - - /* - * Get the index into the agi hash table for the list this inode will - * go on. Make sure the pointer isn't garbage and that this inode - * isn't already on the list. - */ - next_agino = be32_to_cpu(agi->agi_unlinked[bucket_index]); - if (next_agino == agino || - !xfs_verify_agino_or_null(pag, next_agino)) { - xfs_buf_mark_corrupt(agibp); - xfs_ag_mark_sick(pag, XFS_SICK_AG_AGI); - return -EFSCORRUPTED; - } - - /* - * Update the prev pointer in the next inode to point back to this - * inode. - */ - error = xfs_iunlink_update_backref(pag, agino, next_agino); - if (error) - return error; - - if (next_agino != NULLAGINO) { - /* - * There is already another inode in the bucket, so point this - * inode to the current head of the list. - */ - error = xfs_iunlink_log_inode(tp, ip, pag, next_agino); - if (error) - return error; - ip->i_next_unlinked = next_agino; - } - - /* Point the head of the list to point to this inode. */ - ip->i_prev_unlinked = NULLAGINO; - return xfs_iunlink_update_bucket(tp, pag, agibp, bucket_index, agino); -} - -/* - * This is called when the inode's link count has gone to 0 or we are creating - * a tmpfile via O_TMPFILE. The inode @ip must have nlink == 0. - * - * We place the on-disk inode on a list in the AGI. It will be pulled from this - * list when the inode is freed. - */ -int -xfs_iunlink( - struct xfs_trans *tp, - struct xfs_inode *ip) -{ - struct xfs_mount *mp = tp->t_mountp; - struct xfs_perag *pag; - struct xfs_buf *agibp; - int error; - - ASSERT(VFS_I(ip)->i_nlink == 0); - ASSERT(VFS_I(ip)->i_mode != 0); - trace_xfs_iunlink(ip); - - pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino)); - - /* Get the agi buffer first. It ensures lock ordering on the list. */ - error = xfs_read_agi(pag, tp, &agibp); - if (error) - goto out; - - error = xfs_iunlink_insert_inode(tp, pag, agibp, ip); -out: - xfs_perag_put(pag); - return error; -} - -static int -xfs_iunlink_remove_inode( - struct xfs_trans *tp, - struct xfs_perag *pag, - struct xfs_buf *agibp, - struct xfs_inode *ip) -{ - struct xfs_mount *mp = tp->t_mountp; - struct xfs_agi *agi = agibp->b_addr; - xfs_agino_t agino = XFS_INO_TO_AGINO(mp, ip->i_ino); - xfs_agino_t head_agino; - short bucket_index = agino % XFS_AGI_UNLINKED_BUCKETS; - int error; - - trace_xfs_iunlink_remove(ip); - - /* - * Get the index into the agi hash table for the list this inode will - * go on. Make sure the head pointer isn't garbage. - */ - head_agino = be32_to_cpu(agi->agi_unlinked[bucket_index]); - if (!xfs_verify_agino(pag, head_agino)) { - XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, - agi, sizeof(*agi)); - xfs_ag_mark_sick(pag, XFS_SICK_AG_AGI); - return -EFSCORRUPTED; - } - - /* - * Set our inode's next_unlinked pointer to NULL and then return - * the old pointer value so that we can update whatever was previous - * to us in the list to point to whatever was next in the list. - */ - error = xfs_iunlink_log_inode(tp, ip, pag, NULLAGINO); - if (error) - return error; - - /* - * Update the prev pointer in the next inode to point back to previous - * inode in the chain. - */ - error = xfs_iunlink_update_backref(pag, ip->i_prev_unlinked, - ip->i_next_unlinked); - if (error) - return error; - - if (head_agino != agino) { - struct xfs_inode *prev_ip; - - prev_ip = xfs_iunlink_lookup(pag, ip->i_prev_unlinked); - if (!prev_ip) { - xfs_inode_mark_sick(ip, XFS_SICK_INO_CORE); - return -EFSCORRUPTED; - } - - error = xfs_iunlink_log_inode(tp, prev_ip, pag, - ip->i_next_unlinked); - prev_ip->i_next_unlinked = ip->i_next_unlinked; - } else { - /* Point the head of the list to the next unlinked inode. */ - error = xfs_iunlink_update_bucket(tp, pag, agibp, bucket_index, - ip->i_next_unlinked); - } - - ip->i_next_unlinked = NULLAGINO; - ip->i_prev_unlinked = 0; - return error; -} - -/* - * Pull the on-disk inode from the AGI unlinked list. - */ -STATIC int -xfs_iunlink_remove( - struct xfs_trans *tp, - struct xfs_perag *pag, - struct xfs_inode *ip) -{ - struct xfs_buf *agibp; - int error; - - trace_xfs_iunlink_remove(ip); - - /* Get the agi buffer first. It ensures lock ordering on the list. */ - error = xfs_read_agi(pag, tp, &agibp); - if (error) - return error; - - return xfs_iunlink_remove_inode(tp, pag, agibp, ip); -} - /* * Look up the inode number specified and if it is not already marked XFS_ISTALE * mark it stale. We should only find clean inodes in this lookup that aren't diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index b99c62f14919..d07763312a27 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -574,7 +574,6 @@ extern struct kmem_cache *xfs_inode_cache; bool xfs_inode_needs_inactive(struct xfs_inode *ip); -int xfs_iunlink(struct xfs_trans *tp, struct xfs_inode *ip); struct xfs_inode *xfs_iunlink_lookup(struct xfs_perag *pag, xfs_agino_t agino); void xfs_end_io(struct work_struct *work); From patchwork Fri Dec 30 22:17:20 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13085356 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 06A21C4332F for ; Sat, 31 Dec 2022 01:08:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236003AbiLaBId (ORCPT ); Fri, 30 Dec 2022 20:08:33 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41302 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235933AbiLaBIc (ORCPT ); Fri, 30 Dec 2022 20:08:32 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CC87D1573A for ; Fri, 30 Dec 2022 17:08:31 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 71AF661D38 for ; Sat, 31 Dec 2022 01:08:31 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id D22A2C433D2; Sat, 31 Dec 2022 01:08:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1672448910; bh=JeRumTp+7rYI+pzaW+cwzkfzv1rijkpzNulh2GedVaQ=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=DkpFKejXGA9h2d0AoDsfOB8I7MtW5ON7BL0/0YwrwfsY/Y+6c2egklwYzLctBjC+d EPt+nmLZdn0yaMilXeLdY2w215E6k2HOBhGaHIkOaUDAnB8NBGDzhkQQkU9JQDdJz3 5HCa3He48t/HWBuGFWycDdvhB4lNVYPKyp+wYMlr6DJkmvHDJpq9D2nTmNWROQ4uCO YFaR9r33XSWRKEizMUSq8El5tuDD4rbewnaGfe+MRZVjCcg0XIjBqioRQbkB0KXZC0 ty/hw2iLOyep1omNkYsUeyuYV/DtllsdfT8J48Qe/Hy70HutT043g0AlNKIWNUodQB tLPA/Qefd3l4Q== Subject: [PATCH 13/20] xfs: hoist xfs_{bump,drop}link to libxfs From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Date: Fri, 30 Dec 2022 14:17:20 -0800 Message-ID: <167243864015.707335.15427130046025701783.stgit@magnolia> In-Reply-To: <167243863809.707335.15895322495460356300.stgit@magnolia> References: <167243863809.707335.15895322495460356300.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Move xfs_bumplink and xfs_droplink to libxfs. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_inode_util.c | 35 +++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_inode_util.h | 2 ++ fs/xfs/xfs_inode.c | 35 ----------------------------------- fs/xfs/xfs_inode.h | 1 - 4 files changed, 37 insertions(+), 36 deletions(-) diff --git a/fs/xfs/libxfs/xfs_inode_util.c b/fs/xfs/libxfs/xfs_inode_util.c index 0c3ac4b07cc5..e32b3152c3df 100644 --- a/fs/xfs/libxfs/xfs_inode_util.c +++ b/fs/xfs/libxfs/xfs_inode_util.c @@ -610,3 +610,38 @@ xfs_iunlink_remove( return xfs_iunlink_remove_inode(tp, pag, agibp, ip); } + +/* + * Decrement the link count on an inode & log the change. If this causes the + * link count to go to zero, move the inode to AGI unlinked list so that it can + * be freed when the last active reference goes away via xfs_inactive(). + */ +int +xfs_droplink( + struct xfs_trans *tp, + struct xfs_inode *ip) +{ + xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG); + + drop_nlink(VFS_I(ip)); + xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); + + if (VFS_I(ip)->i_nlink) + return 0; + + return xfs_iunlink(tp, ip); +} + +/* + * Increment the link count on an inode & log the change. + */ +void +xfs_bumplink( + struct xfs_trans *tp, + struct xfs_inode *ip) +{ + xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG); + + inc_nlink(VFS_I(ip)); + xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); +} diff --git a/fs/xfs/libxfs/xfs_inode_util.h b/fs/xfs/libxfs/xfs_inode_util.h index e15cf94e0943..f92b14a6fbe8 100644 --- a/fs/xfs/libxfs/xfs_inode_util.h +++ b/fs/xfs/libxfs/xfs_inode_util.h @@ -59,6 +59,8 @@ void xfs_inode_init(struct xfs_trans *tp, const struct xfs_icreate_args *args, int xfs_iunlink(struct xfs_trans *tp, struct xfs_inode *ip); int xfs_iunlink_remove(struct xfs_trans *tp, struct xfs_perag *pag, struct xfs_inode *ip); +int xfs_droplink(struct xfs_trans *tp, struct xfs_inode *ip); +void xfs_bumplink(struct xfs_trans *tp, struct xfs_inode *ip); /* The libxfs client must provide this group of helper functions. */ diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index f69423504216..f9599aa49ab4 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -657,41 +657,6 @@ xfs_icreate_args_rootfile( XFS_ICREATE_ARGS_FORCE_MODE; } -/* - * Decrement the link count on an inode & log the change. If this causes the - * link count to go to zero, move the inode to AGI unlinked list so that it can - * be freed when the last active reference goes away via xfs_inactive(). - */ -static int /* error */ -xfs_droplink( - xfs_trans_t *tp, - xfs_inode_t *ip) -{ - xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG); - - drop_nlink(VFS_I(ip)); - xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); - - if (VFS_I(ip)->i_nlink) - return 0; - - return xfs_iunlink(tp, ip); -} - -/* - * Increment the link count on an inode & log the change. - */ -void -xfs_bumplink( - struct xfs_trans *tp, - struct xfs_inode *ip) -{ - xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG); - - inc_nlink(VFS_I(ip)); - xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); -} - #ifdef CONFIG_XFS_LIVE_HOOKS /* * Use a static key here to reduce the overhead of link count live updates. If diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index d07763312a27..571f61930b7b 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -580,7 +580,6 @@ void xfs_end_io(struct work_struct *work); int xfs_ilock2_io_mmap(struct xfs_inode *ip1, struct xfs_inode *ip2); void xfs_iunlock2_io_mmap(struct xfs_inode *ip1, struct xfs_inode *ip2); -void xfs_bumplink(struct xfs_trans *tp, struct xfs_inode *ip); void xfs_inode_count_blocks(struct xfs_trans *tp, struct xfs_inode *ip, xfs_filblks_t *dblocks, xfs_filblks_t *rblocks); From patchwork Fri Dec 30 22:17:20 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13085357 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 1AE5CC3DA7D for ; Sat, 31 Dec 2022 01:08:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235750AbiLaBIu (ORCPT ); Fri, 30 Dec 2022 20:08:50 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41344 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236008AbiLaBIs (ORCPT ); Fri, 30 Dec 2022 20:08:48 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 71E1F15F3F for ; Fri, 30 Dec 2022 17:08:47 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 116E761D3D for ; Sat, 31 Dec 2022 01:08:47 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6D90DC433F1; Sat, 31 Dec 2022 01:08:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1672448926; bh=4TZXYGpMLLTXMOdSQHjP+ekx99tNVyAIdgI6smfMv2w=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=iydwyFlFmqgNnKYb23BncNJPYGjzqXMEJ+IkaGEVXWfxbUNEWe6sRUwLw46A1Toz+ nnhol6zoagpqbJDUmxNWn0SHv2HoAJx4wlmyDrOIrbxu5CmZpZ/EEv9ySD/rzZT4NL xwP0TBuHyrqui1m5nR+VgZBEVFyU+eyGv5NfeqsQQI3GNwu2vPkGV/CplpwXV+6vlV qwmDex5QYeW3ZR3Ew3DerkpMvu1ebJO1U6bz1z/ViIy8LiCzlaw4MwblE3/d5kA9Pn 7F6BjT0Mfr7pfGhDKRvgR3NvZYHAzVCchuWOFWdbE5Cr6Vt7NVJsze5a0Q6ujfEp3H AYjTpmpFEHm6A== Subject: [PATCH 14/20] xfs: create libxfs helper to link a new inode into a directory From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Date: Fri, 30 Dec 2022 14:17:20 -0800 Message-ID: <167243864030.707335.4591241191547646047.stgit@magnolia> In-Reply-To: <167243863809.707335.15895322495460356300.stgit@magnolia> References: <167243863809.707335.15895322495460356300.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Create a new libxfs function to link a newly created inode into a directory. The upcoming metadata directory feature will need this to create a metadata directory tree. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_dir2.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_dir2.h | 4 ++++ fs/xfs/xfs_inode.c | 17 ++--------------- 3 files changed, 50 insertions(+), 15 deletions(-) diff --git a/fs/xfs/libxfs/xfs_dir2.c b/fs/xfs/libxfs/xfs_dir2.c index fb0697dc733f..bca493a2da8d 100644 --- a/fs/xfs/libxfs/xfs_dir2.c +++ b/fs/xfs/libxfs/xfs_dir2.c @@ -19,6 +19,8 @@ #include "xfs_error.h" #include "xfs_trace.h" #include "xfs_health.h" +#include "xfs_bmap_btree.h" +#include "xfs_trans_space.h" const struct xfs_name xfs_name_dotdot = { .name = (const unsigned char *)"..", @@ -781,3 +783,45 @@ xfs_dir2_compname( return xfs_ascii_ci_compname(args, name, len); return xfs_da_compname(args, name, len); } + +/* + * Given a directory @dp, a newly allocated inode @ip, and a @name, link @ip + * into @dp under the given @name. If @ip is a directory, it will be + * initialized. Both inodes must have the ILOCK held and the transaction must + * have sufficient blocks reserved. + */ +int +xfs_dir_create_new_child( + struct xfs_trans *tp, + uint resblks, + struct xfs_inode *dp, + struct xfs_name *name, + struct xfs_inode *ip) +{ + struct xfs_mount *mp = tp->t_mountp; + int error; + + ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); + ASSERT(xfs_isilocked(dp, XFS_ILOCK_EXCL)); + ASSERT(resblks == 0 || resblks > XFS_IALLOC_SPACE_RES(mp)); + + error = xfs_dir_createname(tp, dp, name, ip->i_ino, + resblks - XFS_IALLOC_SPACE_RES(mp)); + if (error) { + ASSERT(error != -ENOSPC); + return error; + } + + xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); + xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); + + if (!S_ISDIR(VFS_I(ip)->i_mode)) + return 0; + + error = xfs_dir_init(tp, ip, dp); + if (error) + return error; + + xfs_bumplink(tp, dp); + return 0; +} diff --git a/fs/xfs/libxfs/xfs_dir2.h b/fs/xfs/libxfs/xfs_dir2.h index 7322284f61a0..d3e7607c0e9d 100644 --- a/fs/xfs/libxfs/xfs_dir2.h +++ b/fs/xfs/libxfs/xfs_dir2.h @@ -253,4 +253,8 @@ unsigned int xfs_dir3_data_end_offset(struct xfs_da_geometry *geo, struct xfs_dir2_data_hdr *hdr); bool xfs_dir2_namecheck(const void *name, size_t length); +int xfs_dir_create_new_child(struct xfs_trans *tp, uint resblks, + struct xfs_inode *dp, struct xfs_name *name, + struct xfs_inode *ip); + #endif /* __XFS_DIR2_H__ */ diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index f9599aa49ab4..b66a9cf66055 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -868,22 +868,9 @@ xfs_create( xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL); unlock_dp_on_error = false; - error = xfs_dir_createname(tp, dp, name, ip->i_ino, - resblks - XFS_IALLOC_SPACE_RES(mp)); - if (error) { - ASSERT(error != -ENOSPC); + error = xfs_dir_create_new_child(tp, resblks, dp, name, ip); + if (error) goto out_trans_cancel; - } - xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); - xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); - - if (is_dir) { - error = xfs_dir_init(tp, ip, dp); - if (error) - goto out_trans_cancel; - - xfs_bumplink(tp, dp); - } /* * Create ip with a reference from dp, and add '.' and '..' references From patchwork Fri Dec 30 22:17:20 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13085358 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 6F8D8C4332F for ; Sat, 31 Dec 2022 01:09:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235811AbiLaBJF (ORCPT ); Fri, 30 Dec 2022 20:09:05 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41406 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236007AbiLaBJE (ORCPT ); Fri, 30 Dec 2022 20:09:04 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F07091573A for ; Fri, 30 Dec 2022 17:09:02 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 9097561D03 for ; Sat, 31 Dec 2022 01:09:02 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0151AC433D2; Sat, 31 Dec 2022 01:09:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1672448942; bh=sQSx26lEfcOUAq6gf+Zr2B8YjYWL/lTwiiUxDkC1Dqg=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=o0YU5gHNYciaYodl2eGYJse8ETaitiUSePzw09igJ6jABqIcZ0J1w/x4xdmyUdjxz 0K0UrPE0uUELR6EK32EAohoMo+VYL3qk7csS9zKXUVKGafdxqh5adKs6QwKrNE/3X5 i8jMuX0EeHILwmJROTzlwPj7d6cREf+MOtoHWUuFZd+gCRVk0rCpb0htC/0I4UD2DR t3wR9cegRv+HpjvS2SvyiDhNMWGPu/8oMEz6SNTg8/R9bqp6GlI57z7TeYI5ASP6YJ Jl3HSZylCdfs5PccRpVJvDdtuIdN/wpsZUZCxZGRddEAFc2uDyee4b+ejqMbffnLGB 1zMzLizh2SQIQ== Subject: [PATCH 15/20] xfs: create libxfs helper to link an existing inode into a directory From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Date: Fri, 30 Dec 2022 14:17:20 -0800 Message-ID: <167243864045.707335.4412916251763797944.stgit@magnolia> In-Reply-To: <167243863809.707335.15895322495460356300.stgit@magnolia> References: <167243863809.707335.15895322495460356300.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Create a new libxfs function to link an existing inode into a directory. The upcoming metadata directory feature will need this to create a metadata directory tree. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_dir2.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_dir2.h | 3 +++ fs/xfs/xfs_inode.c | 26 +---------------------- 3 files changed, 55 insertions(+), 25 deletions(-) diff --git a/fs/xfs/libxfs/xfs_dir2.c b/fs/xfs/libxfs/xfs_dir2.c index bca493a2da8d..e14464712eff 100644 --- a/fs/xfs/libxfs/xfs_dir2.c +++ b/fs/xfs/libxfs/xfs_dir2.c @@ -21,6 +21,7 @@ #include "xfs_health.h" #include "xfs_bmap_btree.h" #include "xfs_trans_space.h" +#include "xfs_ag.h" const struct xfs_name xfs_name_dotdot = { .name = (const unsigned char *)"..", @@ -825,3 +826,53 @@ xfs_dir_create_new_child( xfs_bumplink(tp, dp); return 0; } + +/* + * Given a directory @dp, an existing non-directory inode @ip, and a @name, + * link @ip into @dp under the given @name. Both inodes must have the ILOCK + * held. + */ +int +xfs_dir_link_existing_child( + struct xfs_trans *tp, + uint resblks, + struct xfs_inode *dp, + struct xfs_name *name, + struct xfs_inode *ip) +{ + struct xfs_mount *mp = tp->t_mountp; + int error; + + ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); + ASSERT(xfs_isilocked(dp, XFS_ILOCK_EXCL)); + ASSERT(!S_ISDIR(VFS_I(ip)->i_mode)); + + if (!resblks) { + error = xfs_dir_canenter(tp, dp, name); + if (error) + return error; + } + + /* + * Handle initial link state of O_TMPFILE inode + */ + if (VFS_I(ip)->i_nlink == 0) { + struct xfs_perag *pag; + + pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino)); + error = xfs_iunlink_remove(tp, pag, ip); + xfs_perag_put(pag); + if (error) + return error; + } + + error = xfs_dir_createname(tp, dp, name, ip->i_ino, resblks); + if (error) + return error; + + xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); + xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); + + xfs_bumplink(tp, ip); + return 0; +} diff --git a/fs/xfs/libxfs/xfs_dir2.h b/fs/xfs/libxfs/xfs_dir2.h index d3e7607c0e9d..4afade8b0877 100644 --- a/fs/xfs/libxfs/xfs_dir2.h +++ b/fs/xfs/libxfs/xfs_dir2.h @@ -256,5 +256,8 @@ bool xfs_dir2_namecheck(const void *name, size_t length); int xfs_dir_create_new_child(struct xfs_trans *tp, uint resblks, struct xfs_inode *dp, struct xfs_name *name, struct xfs_inode *ip); +int xfs_dir_link_existing_child(struct xfs_trans *tp, uint resblks, + struct xfs_inode *dp, struct xfs_name *name, + struct xfs_inode *ip); #endif /* __XFS_DIR2_H__ */ diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index b66a9cf66055..e2563401b27d 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -1062,33 +1062,9 @@ xfs_link( goto error_return; } - if (!resblks) { - error = xfs_dir_canenter(tp, tdp, target_name); - if (error) - goto error_return; - } - - /* - * Handle initial link state of O_TMPFILE inode - */ - if (VFS_I(sip)->i_nlink == 0) { - struct xfs_perag *pag; - - pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, sip->i_ino)); - error = xfs_iunlink_remove(tp, pag, sip); - xfs_perag_put(pag); - if (error) - goto error_return; - } - - error = xfs_dir_createname(tp, tdp, target_name, sip->i_ino, - resblks); + error = xfs_dir_link_existing_child(tp, resblks, tdp, target_name, sip); if (error) goto error_return; - xfs_trans_ichgtime(tp, tdp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); - xfs_trans_log_inode(tp, tdp, XFS_ILOG_CORE); - - xfs_bumplink(tp, sip); xfs_nlink_dirent_delta(tdp, sip, 1, target_name); /* From patchwork Fri Dec 30 22:17:20 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13085359 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 27483C4332F for ; Sat, 31 Dec 2022 01:09:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236007AbiLaBJU (ORCPT ); Fri, 30 Dec 2022 20:09:20 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41610 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235827AbiLaBJT (ORCPT ); Fri, 30 Dec 2022 20:09:19 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 856861DDF0 for ; Fri, 30 Dec 2022 17:09:18 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 2222261D33 for ; Sat, 31 Dec 2022 01:09:18 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 81433C433D2; Sat, 31 Dec 2022 01:09:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1672448957; bh=gb+Fy8Zpq48kdEHBJZl/5btK4yizTEHI3BtPJnDURKQ=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=ooTzkpdqeGk1Il7q8KzyCas5e/Rm0KUsQSFP5m5fYp+9/UAE/vMgiVIjPiIUNT94O IPiO7X4wxcgf0XpKtjaztOrx5NcQwkEissvfLIVV/J2EBOBG1gL7Rg7QerOgrgDRbK tBuD5K/vsWXQe81xIFloi3B1aDSa+f8jGiSQUKvoUkXGlsBR2TL+Jdk5cRyqexSeBi 4WZ3fRxY97WhihZ+xso32iWML/IyCykAJY2HcpdzBdkQT9KlT7rqPuW28E37yStXod K9WoRssQ84HTDCVy3ESXNcthWzO1K29SiP8kUb4yE6kozq+K+bbkB1WwfkLRJKD4c9 XLvNYFSgC4JBA== Subject: [PATCH 16/20] xfs: hoist inode free function to libxfs From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Date: Fri, 30 Dec 2022 14:17:20 -0800 Message-ID: <167243864060.707335.16448396748632349504.stgit@magnolia> In-Reply-To: <167243863809.707335.15895322495460356300.stgit@magnolia> References: <167243863809.707335.15895322495460356300.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Create a libxfs helper function that marks an inode free on disk. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_inode_util.c | 51 ++++++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_inode_util.h | 5 ++++ fs/xfs/xfs_inode.c | 35 +-------------------------- 3 files changed, 57 insertions(+), 34 deletions(-) diff --git a/fs/xfs/libxfs/xfs_inode_util.c b/fs/xfs/libxfs/xfs_inode_util.c index e32b3152c3df..1135bec1328b 100644 --- a/fs/xfs/libxfs/xfs_inode_util.c +++ b/fs/xfs/libxfs/xfs_inode_util.c @@ -22,6 +22,7 @@ #include "xfs_trace.h" #include "xfs_ag.h" #include "xfs_iunlink_item.h" +#include "xfs_inode_item.h" uint16_t xfs_flags2diflags( @@ -645,3 +646,53 @@ xfs_bumplink( inc_nlink(VFS_I(ip)); xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); } + +/* Mark an inode free on disk. */ +int +xfs_dir_ifree( + struct xfs_trans *tp, + struct xfs_perag *pag, + struct xfs_inode *ip, + struct xfs_icluster *xic) +{ + int error; + + /* + * Free the inode first so that we guarantee that the AGI lock is going + * to be taken before we remove the inode from the unlinked list. This + * makes the AGI lock -> unlinked list modification order the same as + * used in O_TMPFILE creation. + */ + error = xfs_difree(tp, pag, ip->i_ino, xic); + if (error) + return error; + + error = xfs_iunlink_remove(tp, pag, ip); + if (error) + return error; + + /* + * Free any local-format data sitting around before we reset the + * data fork to extents format. Note that the attr fork data has + * already been freed by xfs_attr_inactive. + */ + if (ip->i_df.if_format == XFS_DINODE_FMT_LOCAL) { + kmem_free(ip->i_df.if_u1.if_data); + ip->i_df.if_u1.if_data = NULL; + ip->i_df.if_bytes = 0; + } + + VFS_I(ip)->i_mode = 0; /* mark incore inode as free */ + ip->i_diflags = 0; + ip->i_diflags2 = ip->i_mount->m_ino_geo.new_diflags2; + ip->i_forkoff = 0; /* mark the attr fork not in use */ + ip->i_df.if_format = XFS_DINODE_FMT_EXTENTS; + + /* + * Bump the generation count so no one will be confused + * by reincarnations of this inode. + */ + VFS_I(ip)->i_generation++; + xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); + return 0; +} diff --git a/fs/xfs/libxfs/xfs_inode_util.h b/fs/xfs/libxfs/xfs_inode_util.h index f92b14a6fbe8..fcddaa6f738c 100644 --- a/fs/xfs/libxfs/xfs_inode_util.h +++ b/fs/xfs/libxfs/xfs_inode_util.h @@ -6,6 +6,8 @@ #ifndef __XFS_INODE_UTIL_H__ #define __XFS_INODE_UTIL_H__ +struct xfs_icluster; + uint16_t xfs_flags2diflags(struct xfs_inode *ip, unsigned int xflags); uint64_t xfs_flags2diflags2(struct xfs_inode *ip, unsigned int xflags); uint32_t xfs_dic2xflags(struct xfs_inode *ip); @@ -56,6 +58,9 @@ void xfs_trans_ichgtime(struct xfs_trans *tp, struct xfs_inode *ip, int flags); void xfs_inode_init(struct xfs_trans *tp, const struct xfs_icreate_args *args, struct xfs_inode *ip); +int xfs_dir_ifree(struct xfs_trans *tp, struct xfs_perag *pag, + struct xfs_inode *ip, struct xfs_icluster *xic); + int xfs_iunlink(struct xfs_trans *tp, struct xfs_inode *ip); int xfs_iunlink_remove(struct xfs_trans *tp, struct xfs_perag *pag, struct xfs_inode *ip); diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index e2563401b27d..8bd9d47bf6fa 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -1886,36 +1886,10 @@ xfs_ifree( pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino)); - /* - * Free the inode first so that we guarantee that the AGI lock is going - * to be taken before we remove the inode from the unlinked list. This - * makes the AGI lock -> unlinked list modification order the same as - * used in O_TMPFILE creation. - */ - error = xfs_difree(tp, pag, ip->i_ino, &xic); + error = xfs_dir_ifree(tp, pag, ip, &xic); if (error) goto out; - error = xfs_iunlink_remove(tp, pag, ip); - if (error) - goto out; - - /* - * Free any local-format data sitting around before we reset the - * data fork to extents format. Note that the attr fork data has - * already been freed by xfs_attr_inactive. - */ - if (ip->i_df.if_format == XFS_DINODE_FMT_LOCAL) { - kmem_free(ip->i_df.if_u1.if_data); - ip->i_df.if_u1.if_data = NULL; - ip->i_df.if_bytes = 0; - } - - VFS_I(ip)->i_mode = 0; /* mark incore inode as free */ - ip->i_diflags = 0; - ip->i_diflags2 = mp->m_ino_geo.new_diflags2; - ip->i_forkoff = 0; /* mark the attr fork not in use */ - ip->i_df.if_format = XFS_DINODE_FMT_EXTENTS; if (xfs_iflags_test(ip, XFS_IPRESERVE_DM_FIELDS)) xfs_iflags_clear(ip, XFS_IPRESERVE_DM_FIELDS); @@ -1924,13 +1898,6 @@ xfs_ifree( iip->ili_fields &= ~(XFS_ILOG_AOWNER | XFS_ILOG_DOWNER); spin_unlock(&iip->ili_lock); - /* - * Bump the generation count so no one will be confused - * by reincarnations of this inode. - */ - VFS_I(ip)->i_generation++; - xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); - if (xic.deleted) error = xfs_ifree_cluster(tp, pag, ip, &xic); out: From patchwork Fri Dec 30 22:17:20 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13085360 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 E07DAC4332F for ; Sat, 31 Dec 2022 01:09:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236008AbiLaBJf (ORCPT ); Fri, 30 Dec 2022 20:09:35 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41658 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231425AbiLaBJf (ORCPT ); Fri, 30 Dec 2022 20:09:35 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 08E4A1573A for ; Fri, 30 Dec 2022 17:09:34 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id A31BC61D45 for ; Sat, 31 Dec 2022 01:09:33 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0F59CC433D2; Sat, 31 Dec 2022 01:09:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1672448973; bh=UsHDECBx47qGrTaFBCkSZPquEFDKQwecAGi1iJi1Ac4=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=AyZztw26nIVRTm6GfPs1zWpumFCCMXjWo4SHk+0k54C8NGrYR64YQXaqQ1Lqn5Gyq zzybugPuXUqpE/ixuJvDAExkt8tBHxcQYZRaPTZnk9V4Batk4oWdmyiMgTuEI8JSmy y2qR/0IGEEjvgXqrkcP8DM1cLU3PSEme6c4lCORM6cFj+JU/MXRsp8GlKEyXqjhcxo 6F9Pho/pLGYY07usqSAOxzH2ZAvF3pd0bg+qF0fFDwJ9yY4kna5YbBw6fd45CyI6Wx AA17e7eENfzvceS/mStVp2J/iltjJJEeSMw/zQ4CwBS2oEPX2jik6H0GtoJStf9Ik8 oyjvn0N744YaA== Subject: [PATCH 17/20] xfs: create libxfs helper to remove an existing inode/name from a directory From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Date: Fri, 30 Dec 2022 14:17:20 -0800 Message-ID: <167243864074.707335.4873300496146568470.stgit@magnolia> In-Reply-To: <167243863809.707335.15895322495460356300.stgit@magnolia> References: <167243863809.707335.15895322495460356300.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Create a new libxfs function to remove a (name, inode) entry from a directory. The upcoming metadata directory feature will need this to create a metadata directory tree. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_dir2.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_dir2.h | 3 ++ fs/xfs/xfs_inode.c | 55 +---------------------------------- 3 files changed, 77 insertions(+), 54 deletions(-) diff --git a/fs/xfs/libxfs/xfs_dir2.c b/fs/xfs/libxfs/xfs_dir2.c index e14464712eff..2923cf568e9d 100644 --- a/fs/xfs/libxfs/xfs_dir2.c +++ b/fs/xfs/libxfs/xfs_dir2.c @@ -876,3 +876,76 @@ xfs_dir_link_existing_child( xfs_bumplink(tp, ip); return 0; } + +/* + * Given a directory @dp, a child @ip, and a @name, remove the (@name, @ip) + * entry from the directory. Both inodes must have the ILOCK held. + */ +int +xfs_dir_remove_child( + struct xfs_trans *tp, + uint resblks, + struct xfs_inode *dp, + struct xfs_name *name, + struct xfs_inode *ip) +{ + int error; + + ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); + ASSERT(xfs_isilocked(dp, XFS_ILOCK_EXCL)); + + /* + * If we're removing a directory perform some additional validation. + */ + if (S_ISDIR(VFS_I(ip)->i_mode)) { + ASSERT(VFS_I(ip)->i_nlink >= 2); + if (VFS_I(ip)->i_nlink != 2) + return -ENOTEMPTY; + if (!xfs_dir_isempty(ip)) + return -ENOTEMPTY; + + /* Drop the link from ip's "..". */ + error = xfs_droplink(tp, dp); + if (error) + return error; + + /* Drop the "." link from ip to self. */ + error = xfs_droplink(tp, ip); + if (error) + return error; + + /* + * Point the unlinked child directory's ".." entry to the root + * directory to eliminate back-references to inodes that may + * get freed before the child directory is closed. If the fs + * gets shrunk, this can lead to dirent inode validation errors. + */ + if (dp->i_ino != tp->t_mountp->m_sb.sb_rootino) { + error = xfs_dir_replace(tp, ip, &xfs_name_dotdot, + tp->t_mountp->m_sb.sb_rootino, 0); + if (error) + return error; + } + } else { + /* + * When removing a non-directory we need to log the parent + * inode here. For a directory this is done implicitly + * by the xfs_droplink call for the ".." entry. + */ + xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); + } + xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); + + /* Drop the link from dp to ip. */ + error = xfs_droplink(tp, ip); + if (error) + return error; + + error = xfs_dir_removename(tp, dp, name, ip->i_ino, resblks); + if (error) { + ASSERT(error != -ENOENT); + return error; + } + + return 0; +} diff --git a/fs/xfs/libxfs/xfs_dir2.h b/fs/xfs/libxfs/xfs_dir2.h index 4afade8b0877..e35deb273d84 100644 --- a/fs/xfs/libxfs/xfs_dir2.h +++ b/fs/xfs/libxfs/xfs_dir2.h @@ -259,5 +259,8 @@ int xfs_dir_create_new_child(struct xfs_trans *tp, uint resblks, int xfs_dir_link_existing_child(struct xfs_trans *tp, uint resblks, struct xfs_inode *dp, struct xfs_name *name, struct xfs_inode *ip); +int xfs_dir_remove_child(struct xfs_trans *tp, uint resblks, + struct xfs_inode *dp, struct xfs_name *name, + struct xfs_inode *ip); #endif /* __XFS_DIR2_H__ */ diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 8bd9d47bf6fa..f2a5de0119b3 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -2020,63 +2020,10 @@ xfs_remove( goto std_return; } - /* - * If we're removing a directory perform some additional validation. - */ - if (is_dir) { - ASSERT(VFS_I(ip)->i_nlink >= 2); - if (VFS_I(ip)->i_nlink != 2) { - error = -ENOTEMPTY; - goto out_trans_cancel; - } - if (!xfs_dir_isempty(ip)) { - error = -ENOTEMPTY; - goto out_trans_cancel; - } - - /* Drop the link from ip's "..". */ - error = xfs_droplink(tp, dp); - if (error) - goto out_trans_cancel; - - /* Drop the "." link from ip to self. */ - error = xfs_droplink(tp, ip); - if (error) - goto out_trans_cancel; - - /* - * Point the unlinked child directory's ".." entry to the root - * directory to eliminate back-references to inodes that may - * get freed before the child directory is closed. If the fs - * gets shrunk, this can lead to dirent inode validation errors. - */ - if (dp->i_ino != tp->t_mountp->m_sb.sb_rootino) { - error = xfs_dir_replace(tp, ip, &xfs_name_dotdot, - tp->t_mountp->m_sb.sb_rootino, 0); - if (error) - goto out_trans_cancel; - } - } else { - /* - * When removing a non-directory we need to log the parent - * inode here. For a directory this is done implicitly - * by the xfs_droplink call for the ".." entry. - */ - xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); - } - xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); - - /* Drop the link from dp to ip. */ - error = xfs_droplink(tp, ip); + error = xfs_dir_remove_child(tp, resblks, dp, name, ip); if (error) goto out_trans_cancel; - error = xfs_dir_removename(tp, dp, name, ip->i_ino, resblks); - if (error) { - ASSERT(error != -ENOENT); - goto out_trans_cancel; - } - /* * Drop the link from dp to ip, and if ip was a directory, remove the * '.' and '..' references since we freed the directory. From patchwork Fri Dec 30 22:17:20 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13085361 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 2E19FC4332F for ; Sat, 31 Dec 2022 01:09:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231425AbiLaBJx (ORCPT ); Fri, 30 Dec 2022 20:09:53 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41790 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235827AbiLaBJw (ORCPT ); Fri, 30 Dec 2022 20:09:52 -0500 Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4B4531EAD1 for ; Fri, 30 Dec 2022 17:09:51 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 035D6B81DEF for ; Sat, 31 Dec 2022 01:09:50 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id AD8C6C433EF; Sat, 31 Dec 2022 01:09:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1672448988; bh=SxR9DrNBVGqk1/rHPInzy1Pcp3tk59XBkgbuLTPHE04=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=BFG8GXKx+pTwwbsuLnHHhYFqYQya7hswOfy23PSYFLwRBT2eB5zqn04mbGgHUYsOg aRmTQUft3yIMXTH1XiXihw2/TsTooPT6SvZI/g6vLsJKu7sGfMHOTLFmHaHm3V6Dxx noqkhwUFBABpF7lq8GTvBzl4IkFP1vx++nO33lXRaX2Lsk84kTGUXLBVUHKnio0ZDk is4uPi3SIJipfe2mguh4CfmwTjYHwSZxr00Q1QcgOZ9tAPQibsLmG4jWUWl1ZR4nPm 0bAWcdSOycDgIoS2vSN/H24NWXnJn1DeCVUfmhdzFEY6cReudSNB7/09vcH4WMLBgq ja/9LnOXEB/GA== Subject: [PATCH 18/20] xfs: create libxfs helper to exchange two directory entries From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Date: Fri, 30 Dec 2022 14:17:20 -0800 Message-ID: <167243864089.707335.16200487956811105227.stgit@magnolia> In-Reply-To: <167243863809.707335.15895322495460356300.stgit@magnolia> References: <167243863809.707335.15895322495460356300.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Create a new libxfs function to exchange two directory entries. The upcoming metadata directory feature will need this to replace a metadata inode directory entry. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_dir2.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_dir2.h | 4 ++ fs/xfs/xfs_inode.c | 86 +------------------------------------ 3 files changed, 115 insertions(+), 83 deletions(-) diff --git a/fs/xfs/libxfs/xfs_dir2.c b/fs/xfs/libxfs/xfs_dir2.c index 2923cf568e9d..6d7851a613e7 100644 --- a/fs/xfs/libxfs/xfs_dir2.c +++ b/fs/xfs/libxfs/xfs_dir2.c @@ -949,3 +949,111 @@ xfs_dir_remove_child( return 0; } + +/* + * Exchange the entry (@name1, @ip1) in directory @dp1 with the entry (@name2, + * @ip2) in directory @dp2, and update '..' @ip1 and @ip2's entries as needed. + * @ip1 and @ip2 need not be of the same type. + * + * All inodes must have the ILOCK held, and both entries must already exist. + */ +int +xfs_dir_exchange( + struct xfs_trans *tp, + struct xfs_inode *dp1, + struct xfs_name *name1, + struct xfs_inode *ip1, + struct xfs_inode *dp2, + struct xfs_name *name2, + struct xfs_inode *ip2, + unsigned int spaceres) +{ + int ip1_flags = 0; + int ip2_flags = 0; + int dp2_flags = 0; + int error; + + /* Swap inode number for dirent in first parent */ + error = xfs_dir_replace(tp, dp1, name1, ip2->i_ino, spaceres); + if (error) + return error; + + /* Swap inode number for dirent in second parent */ + error = xfs_dir_replace(tp, dp2, name2, ip1->i_ino, spaceres); + if (error) + return error; + + /* + * If we're renaming one or more directories across different parents, + * update the respective ".." entries (and link counts) to match the new + * parents. + */ + if (dp1 != dp2) { + dp2_flags = XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG; + + if (S_ISDIR(VFS_I(ip2)->i_mode)) { + error = xfs_dir_replace(tp, ip2, &xfs_name_dotdot, + dp1->i_ino, spaceres); + if (error) + return error; + + /* transfer ip2 ".." reference to dp1 */ + if (!S_ISDIR(VFS_I(ip1)->i_mode)) { + error = xfs_droplink(tp, dp2); + if (error) + return error; + xfs_bumplink(tp, dp1); + } + + /* + * Although ip1 isn't changed here, userspace needs + * to be warned about the change, so that applications + * relying on it (like backup ones), will properly + * notify the change + */ + ip1_flags |= XFS_ICHGTIME_CHG; + ip2_flags |= XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG; + } + + if (S_ISDIR(VFS_I(ip1)->i_mode)) { + error = xfs_dir_replace(tp, ip1, &xfs_name_dotdot, + dp2->i_ino, spaceres); + if (error) + return error; + + /* transfer ip1 ".." reference to dp2 */ + if (!S_ISDIR(VFS_I(ip2)->i_mode)) { + error = xfs_droplink(tp, dp1); + if (error) + return error; + xfs_bumplink(tp, dp2); + } + + /* + * Although ip2 isn't changed here, userspace needs + * to be warned about the change, so that applications + * relying on it (like backup ones), will properly + * notify the change + */ + ip1_flags |= XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG; + ip2_flags |= XFS_ICHGTIME_CHG; + } + } + + if (ip1_flags) { + xfs_trans_ichgtime(tp, ip1, ip1_flags); + xfs_trans_log_inode(tp, ip1, XFS_ILOG_CORE); + } + if (ip2_flags) { + xfs_trans_ichgtime(tp, ip2, ip2_flags); + xfs_trans_log_inode(tp, ip2, XFS_ILOG_CORE); + } + if (dp2_flags) { + xfs_trans_ichgtime(tp, dp2, dp2_flags); + xfs_trans_log_inode(tp, dp2, XFS_ILOG_CORE); + } + xfs_trans_ichgtime(tp, dp1, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); + xfs_trans_log_inode(tp, dp1, XFS_ILOG_CORE); + + return 0; +} diff --git a/fs/xfs/libxfs/xfs_dir2.h b/fs/xfs/libxfs/xfs_dir2.h index e35deb273d84..f63390236f09 100644 --- a/fs/xfs/libxfs/xfs_dir2.h +++ b/fs/xfs/libxfs/xfs_dir2.h @@ -262,5 +262,9 @@ int xfs_dir_link_existing_child(struct xfs_trans *tp, uint resblks, int xfs_dir_remove_child(struct xfs_trans *tp, uint resblks, struct xfs_inode *dp, struct xfs_name *name, struct xfs_inode *ip); +int xfs_dir_exchange(struct xfs_trans *tp, struct xfs_inode *dp1, + struct xfs_name *name1, struct xfs_inode *ip1, + struct xfs_inode *dp2, struct xfs_name *name2, + struct xfs_inode *ip2, unsigned int spaceres); #endif /* __XFS_DIR2_H__ */ diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index f2a5de0119b3..591721755b78 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -2207,93 +2207,13 @@ xfs_cross_rename( struct xfs_inode *ip2, int spaceres) { - int error = 0; - int ip1_flags = 0; - int ip2_flags = 0; - int dp2_flags = 0; + int error; - /* Swap inode number for dirent in first parent */ - error = xfs_dir_replace(tp, dp1, name1, ip2->i_ino, spaceres); + error = xfs_dir_exchange(tp, dp1, name1, ip1, dp2, name2, ip2, + spaceres); if (error) goto out_trans_abort; - /* Swap inode number for dirent in second parent */ - error = xfs_dir_replace(tp, dp2, name2, ip1->i_ino, spaceres); - if (error) - goto out_trans_abort; - - /* - * If we're renaming one or more directories across different parents, - * update the respective ".." entries (and link counts) to match the new - * parents. - */ - if (dp1 != dp2) { - dp2_flags = XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG; - - if (S_ISDIR(VFS_I(ip2)->i_mode)) { - error = xfs_dir_replace(tp, ip2, &xfs_name_dotdot, - dp1->i_ino, spaceres); - if (error) - goto out_trans_abort; - - /* transfer ip2 ".." reference to dp1 */ - if (!S_ISDIR(VFS_I(ip1)->i_mode)) { - error = xfs_droplink(tp, dp2); - if (error) - goto out_trans_abort; - xfs_bumplink(tp, dp1); - } - - /* - * Although ip1 isn't changed here, userspace needs - * to be warned about the change, so that applications - * relying on it (like backup ones), will properly - * notify the change - */ - ip1_flags |= XFS_ICHGTIME_CHG; - ip2_flags |= XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG; - } - - if (S_ISDIR(VFS_I(ip1)->i_mode)) { - error = xfs_dir_replace(tp, ip1, &xfs_name_dotdot, - dp2->i_ino, spaceres); - if (error) - goto out_trans_abort; - - /* transfer ip1 ".." reference to dp2 */ - if (!S_ISDIR(VFS_I(ip2)->i_mode)) { - error = xfs_droplink(tp, dp1); - if (error) - goto out_trans_abort; - xfs_bumplink(tp, dp2); - } - - /* - * Although ip2 isn't changed here, userspace needs - * to be warned about the change, so that applications - * relying on it (like backup ones), will properly - * notify the change - */ - ip1_flags |= XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG; - ip2_flags |= XFS_ICHGTIME_CHG; - } - } - - if (ip1_flags) { - xfs_trans_ichgtime(tp, ip1, ip1_flags); - xfs_trans_log_inode(tp, ip1, XFS_ILOG_CORE); - } - if (ip2_flags) { - xfs_trans_ichgtime(tp, ip2, ip2_flags); - xfs_trans_log_inode(tp, ip2, XFS_ILOG_CORE); - } - if (dp2_flags) { - xfs_trans_ichgtime(tp, dp2, dp2_flags); - xfs_trans_log_inode(tp, dp2, XFS_ILOG_CORE); - } - xfs_trans_ichgtime(tp, dp1, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); - xfs_trans_log_inode(tp, dp1, XFS_ILOG_CORE); - if (xfs_hooks_switched_on(&xfs_nlinks_hooks_switch)) xfs_rename_call_nlink_hooks(dp1, name1, ip1, dp2, name2, ip2, NULL, RENAME_EXCHANGE); From patchwork Fri Dec 30 22:17:21 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13085362 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 371BEC4332F for ; Sat, 31 Dec 2022 01:10:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236011AbiLaBKJ (ORCPT ); Fri, 30 Dec 2022 20:10:09 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41874 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236013AbiLaBKI (ORCPT ); Fri, 30 Dec 2022 20:10:08 -0500 Received: from ams.source.kernel.org (ams.source.kernel.org [145.40.68.75]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 24E8718B37 for ; Fri, 30 Dec 2022 17:10:07 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id AA619B81DCA for ; Sat, 31 Dec 2022 01:10:05 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 64474C433EF; Sat, 31 Dec 2022 01:10:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1672449004; bh=GiSLFhkUD8jfo9UCzouRNsoX/x/YcJpoCtTOFHc5+NU=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=T2R+q6bBk+s+KLZXEoVOGs/bxVzAUTu7/OAthqaYnzsBaMnbwYFzAOGd6bGiKeuu1 lFIssz8ROmohAyFCoFjNhjEADzr9q3aDcqwY4rQrC41g5t2sRT6tvog7eNpwkSilwW 2yycW1mFo0tj1B/Hp1+CsnG59+47pCC54q6wF9x4lpzIrieH04XGJsBPbSxp5GKFgC vAT7uv31eTLTwBwQpXc36Tl2mY7ZFbg198hXw/XmpYNQ27/BgvENrC8g9EEKWezleV baKowRf29pFyqICppyijareURyi78JR5a/fsa71nNttNChVzEQkSehp/jN4sRKZOot F/i8d23S+/T6w== Subject: [PATCH 19/20] xfs: create libxfs helper to rename two directory entries From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Date: Fri, 30 Dec 2022 14:17:21 -0800 Message-ID: <167243864103.707335.9081114896106292572.stgit@magnolia> In-Reply-To: <167243863809.707335.15895322495460356300.stgit@magnolia> References: <167243863809.707335.15895322495460356300.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Create a new libxfs function to rename two directory entries. The upcoming metadata directory feature will need this to replace a metadata inode directory entry. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_dir2.c | 203 ++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_dir2.h | 5 + fs/xfs/xfs_inode.c | 177 ++-------------------------------------- 3 files changed, 218 insertions(+), 167 deletions(-) diff --git a/fs/xfs/libxfs/xfs_dir2.c b/fs/xfs/libxfs/xfs_dir2.c index 6d7851a613e7..e8f4a84a97c8 100644 --- a/fs/xfs/libxfs/xfs_dir2.c +++ b/fs/xfs/libxfs/xfs_dir2.c @@ -22,6 +22,7 @@ #include "xfs_bmap_btree.h" #include "xfs_trans_space.h" #include "xfs_ag.h" +#include "xfs_ialloc.h" const struct xfs_name xfs_name_dotdot = { .name = (const unsigned char *)"..", @@ -1057,3 +1058,205 @@ xfs_dir_exchange( return 0; } + +/* + * Given an entry (@src_name, @src_ip) in directory @src_dp, make the entry + * @target_name in directory @target_dp point to @src_ip and remove the + * original entry, cleaning up everything left behind. + * + * Cleanup involves dropping a link count on @target_ip, and either removing + * the (@src_name, @src_ip) entry from @src_dp or simply replacing the entry + * with (@src_name, @wip) if a whiteout inode @wip is supplied. + * + * All inodes must have the ILOCK held. We assume that if @src_ip is a + * directory then its '..' doesn't already point to @target_dp, and that @wip + * is a freshly allocated whiteout. + */ +int +xfs_dir_rename( + struct xfs_trans *tp, + struct xfs_inode *src_dp, + struct xfs_name *src_name, + struct xfs_inode *src_ip, + struct xfs_inode *target_dp, + struct xfs_name *target_name, + struct xfs_inode *target_ip, + unsigned int spaceres, + struct xfs_inode *wip) +{ + struct xfs_mount *mp = tp->t_mountp; + bool new_parent = (src_dp != target_dp); + bool src_is_directory; + int error; + + src_is_directory = S_ISDIR(VFS_I(src_ip)->i_mode); + + /* + * Check for expected errors before we dirty the transaction + * so we can return an error without a transaction abort. + */ + if (target_ip == NULL) { + /* + * If there's no space reservation, check the entry will + * fit before actually inserting it. + */ + if (!spaceres) { + error = xfs_dir_canenter(tp, target_dp, target_name); + if (error) + return error; + } + } else { + /* + * If target exists and it's a directory, check that whether + * it can be destroyed. + */ + if (S_ISDIR(VFS_I(target_ip)->i_mode) && + (!xfs_dir_isempty(target_ip) || + (VFS_I(target_ip)->i_nlink > 2))) + return -EEXIST; + } + + /* + * Directory entry creation below may acquire the AGF. Remove + * the whiteout from the unlinked list first to preserve correct + * AGI/AGF locking order. This dirties the transaction so failures + * after this point will abort and log recovery will clean up the + * mess. + * + * For whiteouts, we need to bump the link count on the whiteout + * inode. After this point, we have a real link, clear the tmpfile + * state flag from the inode so it doesn't accidentally get misused + * in future. + */ + if (wip) { + struct xfs_perag *pag; + + ASSERT(VFS_I(wip)->i_nlink == 0); + + pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, wip->i_ino)); + error = xfs_iunlink_remove(tp, pag, wip); + xfs_perag_put(pag); + if (error) + return error; + + xfs_bumplink(tp, wip); + } + + /* + * Set up the target. + */ + if (target_ip == NULL) { + /* + * If target does not exist and the rename crosses + * directories, adjust the target directory link count + * to account for the ".." reference from the new entry. + */ + error = xfs_dir_createname(tp, target_dp, target_name, + src_ip->i_ino, spaceres); + if (error) + return error; + + xfs_trans_ichgtime(tp, target_dp, + XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); + + if (new_parent && src_is_directory) { + xfs_bumplink(tp, target_dp); + } + } else { /* target_ip != NULL */ + /* + * Link the source inode under the target name. + * If the source inode is a directory and we are moving + * it across directories, its ".." entry will be + * inconsistent until we replace that down below. + * + * In case there is already an entry with the same + * name at the destination directory, remove it first. + */ + error = xfs_dir_replace(tp, target_dp, target_name, + src_ip->i_ino, spaceres); + if (error) + return error; + + xfs_trans_ichgtime(tp, target_dp, + XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); + + /* + * Decrement the link count on the target since the target + * dir no longer points to it. + */ + error = xfs_droplink(tp, target_ip); + if (error) + return error; + + if (src_is_directory) { + /* + * Drop the link from the old "." entry. + */ + error = xfs_droplink(tp, target_ip); + if (error) + return error; + } + } /* target_ip != NULL */ + + /* + * Remove the source. + */ + if (new_parent && src_is_directory) { + /* + * Rewrite the ".." entry to point to the new + * directory. + */ + error = xfs_dir_replace(tp, src_ip, &xfs_name_dotdot, + target_dp->i_ino, spaceres); + ASSERT(error != -EEXIST); + if (error) + return error; + } + + /* + * We always want to hit the ctime on the source inode. + * + * This isn't strictly required by the standards since the source + * inode isn't really being changed, but old unix file systems did + * it and some incremental backup programs won't work without it. + */ + xfs_trans_ichgtime(tp, src_ip, XFS_ICHGTIME_CHG); + xfs_trans_log_inode(tp, src_ip, XFS_ILOG_CORE); + + /* + * Adjust the link count on src_dp. This is necessary when + * renaming a directory, either within one parent when + * the target existed, or across two parent directories. + */ + if (src_is_directory && (new_parent || target_ip != NULL)) { + + /* + * Decrement link count on src_directory since the + * entry that's moved no longer points to it. + */ + error = xfs_droplink(tp, src_dp); + if (error) + return error; + } + + /* + * For whiteouts, we only need to update the source dirent with the + * inode number of the whiteout inode rather than removing it + * altogether. + */ + if (wip) + error = xfs_dir_replace(tp, src_dp, src_name, wip->i_ino, + spaceres); + else + error = xfs_dir_removename(tp, src_dp, src_name, src_ip->i_ino, + spaceres); + if (error) + return error; + + xfs_trans_ichgtime(tp, src_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); + xfs_trans_log_inode(tp, src_dp, XFS_ILOG_CORE); + if (new_parent) + xfs_trans_log_inode(tp, target_dp, XFS_ILOG_CORE); + + return 0; +} diff --git a/fs/xfs/libxfs/xfs_dir2.h b/fs/xfs/libxfs/xfs_dir2.h index f63390236f09..00b4642bc8a8 100644 --- a/fs/xfs/libxfs/xfs_dir2.h +++ b/fs/xfs/libxfs/xfs_dir2.h @@ -266,5 +266,10 @@ int xfs_dir_exchange(struct xfs_trans *tp, struct xfs_inode *dp1, struct xfs_name *name1, struct xfs_inode *ip1, struct xfs_inode *dp2, struct xfs_name *name2, struct xfs_inode *ip2, unsigned int spaceres); +int xfs_dir_rename(struct xfs_trans *tp, struct xfs_inode *src_dp, + struct xfs_name *src_name, struct xfs_inode *src_ip, + struct xfs_inode *target_dp, struct xfs_name *target_name, + struct xfs_inode *target_ip, unsigned int spaceres, + struct xfs_inode *wip); #endif /* __XFS_DIR2_H__ */ diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 591721755b78..4b9d680c5268 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -2408,33 +2408,6 @@ xfs_rename( goto out_trans_cancel; } - /* - * Check for expected errors before we dirty the transaction - * so we can return an error without a transaction abort. - */ - if (target_ip == NULL) { - /* - * If there's no space reservation, check the entry will - * fit before actually inserting it. - */ - if (!spaceres) { - error = xfs_dir_canenter(tp, target_dp, target_name); - if (error) - goto out_trans_cancel; - } - } else { - /* - * If target exists and it's a directory, check that whether - * it can be destroyed. - */ - if (S_ISDIR(VFS_I(target_ip)->i_mode) && - (!xfs_dir_isempty(target_ip) || - (VFS_I(target_ip)->i_nlink > 2))) { - error = -EEXIST; - goto out_trans_cancel; - } - } - /* * Lock the AGI buffers we need to handle bumping the nlink of the * whiteout inode off the unlinked list and to handle dropping the @@ -2461,150 +2434,20 @@ xfs_rename( } } - /* - * Directory entry creation below may acquire the AGF. Remove - * the whiteout from the unlinked list first to preserve correct - * AGI/AGF locking order. This dirties the transaction so failures - * after this point will abort and log recovery will clean up the - * mess. - * - * For whiteouts, we need to bump the link count on the whiteout - * inode. After this point, we have a real link, clear the tmpfile - * state flag from the inode so it doesn't accidentally get misused - * in future. - */ + error = xfs_dir_rename(tp, src_dp, src_name, src_ip, target_dp, + target_name, target_ip, spaceres, wip); + if (error) + goto out_trans_cancel; + if (wip) { - struct xfs_perag *pag; - - ASSERT(VFS_I(wip)->i_nlink == 0); - - pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, wip->i_ino)); - error = xfs_iunlink_remove(tp, pag, wip); - xfs_perag_put(pag); - if (error) - goto out_trans_cancel; - - xfs_bumplink(tp, wip); + /* + * Now we have a real link, clear the "I'm a tmpfile" state + * flag from the inode so it doesn't accidentally get misused in + * future. + */ VFS_I(wip)->i_state &= ~I_LINKABLE; } - /* - * Set up the target. - */ - if (target_ip == NULL) { - /* - * If target does not exist and the rename crosses - * directories, adjust the target directory link count - * to account for the ".." reference from the new entry. - */ - error = xfs_dir_createname(tp, target_dp, target_name, - src_ip->i_ino, spaceres); - if (error) - goto out_trans_cancel; - - xfs_trans_ichgtime(tp, target_dp, - XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); - - if (new_parent && src_is_directory) { - xfs_bumplink(tp, target_dp); - } - } else { /* target_ip != NULL */ - /* - * Link the source inode under the target name. - * If the source inode is a directory and we are moving - * it across directories, its ".." entry will be - * inconsistent until we replace that down below. - * - * In case there is already an entry with the same - * name at the destination directory, remove it first. - */ - error = xfs_dir_replace(tp, target_dp, target_name, - src_ip->i_ino, spaceres); - if (error) - goto out_trans_cancel; - - xfs_trans_ichgtime(tp, target_dp, - XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); - - /* - * Decrement the link count on the target since the target - * dir no longer points to it. - */ - error = xfs_droplink(tp, target_ip); - if (error) - goto out_trans_cancel; - - if (src_is_directory) { - /* - * Drop the link from the old "." entry. - */ - error = xfs_droplink(tp, target_ip); - if (error) - goto out_trans_cancel; - } - } /* target_ip != NULL */ - - /* - * Remove the source. - */ - if (new_parent && src_is_directory) { - /* - * Rewrite the ".." entry to point to the new - * directory. - */ - error = xfs_dir_replace(tp, src_ip, &xfs_name_dotdot, - target_dp->i_ino, spaceres); - ASSERT(error != -EEXIST); - if (error) - goto out_trans_cancel; - } - - /* - * We always want to hit the ctime on the source inode. - * - * This isn't strictly required by the standards since the source - * inode isn't really being changed, but old unix file systems did - * it and some incremental backup programs won't work without it. - */ - xfs_trans_ichgtime(tp, src_ip, XFS_ICHGTIME_CHG); - xfs_trans_log_inode(tp, src_ip, XFS_ILOG_CORE); - - /* - * Adjust the link count on src_dp. This is necessary when - * renaming a directory, either within one parent when - * the target existed, or across two parent directories. - */ - if (src_is_directory && (new_parent || target_ip != NULL)) { - - /* - * Decrement link count on src_directory since the - * entry that's moved no longer points to it. - */ - error = xfs_droplink(tp, src_dp); - if (error) - goto out_trans_cancel; - } - - /* - * For whiteouts, we only need to update the source dirent with the - * inode number of the whiteout inode rather than removing it - * altogether. - */ - if (wip) - error = xfs_dir_replace(tp, src_dp, src_name, wip->i_ino, - spaceres); - else - error = xfs_dir_removename(tp, src_dp, src_name, src_ip->i_ino, - spaceres); - - if (error) - goto out_trans_cancel; - - xfs_trans_ichgtime(tp, src_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); - xfs_trans_log_inode(tp, src_dp, XFS_ILOG_CORE); - if (new_parent) - xfs_trans_log_inode(tp, target_dp, XFS_ILOG_CORE); - if (xfs_hooks_switched_on(&xfs_nlinks_hooks_switch)) xfs_rename_call_nlink_hooks(src_dp, src_name, src_ip, target_dp, target_name, target_ip, wip, flags); From patchwork Fri Dec 30 22:17:21 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13085363 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 5E571C4332F for ; Sat, 31 Dec 2022 01:10:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236012AbiLaBKZ (ORCPT ); Fri, 30 Dec 2022 20:10:25 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41914 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235827AbiLaBKY (ORCPT ); Fri, 30 Dec 2022 20:10:24 -0500 Received: from sin.source.kernel.org (sin.source.kernel.org [145.40.73.55]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7387C18B37 for ; Fri, 30 Dec 2022 17:10:23 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sin.source.kernel.org (Postfix) with ESMTPS id E240ACE191A for ; Sat, 31 Dec 2022 01:10:21 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 25A6EC433EF; Sat, 31 Dec 2022 01:10:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1672449020; bh=jHlFA9s9JXdSIWR6E/qDBVglOEPIyp440wxiLt2Hs9s=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=jE4XNcdgJm0/5NgeUK42iwIPP9aAWmIzqMITDkgMllfIyKYyj6+iuh13NdBZgZGcv 0+7TqK36H2Cf6ZemZKIk7chgolAhqRpnKioYk1P/LGyEVrl70nYIoodHEWMVp6++Fr r0CFPOcAUsThRRIHVic+ECOC02YsJD0shIbes6aJcmZf8qi2VXzkiBs4pR4cBkXwoZ Br4ZGri9myvLQjC7J2oFl9vLp9fpl6cCTgwHN2SZdOcax27dIo7ArCmQBWE4zhYi+0 9RC9seDPFvRZbKkjtpp8ugJ6+0qjRH6crhPQxEz7LmSJvbJC4xpH+nrbyHuEF9UpCx CPjzLHQVmiMyQ== Subject: [PATCH 20/20] xfs: get rid of cross_rename From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Date: Fri, 30 Dec 2022 14:17:21 -0800 Message-ID: <167243864118.707335.4987942983753574680.stgit@magnolia> In-Reply-To: <167243863809.707335.15895322495460356300.stgit@magnolia> References: <167243863809.707335.15895322495460356300.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Get rid of the largely pointless xfs_cross_rename now that we've refactored its parent. Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_inode.c | 72 +++++++++++----------------------------------------- 1 file changed, 15 insertions(+), 57 deletions(-) diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 4b9d680c5268..fdd5e5c89e62 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -2177,54 +2177,6 @@ xfs_rename_call_nlink_hooks( ((void)0) #endif /* CONFIG_XFS_LIVE_HOOKS */ -static int -xfs_finish_rename( - struct xfs_trans *tp) -{ - /* - * If this is a synchronous mount, make sure that the rename transaction - * goes to disk before returning to the user. - */ - if (xfs_has_wsync(tp->t_mountp) || xfs_has_dirsync(tp->t_mountp)) - xfs_trans_set_sync(tp); - - return xfs_trans_commit(tp); -} - -/* - * xfs_cross_rename() - * - * responsible for handling RENAME_EXCHANGE flag in renameat2() syscall - */ -STATIC int -xfs_cross_rename( - struct xfs_trans *tp, - struct xfs_inode *dp1, - struct xfs_name *name1, - struct xfs_inode *ip1, - struct xfs_inode *dp2, - struct xfs_name *name2, - struct xfs_inode *ip2, - int spaceres) -{ - int error; - - error = xfs_dir_exchange(tp, dp1, name1, ip1, dp2, name2, ip2, - spaceres); - if (error) - goto out_trans_abort; - - if (xfs_hooks_switched_on(&xfs_nlinks_hooks_switch)) - xfs_rename_call_nlink_hooks(dp1, name1, ip1, dp2, name2, ip2, - NULL, RENAME_EXCHANGE); - - return xfs_finish_rename(tp); - -out_trans_abort: - xfs_trans_cancel(tp); - return error; -} - /* * xfs_rename_alloc_whiteout() * @@ -2377,12 +2329,6 @@ xfs_rename( goto out_trans_cancel; } - /* RENAME_EXCHANGE is unique from here on. */ - if (flags & RENAME_EXCHANGE) - return xfs_cross_rename(tp, src_dp, src_name, src_ip, - target_dp, target_name, target_ip, - spaceres); - /* * Try to reserve quota to handle an expansion of the target directory. * We'll allow the rename to continue in reservationless mode if we hit @@ -2434,8 +2380,13 @@ xfs_rename( } } - error = xfs_dir_rename(tp, src_dp, src_name, src_ip, target_dp, - target_name, target_ip, spaceres, wip); + if (flags & RENAME_EXCHANGE) + error = xfs_dir_exchange(tp, src_dp, src_name, src_ip, + target_dp, target_name, target_ip, spaceres); + else + error = xfs_dir_rename(tp, src_dp, src_name, src_ip, + target_dp, target_name, target_ip, spaceres, + wip); if (error) goto out_trans_cancel; @@ -2452,7 +2403,14 @@ xfs_rename( xfs_rename_call_nlink_hooks(src_dp, src_name, src_ip, target_dp, target_name, target_ip, wip, flags); - error = xfs_finish_rename(tp); + /* + * If this is a synchronous mount, make sure that the rename + * transaction goes to disk before returning to the user. + */ + if (xfs_has_wsync(tp->t_mountp) || xfs_has_dirsync(tp->t_mountp)) + xfs_trans_set_sync(tp); + + error = xfs_trans_commit(tp); if (wip) xfs_irele(wip); return error;