Re: [PATCH v2] ceph: remove the inline data support

Viacheslav Dubeyko <[email protected]> Wed, 29 Jul 2026 17:44:29 -0700
Newsgroups org.kernel.vger.ceph-devel,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
On Wed, 2026-07-29 at 09:28 +0800, Xiubo Li via B4 Relay wrote:
> From: Xiubo Li <[email protected]>
>=20
> Inline data support has been deprecated in the CephFS MDS and is
> being formally removed.=C2=A0 Existing inline data can be migrated to
> data pool objects via MDS scrub (see PR #44359).
>=20
> Add CONFIG_CEPH_FS_INLINE_DATA (default n) to gate all inline data
> code in the kclient.=C2=A0 When disabled, CEPH_FEATURE_MDS_INLINE_DATA
> is defined as 0 so that the kclient no longer advertises the
> feature to the MDS.=C2=A0 The MDS will then refuse to open files that
> still have inline data, returning -EPERM, preventing silent data
> corruption that would occur if the kclient tried to read inline
> data from OSD objects that do not contain it.
>=20
> This config option will be kept for a transitional period to
> allow existing CephFS deployments to migrate inline data via
> MDS scrub.=C2=A0 Once the migration period ends, the option and all
> inline data code will be permanently removed.
>=20
> Users upgrading from an older Ceph release should ensure all inline
> data has been migrated before deploying a kclient with this option
> disabled:
> =C2=A0 1. Enable and run MDS scrub to uninline existing data
> =C2=A0 2. Disable inline_data on the filesystem:
> =C2=A0=C2=A0=C2=A0=C2=A0 ceph fs set <fs> inline_data false --yes-i-reall=
y-really-mean-it
>=20
> Link: https://tracker-origin.ceph.com/issues/67769
> Signed-off-by: Xiubo Li <[email protected]>
> ---
> Changes in v2:
> - keep CEPH_FEATURE_MDS_INLINE_DATA always defined as (1ULL << 40)
> =C2=A0 so decode logic can still check MDS feature bits; gate the
> =C2=A0 supported features set via CEPH_FEATURE_MDS_INLINE_DATA_DEFAULT
> - Link to v1:
> https://patch.msgid.link/20260728-b4-ceph-remove-inline-data-v1-1-8ffa7e0=
[email protected]
> ---
> =C2=A0fs/ceph/Kconfig=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 | 12 ++++++=
++++++
> =C2=A0fs/ceph/addr.c=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 | 16 =
+++++++++++++++
> =C2=A0fs/ceph/caps.c=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 | 40
> +++++++++++++++++++++++++++++++++++++-
> =C2=A0fs/ceph/file.c=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 | 20 =
+++++++++++++++++++
> =C2=A0fs/ceph/inode.c=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 | 10 ++++++=
++++
> =C2=A0fs/ceph/mds_client.c=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 | 30 ++++++++++++++++++++++++++++
> =C2=A0fs/ceph/mds_client.h=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 |=C2=A0 2 ++
> =C2=A0fs/ceph/snap.c=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 |=C2=
=A0 2 ++
> =C2=A0fs/ceph/super.h=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 | 13 ++++++=
+++++++
> =C2=A0include/linux/ceph/ceph_features.h |=C2=A0 7 ++++++-
> =C2=A010 files changed, 150 insertions(+), 2 deletions(-)
>=20
> diff --git a/fs/ceph/Kconfig b/fs/ceph/Kconfig
> index 3d64a316ca31..be1c8ada5665 100644
> --- a/fs/ceph/Kconfig
> +++ b/fs/ceph/Kconfig
> @@ -17,6 +17,18 @@ config CEPH_FS
> =C2=A0	=C2=A0 If unsure, say N.
> =C2=A0
> =C2=A0if CEPH_FS
> +config CEPH_FS_INLINE_DATA
> +	bool "Enable CephFS inline data support (deprecated)"
> +	depends on CEPH_FS
> +	default n
> +	help
> +	=C2=A0 Inline data support has been deprecated in the CephFS MDS
> +	=C2=A0 and is being formally removed.=C2=A0 Existing inline data can
> be
> +	=C2=A0 migrated to data pool objects via MDS scrub.=C2=A0 Choose N
> +	=C2=A0 unless you have a legacy filesystem that requires it,
> +	=C2=A0 and ensure all inline data has been migrated (see
> +	=C2=A0 ceph fs set <fs> inline_data false) before enabling.
> +
> =C2=A0config CEPH_FSCACHE
> =C2=A0	bool "Enable Ceph client caching support"
> =C2=A0	depends on CEPH_FS=3Dm && FSCACHE || CEPH_FS=3Dy && FSCACHE=3Dy
> diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
> index e2da3ab9f808..5211320a50ac 100644
> --- a/fs/ceph/addr.c
> +++ b/fs/ceph/addr.c
> @@ -274,6 +274,7 @@ static void finish_netfs_read(struct
> ceph_osd_request *req)
> =C2=A0	ceph_dec_osd_stopping_blocker(fsc->mdsc);
> =C2=A0}
> =C2=A0
> +#ifdef CONFIG_CEPH_FS_INLINE_DATA
> =C2=A0static bool ceph_netfs_issue_op_inline(struct netfs_io_subrequest
> *subreq)
> =C2=A0{
> =C2=A0	struct netfs_io_request *rreq =3D subreq->rreq;
> @@ -335,6 +336,7 @@ static bool ceph_netfs_issue_op_inline(struct
> netfs_io_subrequest *subreq)
> =C2=A0	netfs_read_subreq_terminated(subreq);
> =C2=A0	return true;
> =C2=A0}
> +#endif /* CONFIG_CEPH_FS_INLINE_DATA */
> =C2=A0
> =C2=A0static int ceph_netfs_prepare_read(struct netfs_io_subrequest
> *subreq)
> =C2=A0{
> @@ -372,8 +374,10 @@ static void ceph_netfs_issue_read(struct
> netfs_io_subrequest *subreq)
> =C2=A0		goto out;
> =C2=A0	}
> =C2=A0
> +#ifdef CONFIG_CEPH_FS_INLINE_DATA
> =C2=A0	if (ceph_has_inline_data(ci) &&
> ceph_netfs_issue_op_inline(subreq))
> =C2=A0		return;
> +#endif
> =C2=A0
> =C2=A0	// TODO: This rounding here is slightly dodgy.=C2=A0 It *should*
> work, for
> =C2=A0	// now, as the cache only deals in blocks that are a
> multiple of
> @@ -2006,7 +2010,11 @@ static vm_fault_t ceph_filemap_fault(struct
> vm_fault *vmf)
> =C2=A0	=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 off, ceph_cap_string(got));
> =C2=A0
> =C2=A0	if ((got & (CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_LAZYIO)) ||
> +#ifdef CONFIG_CEPH_FS_INLINE_DATA
> =C2=A0	=C2=A0=C2=A0=C2=A0 !ceph_has_inline_data(ci)) {
> +#else
> +	=C2=A0=C2=A0=C2=A0 true) {
> +#endif

Maybe, some static inline function here?

> =C2=A0		CEPH_DEFINE_RW_CONTEXT(rw_ctx, got);
> =C2=A0		ceph_add_rw_context(fi, &rw_ctx);
> =C2=A0		ret =3D filemap_fault(vmf);
> @@ -2037,7 +2045,11 @@ static vm_fault_t ceph_filemap_fault(struct
> vm_fault *vmf)
> =C2=A0			goto out_inline;
> =C2=A0		}
> =C2=A0		err =3D __ceph_do_getattr(inode, page,
> +#ifdef CONFIG_CEPH_FS_INLINE_DATA
> =C2=A0					 CEPH_STAT_CAP_INLINE_DATA,
> true);
> +#else
> +					 0, true);
> +#endif

Maybe some macro that can hide this?

> =C2=A0		if (err < 0 || off >=3D i_size_read(inode)) {
> =C2=A0			unlock_page(page);
> =C2=A0			put_page(page);
> @@ -2168,6 +2180,7 @@ static vm_fault_t ceph_page_mkwrite(struct
> vm_fault *vmf)
> =C2=A0	return ret;
> =C2=A0}
> =C2=A0
> +#ifdef CONFIG_CEPH_FS_INLINE_DATA
> =C2=A0void ceph_fill_inline_data(struct inode *inode, struct page
> *locked_page,
> =C2=A0			=C2=A0=C2=A0 char	*data, size_t len)
> =C2=A0{
> @@ -2214,7 +2227,9 @@ void ceph_fill_inline_data(struct inode *inode,
> struct page *locked_page,
> =C2=A0		put_page(page);
> =C2=A0	}
> =C2=A0}
> +#endif /* CONFIG_CEPH_FS_INLINE_DATA */
> =C2=A0
> +#ifdef CONFIG_CEPH_FS_INLINE_DATA
> =C2=A0int ceph_uninline_data(struct file *file)
> =C2=A0{
> =C2=A0	struct inode *inode =3D file_inode(file);
> @@ -2370,6 +2385,7 @@ int ceph_uninline_data(struct file *file)
> =C2=A0	=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ceph_vinop(inode), inline_version, =
err);
> =C2=A0	return err;
> =C2=A0}
> +#endif /* CONFIG_CEPH_FS_INLINE_DATA */
> =C2=A0
> =C2=A0static const struct vm_operations_struct ceph_vmops =3D {
> =C2=A0	.fault		=3D ceph_filemap_fault,
> diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
> index f8d898ad091e..2fd2116a3308 100644
> --- a/fs/ceph/caps.c
> +++ b/fs/ceph/caps.c
> @@ -1266,7 +1266,9 @@ struct cap_msg_args {
> =C2=A0	kuid_t			uid;
> =C2=A0	kgid_t			gid;
> =C2=A0	umode_t			mode;
> +#ifdef CONFIG_CEPH_FS_INLINE_DATA
> =C2=A0	bool			inline_data;
> +#endif
> =C2=A0	bool			wake;
> =C2=A0	bool			encrypted;
> =C2=A0	u32			fscrypt_auth_len;
> @@ -1336,8 +1338,16 @@ static void encode_cap_msg(struct ceph_msg
> *msg, struct cap_msg_args *arg)
> =C2=A0	p =3D fc + 1;
> =C2=A0	/* flock buffer size (version 2) */
> =C2=A0	ceph_encode_32(&p, 0);
> -	/* inline version (version 4) */
> +#ifdef CONFIG_CEPH_FS_INLINE_DATA
> =C2=A0	ceph_encode_64(&p, arg->inline_data ? 0 : CEPH_INLINE_NONE);
> +#else
> +	/*
> +	 * Inline data support has been removed.=C2=A0 The field is still
> +	 * encoded for protocol compatibility; always advertise
> +	 * CEPH_INLINE_NONE to indicate no inline data is present.
> +	 */
> +	ceph_encode_64(&p, CEPH_INLINE_NONE);
> +#endif
> =C2=A0	/* inline data size */
> =C2=A0	ceph_encode_32(&p, 0);
> =C2=A0	/*
> @@ -1499,7 +1509,9 @@ static void __prep_cap(struct cap_msg_args
> *arg, struct ceph_cap *cap,
> =C2=A0	arg->gid =3D inode->i_gid;
> =C2=A0	arg->mode =3D inode->i_mode;
> =C2=A0
> +#ifdef CONFIG_CEPH_FS_INLINE_DATA
> =C2=A0	arg->inline_data =3D ci->i_inline_version !=3D CEPH_INLINE_NONE;
> +#endif
> =C2=A0	if (!(flags & CEPH_CLIENT_CAPS_PENDING_CAPSNAP) &&
> =C2=A0	=C2=A0=C2=A0=C2=A0 !list_empty(&ci->i_cap_snaps)) {
> =C2=A0		struct ceph_cap_snap *capsnap;
> @@ -1620,7 +1632,9 @@ static inline int __send_flush_snap(struct
> inode *inode,
> =C2=A0	arg.gid =3D capsnap->gid;
> =C2=A0	arg.mode =3D capsnap->mode;
> =C2=A0
> +#ifdef CONFIG_CEPH_FS_INLINE_DATA
> =C2=A0	arg.inline_data =3D capsnap->inline_data;
> +#endif
> =C2=A0	arg.flags =3D 0;
> =C2=A0	arg.wake =3D false;
> =C2=A0	arg.encrypted =3D IS_ENCRYPTED(inode);
> @@ -3192,6 +3206,7 @@ int __ceph_get_caps(struct inode *inode, struct
> ceph_file_info *fi, int need,
> =C2=A0			return ret;
> =C2=A0		}
> =C2=A0
> +#ifdef CONFIG_CEPH_FS_INLINE_DATA
> =C2=A0		if (S_ISREG(ci->netfs.inode.i_mode) &&
> =C2=A0		=C2=A0=C2=A0=C2=A0 ceph_has_inline_data(ci) &&
> =C2=A0		=C2=A0=C2=A0=C2=A0 (_got &
> (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)) &&
> @@ -3223,6 +3238,7 @@ int __ceph_get_caps(struct inode *inode, struct
> ceph_file_info *fi, int need,
> =C2=A0				return ret;
> =C2=A0			continue;
> =C2=A0		}
> +#endif

Ditto. Maybe, some static inline function?

> =C2=A0		break;
> =C2=A0	}
> =C2=A0	*got =3D _got;
> @@ -3518,10 +3534,12 @@ static void invalidate_aliases(struct inode
> *inode)
> =C2=A0
> =C2=A0struct cap_extra_info {
> =C2=A0	struct ceph_string *pool_ns;
> +#ifdef CONFIG_CEPH_FS_INLINE_DATA
> =C2=A0	/* inline data */
> =C2=A0	u64 inline_version;
> =C2=A0	void *inline_data;
> =C2=A0	u32 inline_len;
> +#endif
> =C2=A0	/* dirstat */
> =C2=A0	bool dirstat_valid;
> =C2=A0	u64 nfiles;
> @@ -3564,7 +3582,9 @@ static void handle_cap_grant(struct inode
> *inode,
> =C2=A0	bool queue_trunc =3D false;
> =C2=A0	bool queue_invalidate =3D false;
> =C2=A0	bool deleted_inode =3D false;
> +#ifdef CONFIG_CEPH_FS_INLINE_DATA
> =C2=A0	bool fill_inline =3D false;
> +#endif
> =C2=A0	bool revoke_wait =3D false;
> =C2=A0	int flags =3D 0;
> =C2=A0
> @@ -3830,6 +3850,7 @@ static void handle_cap_grant(struct inode
> *inode,
> =C2=A0			check_caps =3D 2; /* check all caps */
> =C2=A0	}
> =C2=A0
> +#ifdef CONFIG_CEPH_FS_INLINE_DATA
> =C2=A0	if (extra_info->inline_version > 0 &&
> =C2=A0	=C2=A0=C2=A0=C2=A0 extra_info->inline_version >=3D ci->i_inline_ve=
rsion) {
> =C2=A0		ci->i_inline_version =3D extra_info->inline_version;
> @@ -3837,6 +3858,7 @@ static void handle_cap_grant(struct inode
> *inode,
> =C2=A0		=C2=A0=C2=A0=C2=A0 (newcaps &
> (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)))
> =C2=A0			fill_inline =3D true;
> =C2=A0	}
> +#endif

Ditto.

> =C2=A0
> =C2=A0	if (le32_to_cpu(grant->op) =3D=3D CEPH_CAP_OP_IMPORT) {
> =C2=A0		if (ci->i_auth_cap =3D=3D cap) {
> @@ -3856,9 +3878,11 @@ static void handle_cap_grant(struct inode
> *inode,
> =C2=A0	}
> =C2=A0	spin_unlock(&ci->i_ceph_lock);
> =C2=A0
> +#ifdef CONFIG_CEPH_FS_INLINE_DATA
> =C2=A0	if (fill_inline)
> =C2=A0		ceph_fill_inline_data(inode, NULL, extra_info-
> >inline_data,
> =C2=A0				=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 extra_info->inline_len);
> +#endif
> =C2=A0
> =C2=A0	if (queue_trunc)
> =C2=A0		ceph_queue_vmtruncate(inode);
> @@ -4476,12 +4500,26 @@ void ceph_handle_caps(struct ceph_mds_session
> *session,
> =C2=A0	}
> =C2=A0
> =C2=A0	if (msg_version >=3D 4) {
> +#ifdef CONFIG_CEPH_FS_INLINE_DATA
> =C2=A0		ceph_decode_64_safe(&p, end,
> extra_info.inline_version, bad);
> =C2=A0		ceph_decode_32_safe(&p, end, extra_info.inline_len,
> bad);
> =C2=A0		if (p + extra_info.inline_len > end)
> =C2=A0			goto bad;
> =C2=A0		extra_info.inline_data =3D p;
> =C2=A0		p +=3D extra_info.inline_len;
> +#else
> +		/*
> +		 * Inline data support has been removed, but cap
> grant
> +		 * messages (msg_version >=3D 4) always carry
> inline_version
> +		 * + inline_data.=C2=A0 We must consume the fields to
> keep the
> +		 * decode pointer in sync.
> +		 */
> +		u32 __len;

The leading double-underscore is reserved namespace in C. Maybe, simply
len?

> +
> +		ceph_decode_skip_64(&p, end, bad);
> +		ceph_decode_32_safe(&p, end, __len, bad);
> +		ceph_decode_skip_n(&p, end, __len, bad);
> +#endif
> =C2=A0	}
> =C2=A0
> =C2=A0	if (msg_version >=3D 5) {
> diff --git a/fs/ceph/file.c b/fs/ceph/file.c
> index 3823671ab95a..901ed97b1963 100644
> --- a/fs/ceph/file.c
> +++ b/fs/ceph/file.c
> @@ -224,7 +224,9 @@ static int ceph_init_file_info(struct inode
> *inode, struct file *file,
> =C2=A0		ceph_inode_to_fs_client(&ci->netfs.inode)-
> >mount_options;
> =C2=A0	struct ceph_client *cl =3D ceph_inode_to_client(inode);
> =C2=A0	struct ceph_file_info *fi;
> +#ifdef CONFIG_CEPH_FS_INLINE_DATA
> =C2=A0	int ret;
> +#endif
> =C2=A0
> =C2=A0	doutc(cl, "%p %llx.%llx %p 0%o (%s)\n", inode,
> ceph_vinop(inode),
> =C2=A0	=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 file, inode->i_mode, isdir ? "dir" =
: "regular");
> @@ -258,14 +260,17 @@ static int ceph_init_file_info(struct inode
> *inode, struct file *file,
> =C2=A0	INIT_LIST_HEAD(&fi->rw_contexts);
> =C2=A0	fi->filp_gen =3D READ_ONCE(ceph_inode_to_fs_client(inode)-
> >filp_gen);
> =C2=A0
> +#ifdef CONFIG_CEPH_FS_INLINE_DATA
> =C2=A0	if ((file->f_mode & FMODE_WRITE) &&
> ceph_has_inline_data(ci)) {
> =C2=A0		ret =3D ceph_uninline_data(file);
> =C2=A0		if (ret < 0)
> =C2=A0			goto error;
> =C2=A0	}
> +#endif

Maybe, static inline function?

> =C2=A0
> =C2=A0	return 0;
> =C2=A0
> +#ifdef CONFIG_CEPH_FS_INLINE_DATA
> =C2=A0error:
> =C2=A0	ceph_fscache_unuse_cookie(inode, file->f_mode &
> FMODE_WRITE);
> =C2=A0	ceph_put_fmode(ci, fi->fmode, 1);
> @@ -273,6 +278,7 @@ static int ceph_init_file_info(struct inode
> *inode, struct file *file,
> =C2=A0	/* wake up anyone waiting for caps on this inode */
> =C2=A0	wake_up_all(&ci->i_cap_wq);
> =C2=A0	return ret;
> +#endif
> =C2=A0}
> =C2=A0
> =C2=A0/*
> @@ -702,7 +708,9 @@ static int ceph_finish_async_create(struct inode
> *dir, struct inode *inode,
> =C2=A0
> =C2=A0	ktime_get_real_ts64(&now);
> =C2=A0
> +#ifdef CONFIG_CEPH_FS_INLINE_DATA
> =C2=A0	iinfo.inline_version =3D CEPH_INLINE_NONE;
> +#endif
> =C2=A0	iinfo.change_attr =3D 1;
> =C2=A0	ceph_encode_timespec64(&iinfo.btime, &now);
> =C2=A0
> @@ -2224,7 +2232,11 @@ static ssize_t ceph_read_iter(struct kiocb
> *iocb, struct iov_iter *to)
> =C2=A0		=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 inode, ceph_vinop(inode), iocb->ki=
_pos,
> (unsigned)len,
> =C2=A0		=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ceph_cap_string(got));
> =C2=A0
> +#ifdef CONFIG_CEPH_FS_INLINE_DATA
> =C2=A0		if (!ceph_has_inline_data(ci)) {
> +#else
> +		if (true) {
> +#endif

Ditto.

> =C2=A0			if (!retry_op &&
> =C2=A0			=C2=A0=C2=A0=C2=A0 (iocb->ki_flags & IOCB_DIRECT) &&
> =C2=A0			=C2=A0=C2=A0=C2=A0 !IS_ENCRYPTED(inode)) {
> @@ -2267,7 +2279,11 @@ static ssize_t ceph_read_iter(struct kiocb
> *iocb, struct iov_iter *to)
> =C2=A0			if (!page)
> =C2=A0				return -ENOMEM;
> =C2=A0
> +#ifdef CONFIG_CEPH_FS_INLINE_DATA
> =C2=A0			mask =3D CEPH_STAT_CAP_INLINE_DATA;
> +#else
> +			mask =3D 0;
> +#endif

Ditto.

> =C2=A0		}
> =C2=A0
> =C2=A0		statret =3D __ceph_do_getattr(inode, page, mask,
> !!page);
> @@ -2349,8 +2365,12 @@ static ssize_t ceph_splice_read(struct file
> *in, loff_t *ppos,
> =C2=A0	if (ceph_inode_is_shutdown(inode))
> =C2=A0		return -ESTALE;
> =C2=A0
> +#ifdef CONFIG_CEPH_FS_INLINE_DATA
> =C2=A0	if (ceph_has_inline_data(ci) ||
> =C2=A0	=C2=A0=C2=A0=C2=A0 (fi->flags & CEPH_F_SYNC))
> +#else
> +	if (fi->flags & CEPH_F_SYNC)
> +#endif
> =C2=A0		return copy_splice_read(in, ppos, pipe, len, flags);
> =C2=A0
> =C2=A0	ret =3D ceph_start_io_read(inode);
> diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
> index 61d7c0b8161f..20abf7dc9c64 100644
> --- a/fs/ceph/inode.c
> +++ b/fs/ceph/inode.c
> @@ -627,7 +627,9 @@ struct inode *ceph_alloc_inode(struct super_block
> *sb)
> =C2=A0	spin_lock_init(&ci->i_ceph_lock);
> =C2=A0
> =C2=A0	ci->i_version =3D 0;
> +#ifdef CONFIG_CEPH_FS_INLINE_DATA
> =C2=A0	ci->i_inline_version =3D 0;
> +#endif
> =C2=A0	ci->i_time_warp_seq =3D 0;
> =C2=A0	ci->i_ceph_flags =3D 0;
> =C2=A0	atomic64_set(&ci->i_ordered_count, 1);
> @@ -1030,7 +1032,9 @@ int ceph_fill_inode(struct inode *inode, struct
> page *locked_page,
> =C2=A0	bool wake =3D false;
> =C2=A0	bool queue_trunc =3D false;
> =C2=A0	bool new_version =3D false;
> +#ifdef CONFIG_CEPH_FS_INLINE_DATA
> =C2=A0	bool fill_inline =3D false;
> +#endif
> =C2=A0	umode_t mode =3D le32_to_cpu(info->mode);
> =C2=A0	dev_t rdev =3D le32_to_cpu(info->rdev);
> =C2=A0
> @@ -1362,6 +1366,7 @@ int ceph_fill_inode(struct inode *inode, struct
> page *locked_page,
> =C2=A0		}
> =C2=A0	}
> =C2=A0
> +#ifdef CONFIG_CEPH_FS_INLINE_DATA
> =C2=A0	if (iinfo->inline_version > 0 &&
> =C2=A0	=C2=A0=C2=A0=C2=A0 iinfo->inline_version >=3D ci->i_inline_version=
) {
> =C2=A0		int cache_caps =3D CEPH_CAP_FILE_CACHE |
> CEPH_CAP_FILE_LAZYIO;
> @@ -1370,6 +1375,7 @@ int ceph_fill_inode(struct inode *inode, struct
> page *locked_page,
> =C2=A0		=C2=A0=C2=A0=C2=A0 (locked_page || (info_caps & cache_caps)))
> =C2=A0			fill_inline =3D true;
> =C2=A0	}
> +#endif
> =C2=A0
> =C2=A0	if (cap_fmode >=3D 0) {
> =C2=A0		if (!info_caps)
> @@ -1382,9 +1388,11 @@ int ceph_fill_inode(struct inode *inode,
> struct page *locked_page,
> =C2=A0
> =C2=A0	ceph_fscache_register_inode_cookie(inode);
> =C2=A0
> +#ifdef CONFIG_CEPH_FS_INLINE_DATA
> =C2=A0	if (fill_inline)
> =C2=A0		ceph_fill_inline_data(inode, locked_page,
> =C2=A0				=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 iinfo->inline_data, iinfo-
> >inline_len);
> +#endif
> =C2=A0
> =C2=A0	if (wake)
> =C2=A0		wake_up_all(&ci->i_cap_wq);
> @@ -3022,6 +3030,7 @@ int __ceph_do_getattr(struct inode *inode,
> struct page *locked_page,
> =C2=A0	req->r_args.getattr.mask =3D cpu_to_le32(mask);
> =C2=A0	req->r_locked_page =3D locked_page;
> =C2=A0	err =3D ceph_mdsc_do_request(mdsc, NULL, req);
> +#ifdef CONFIG_CEPH_FS_INLINE_DATA
> =C2=A0	if (locked_page && err =3D=3D 0) {
> =C2=A0		u64 inline_version =3D req-
> >r_reply_info.targeti.inline_version;
> =C2=A0		if (inline_version =3D=3D 0) {
> @@ -3034,6 +3043,7 @@ int __ceph_do_getattr(struct inode *inode,
> struct page *locked_page,
> =C2=A0			err =3D req->r_reply_info.targeti.inline_len;
> =C2=A0		}
> =C2=A0	}
> +#endif

Ditto.

> =C2=A0	ceph_mdsc_put_request(req);
> =C2=A0	doutc(cl, "result=3D%d\n", err);
> =C2=A0	return err;
> diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
> index 18be36c2e9e8..6a439da76616 100644
> --- a/fs/ceph/mds_client.c
> +++ b/fs/ceph/mds_client.c
> @@ -156,12 +156,26 @@ static int parse_reply_info_in(void **p, void
> *end,
> =C2=A0	*p +=3D info->xattr_len;
> =C2=A0
> =C2=A0	if (features =3D=3D (u64)-1) {
> +#ifdef CONFIG_CEPH_FS_INLINE_DATA
> =C2=A0		/* inline data */
> =C2=A0		ceph_decode_64_safe(p, end, info->inline_version,
> bad);
> =C2=A0		ceph_decode_32_safe(p, end, info->inline_len, bad);
> =C2=A0		ceph_decode_need(p, end, info->inline_len, bad);
> =C2=A0		info->inline_data =3D *p;
> =C2=A0		*p +=3D info->inline_len;
> +#else
> +		/*
> +		 * Inline data support has been removed, but the MDS
> always
> +		 * encodes inline_version + inline_data in versioned
> replies.
> +		 * We must consume these fields from the message to
> keep the
> +		 * decode pointer in sync, even though we discard
> them.
> +		 */
> +		u32 __len;

Ditto, Maybe, simply len?

> +
> +		ceph_decode_skip_64(p, end, bad);
> +		ceph_decode_32_safe(p, end, __len, bad);
> +		ceph_decode_skip_n(p, end, __len, bad);
> +#endif
> =C2=A0		/* quota */
> =C2=A0		err =3D parse_reply_info_quota(p, end, info);
> =C2=A0		if (err < 0)
> @@ -276,6 +290,7 @@ static int parse_reply_info_in(void **p, void
> *end,
> =C2=A0		*p =3D end;
> =C2=A0	} else {
> =C2=A0		/* legacy (unversioned) struct */
> +#ifdef CONFIG_CEPH_FS_INLINE_DATA
> =C2=A0		if (features & CEPH_FEATURE_MDS_INLINE_DATA) {
> =C2=A0			ceph_decode_64_safe(p, end, info-
> >inline_version, bad);
> =C2=A0			ceph_decode_32_safe(p, end, info-
> >inline_len, bad);
> @@ -284,6 +299,21 @@ static int parse_reply_info_in(void **p, void
> *end,
> =C2=A0			*p +=3D info->inline_len;
> =C2=A0		} else
> =C2=A0			info->inline_version =3D CEPH_INLINE_NONE;
> +#else
> +		/*
> +		 * Inline data support has been removed.=C2=A0 When the
> MDS
> +		 * advertises CEPH_FEATURE_MDS_INLINE_DATA it
> includes
> +		 * inline_version + inline_data in legacy replies.=C2=A0
> We
> +		 * must consume them to keep the decode pointer in
> sync.
> +		 */
> +		if (features & CEPH_FEATURE_MDS_INLINE_DATA) {
> +			u32 __len;

Ditto. Maybe, len?

> +
> +			ceph_decode_skip_64(p, end, bad);
> +			ceph_decode_32_safe(p, end, __len, bad);
> +			ceph_decode_skip_n(p, end, __len, bad);
> +		}
> +#endif

Ditto. Maybe, static inline function?
> =C2=A0
> =C2=A0		if (features & CEPH_FEATURE_MDS_QUOTA) {
> =C2=A0			err =3D parse_reply_info_quota(p, end, info);
> diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h
> index 731d6ad04956..9bcf1a9d5ba8 100644
> --- a/fs/ceph/mds_client.h
> +++ b/fs/ceph/mds_client.h
> @@ -149,9 +149,11 @@ struct ceph_mds_reply_info_in {
> =C2=A0	char *symlink;
> =C2=A0	u32 xattr_len;
> =C2=A0	char *xattr_data;
> +#ifdef CONFIG_CEPH_FS_INLINE_DATA
> =C2=A0	u64 inline_version;
> =C2=A0	u32 inline_len;
> =C2=A0	char *inline_data;
> +#endif
> =C2=A0	u32 pool_ns_len;
> =C2=A0	char *pool_ns_data;
> =C2=A0	u64 max_bytes;
> diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c
> index e5d8d59ffc17..3bc3a2ce72a2 100644
> --- a/fs/ceph/snap.c
> +++ b/fs/ceph/snap.c
> @@ -613,7 +613,9 @@ static void ceph_queue_cap_snap(struct
> ceph_inode_info *ci,
> =C2=A0		capsnap->xattr_version =3D 0;
> =C2=A0	}
> =C2=A0
> +#ifdef CONFIG_CEPH_FS_INLINE_DATA
> =C2=A0	capsnap->inline_data =3D ci->i_inline_version !=3D
> CEPH_INLINE_NONE;
> +#endif
> =C2=A0
> =C2=A0	/* dirty page count moved from _head to this cap_snap;
> =C2=A0	=C2=A0=C2=A0 all subsequent writes page dirties occur _after_ this
> diff --git a/fs/ceph/super.h b/fs/ceph/super.h
> index 3737ea7ed88b..eced08f52b79 100644
> --- a/fs/ceph/super.h
> +++ b/fs/ceph/super.h
> @@ -274,7 +274,9 @@ struct ceph_cap_snap {
> =C2=A0	u32 truncate_seq;
> =C2=A0	int writing;=C2=A0=C2=A0 /* a sync write is still in progress */
> =C2=A0	int dirty_pages;=C2=A0=C2=A0=C2=A0=C2=A0 /* dirty pages awaiting w=
riteback */
> +#ifdef CONFIG_CEPH_FS_INLINE_DATA
> =C2=A0	bool inline_data;
> +#endif
> =C2=A0	bool need_flush;
> =C2=A0};
> =C2=A0
> @@ -381,7 +383,9 @@ struct ceph_inode_info {
> =C2=A0	spinlock_t i_ceph_lock;
> =C2=A0
> =C2=A0	u64 i_version;
> +#ifdef CONFIG_CEPH_FS_INLINE_DATA
> =C2=A0	u64 i_inline_version;
> +#endif
> =C2=A0	u32 i_time_warp_seq;
> =C2=A0
> =C2=A0	unsigned long i_ceph_flags;
> @@ -1335,11 +1339,14 @@ extern void __ceph_touch_fmode(struct
> ceph_inode_info *ci,
> =C2=A0extern const struct address_space_operations ceph_aops;
> =C2=A0extern const struct netfs_request_ops ceph_netfs_ops;
> =C2=A0int ceph_mmap_prepare(struct vm_area_desc *desc);
> +#ifdef CONFIG_CEPH_FS_INLINE_DATA
> =C2=A0extern int ceph_uninline_data(struct file *file);
> +#endif
> =C2=A0extern int ceph_pool_perm_check(struct inode *inode, int need);
> =C2=A0extern void ceph_pool_perm_destroy(struct ceph_mds_client* mdsc);
> =C2=A0int ceph_purge_inode_cap(struct inode *inode, struct ceph_cap *cap,
> bool *invalidate);
> =C2=A0
> +#ifdef CONFIG_CEPH_FS_INLINE_DATA
> =C2=A0static inline bool ceph_has_inline_data(struct ceph_inode_info *ci)
> =C2=A0{
> =C2=A0	if (ci->i_inline_version =3D=3D CEPH_INLINE_NONE ||
> @@ -1347,6 +1354,12 @@ static inline bool ceph_has_inline_data(struct
> ceph_inode_info *ci)
> =C2=A0		return false;
> =C2=A0	return true;
> =C2=A0}
> +#else
> +static inline bool ceph_has_inline_data(struct ceph_inode_info *ci)
> +{
> +	return false;
> +}
> +#endif
> =C2=A0
> =C2=A0/* file.c */
> =C2=A0extern const struct file_operations ceph_file_fops;
> diff --git a/include/linux/ceph/ceph_features.h
> b/include/linux/ceph/ceph_features.h
> index 3a47acd9cc14..207b93787a4f 100644
> --- a/include/linux/ceph/ceph_features.h
> +++ b/include/linux/ceph/ceph_features.h
> @@ -132,6 +132,11 @@ DEFINE_CEPH_FEATURE(38, 1, OSD_ERASURE_CODES)
> =C2=A0DEFINE_CEPH_FEATURE(38, 1, OSD_OSD_TMAP2OMAP) // overlap
> =C2=A0DEFINE_CEPH_FEATURE(39, 1, OSDMAP_ENC)
> =C2=A0DEFINE_CEPH_FEATURE(40, 1, MDS_INLINE_DATA)
> +#ifdef CONFIG_CEPH_FS_INLINE_DATA
> +#define
> CEPH_FEATURE_MDS_INLINE_DATA_DEFAULT	CEPH_FEATURE_MDS_INLINE_DATA
> +#else
> +#define CEPH_FEATURE_MDS_INLINE_DATA_DEFAULT	0
> +#endif
> =C2=A0DEFINE_CEPH_FEATURE(41, 1, CRUSH_TUNABLES3)
> =C2=A0DEFINE_CEPH_FEATURE(41, 1, OSD_PRIMARY_AFFINITY) // overlap
> =C2=A0DEFINE_CEPH_FEATURE(42, 1, MSGR_KEEPALIVE2)
> @@ -204,7 +209,7 @@ DEFINE_CEPH_FEATURE_DEPRECATED(63, 1,
> RESERVED_BROKEN, LUMINOUS) // client-facin
> =C2=A0	 CEPH_FEATURE_CRUSH_V2 |		\
> =C2=A0	 CEPH_FEATURE_EXPORT_PEER |		\
> =C2=A0	 CEPH_FEATURE_OSDMAP_ENC |		\
> -	 CEPH_FEATURE_MDS_INLINE_DATA |		\
> +	 CEPH_FEATURE_MDS_INLINE_DATA_DEFAULT |	\
> =C2=A0	 CEPH_FEATURE_CRUSH_TUNABLES3 |		\
> =C2=A0	 CEPH_FEATURE_OSD_PRIMARY_AFFINITY |	\
> =C2=A0	 CEPH_FEATURE_MSGR_KEEPALIVE2 |		\
>=20
> ---
> base-commit: 602bb4525c8146865b7f6e44c81d54bf97861aed
> change-id: 20260728-b4-ceph-remove-inline-data-d55c6466dd7e
>=20
>=20

git apply --check ./\[PATCH\ v2\]\ ceph\:\ remove\ the\ inline\ data\
support.mbox
error: patch failed: fs/ceph/Kconfig:17
error: fs/ceph/Kconfig: patch does not apply
error: patch failed: fs/ceph/addr.c:274
error: fs/ceph/addr.c: patch does not apply
error: patch failed: fs/ceph/caps.c:1266
error: fs/ceph/caps.c: patch does not apply
error: patch failed: fs/ceph/file.c:224
error: fs/ceph/file.c: patch does not apply
error: patch failed: fs/ceph/inode.c:627
error: fs/ceph/inode.c: patch does not apply
error: patch failed: fs/ceph/mds_client.c:156
error: fs/ceph/mds_client.c: patch does not apply
error: patch failed: fs/ceph/mds_client.h:149
error: fs/ceph/mds_client.h: patch does not apply
error: patch failed: fs/ceph/snap.c:613
error: fs/ceph/snap.c: patch does not apply
error: patch failed: fs/ceph/super.h:274
error: fs/ceph/super.h: patch does not apply
error: patch failed: include/linux/ceph/ceph_features.h:132
error: include/linux/ceph/ceph_features.h: patch does not apply
>=20

./scripts/checkpatch.pl --strict ./\[PATCH\ v2\]\ ceph\:\ remove\ the\
inline\ data\ support.mbox=20
ERROR: DOS line endings
#145: FILE: fs/ceph/Kconfig:20:
+config CEPH_FS_INLINE_DATA^M$

ERROR: DOS line endings
#146: FILE: fs/ceph/Kconfig:21:
+^Ibool "Enable CephFS inline data support (deprecated)"^M$

Every new line in this patch is indented with spaces, not tabs.

Thanks,
Slava.