From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 75E061FCFF8; Thu, 17 Jul 2025 23:40:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752795609; cv=none; b=Cqwjz8O5VqG5eFh8EzmfW+X8KTAB83kHfrbXh2FwEmMnPuNwNwbCh2c1kgKN1g14Nri75Lop1AG/e0B8SBL1WFWhnS8hUZ0mc8lthuSlpdXCs+VMLUuP+VQlFNJ1j0wogDD2Kz5k+5g6IQrmu2f//BXS75X+rKbQKlrAr/T6bPM= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752795609; c=relaxed/simple; bh=MlTueowV7K2ntrQgiZ3XflCleWaN6u2gBJJ1kb1m/MI=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=bcKF/C7gtfhk2A7YFT3k9rsDDCnlMTH6TA37qD8zkh2JSH+ukEpZUzoD7HvpRLWw0hoBzi3P1wHNo9Px8bmgYS/IsbkQuqHXSzS2DRfTvcgtHS3I+7eNZ7JZjEh2nR36xiyb4sQKJY0HWJcvvNHomJicQWJiBM3lmiQq1R94V90= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=XSA89//V; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="XSA89//V" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4CA94C4CEE3; Thu, 17 Jul 2025 23:40:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1752795609; bh=MlTueowV7K2ntrQgiZ3XflCleWaN6u2gBJJ1kb1m/MI=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=XSA89//V8voQrTB2/pk6OXrcS8FlzXH3PuSiMHFai1ZUFmfB3VfGPMyJ/Yzk6wfRc vtbh0928QulAVWOdmAGmxF0fpnmsNhNkULM1gyb+uHT/mOdtk3Re8B+Ypd/uZ3vra1 OV4lbDKdMdl23QFUbOBgFz1I8ZOLD8HIZDu87mCZX6ULzr78RHa4WM2DD7RNI8PP4O 0MyLLJktLhJH+MDlXxeE9KmzBcSEuNBdNA1ewSjQo6SeIO74Vqh+FI1o7dwXx7qTm7 7ipBvMejsr1nt9Bil3cJ5vhp8psMP6iAvWZvLE/b8bNXJNGZpmRHJV5i+QAnkuRki0 7wdgcnHUzZsHg== Date: Thu, 17 Jul 2025 16:40:08 -0700 Subject: [PATCH 03/22] fuse2fs: implement iomap configuration From: "Darrick J. Wong" To: tytso@mit.edu Cc: joannelkoong@gmail.com, miklos@szeredi.hu, John@groves.net, linux-fsdevel@vger.kernel.org, bernd@bsbernd.com, linux-ext4@vger.kernel.org, neal@gompa.dev Message-ID: <175279461087.715479.14356495453151928971.stgit@frogsfrogsfrogs> In-Reply-To: <175279460935.715479.15460687085573767955.stgit@frogsfrogsfrogs> References: <175279460935.715479.15460687085573767955.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit From: Darrick J. Wong Upload the filesystem geometry to the kernel when asked. Signed-off-by: "Darrick J. Wong" --- misc/fuse2fs.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 93 insertions(+), 3 deletions(-) diff --git a/misc/fuse2fs.c b/misc/fuse2fs.c index d4912dee08d43f..fb71886b58f215 100644 --- a/misc/fuse2fs.c +++ b/misc/fuse2fs.c @@ -194,6 +194,10 @@ static inline uint64_t round_down(uint64_t b, unsigned int align) # define FL_ZERO_RANGE_FLAG (0) #endif +#ifndef NSEC_PER_SEC +# define NSEC_PER_SEC (1000000000L) +#endif + errcode_t ext2fs_run_ext3_journal(ext2_filsys *fs); const char *err_shortdev; @@ -575,9 +579,9 @@ static int update_atime(ext2_filsys fs, ext2_ino_t ino) EXT4_INODE_GET_XTIME(i_mtime, &mtime, pinode); get_now(&now); - datime = atime.tv_sec + ((double)atime.tv_nsec / 1000000000); - dmtime = mtime.tv_sec + ((double)mtime.tv_nsec / 1000000000); - dnow = now.tv_sec + ((double)now.tv_nsec / 1000000000); + datime = atime.tv_sec + ((double)atime.tv_nsec / NSEC_PER_SEC); + dmtime = mtime.tv_sec + ((double)mtime.tv_nsec / NSEC_PER_SEC); + dnow = now.tv_sec + ((double)now.tv_nsec / NSEC_PER_SEC); /* * If atime is newer than mtime and atime hasn't been updated in thirty @@ -5228,6 +5232,91 @@ static int op_iomap_end(const char *path, uint64_t nodeid, uint64_t attr_ino, return 0; } + +/* + * Maximal extent format file size. + * Resulting logical blkno at s_maxbytes must fit in our on-disk + * extent format containers, within a sector_t, and within i_blocks + * in the vfs. ext4 inode has 48 bits of i_block in fsblock units, + * so that won't be a limiting factor. + * + * However there is other limiting factor. We do store extents in the form + * of starting block and length, hence the resulting length of the extent + * covering maximum file size must fit into on-disk format containers as + * well. Given that length is always by 1 unit bigger than max unit (because + * we count 0 as well) we have to lower the s_maxbytes by one fs block. + * + * Note, this does *not* consider any metadata overhead for vfs i_blocks. + */ +static off_t fuse2fs_max_size(struct fuse2fs *ff, off_t upper_limit) +{ + off_t res; + + if (!ext2fs_has_feature_huge_file(ff->fs->super)) { + upper_limit = (1LL << 32) - 1; + + /* total blocks in file system block size */ + upper_limit >>= (ff->blocklog - 9); + upper_limit <<= ff->blocklog; + } + + /* + * 32-bit extent-start container, ee_block. We lower the maxbytes + * by one fs block, so ee_len can cover the extent of maximum file + * size + */ + res = (1LL << 32) - 1; + res <<= ff->blocklog; + + /* Sanity check against vm- & vfs- imposed limits */ + if (res > upper_limit) + res = upper_limit; + + return res; +} + +static int op_iomap_config(uint32_t flags, off_t maxbytes, + struct fuse_iomap_config *cfg) +{ + struct fuse_context *ctxt = fuse_get_context(); + struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data; + ext2_filsys fs; + + FUSE2FS_CHECK_CONTEXT(ff); + + dbg_printf(ff, "%s: flags=0x%x maxbytes=0x%llx\n", __func__, flags, + (long long)maxbytes); + fs = fuse2fs_start(ff); + + cfg->flags |= FUSE_IOMAP_CONFIG_UUID; + memcpy(cfg->s_uuid, fs->super->s_uuid, sizeof(cfg->s_uuid)); + cfg->s_uuid_len = sizeof(fs->super->s_uuid); + + cfg->flags |= FUSE_IOMAP_CONFIG_BLOCKSIZE; + cfg->s_blocksize = FUSE2FS_FSB_TO_B(ff, 1); + + /* + * If there inode is large enough to house i_[acm]time_extra then we + * can turn on nanosecond timestamps; i_crtime was the next field added + * after i_atime_extra. + */ + cfg->flags |= FUSE_IOMAP_CONFIG_TIME; + if (fs->super->s_inode_size >= + offsetof(struct ext2_inode_large, i_crtime)) { + cfg->s_time_gran = 1; + cfg->s_time_max = EXT4_EXTRA_TIMESTAMP_MAX; + } else { + cfg->s_time_gran = NSEC_PER_SEC; + cfg->s_time_max = EXT4_NON_EXTRA_TIMESTAMP_MAX; + } + cfg->s_time_min = EXT4_TIMESTAMP_MIN; + + cfg->flags |= FUSE_IOMAP_CONFIG_MAXBYTES; + cfg->s_maxbytes = fuse2fs_max_size(ff, maxbytes); + + fuse2fs_finish(ff, 0); + return 0; +} #endif /* HAVE_FUSE_IOMAP */ static struct fuse_operations fs_ops = { @@ -5293,6 +5382,7 @@ static struct fuse_operations fs_ops = { #ifdef HAVE_FUSE_IOMAP .iomap_begin = op_iomap_begin, .iomap_end = op_iomap_end, + .iomap_config = op_iomap_config, #endif /* HAVE_FUSE_IOMAP */ };