mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 08:15:07 -04:00
ceph: make nearfull sync writes opt-in
The kernel CephFS client has historically treated a cluster or pool NEARFULL condition as a request to force successful writes through generic_write_sync(). That effectively turns otherwise buffered writes into synchronous writes and can cause a severe throughput drop as soon as a single OSD or the file data pool crosses the nearfull threshold. On modern large clusters, NEARFULL is primarily an operator health signal rather than an immediate client-side capacity failure. Operators can still have substantial usable capacity while a cluster is rebalancing, splitting PGs, or expanding onto new devices. RBD, RGW and the userspace CephFS client do not impose this extra client-side sync-write throttle, so the kernel client behavior is surprising and operationally painful. Change the default behavior so NEARFULL no longer changes normal write-sync semantics. FULL and pool FULL still fail with -ENOSPC, and explicitly synchronous writes continue to be synced by generic_write_sync(). Add a nearfull_sync mount option for deployments that want the legacy backpressure behavior. When this option is set, successful writes are promoted to IOCB_DSYNC if the cluster or file data pool is marked NEARFULL, preserving the old behavior for conservative deployments. Link: https://tracker.ceph.com/issues/74849 Signed-off-by: Alex Markuze <amarkuze@redhat.com> Reviewed-by: Xiubo Li <xiubo.li@clyso.com> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
This commit is contained in:
committed by
Ilya Dryomov
parent
e7d7aa7b73
commit
5f074d7f29
@@ -194,6 +194,12 @@ Mount Options
|
||||
copies. Currently, it's only used in copy_file_range, which will revert
|
||||
to the default VFS implementation if this option is used.
|
||||
|
||||
nearfull_sync
|
||||
Force written data to stable storage when the cluster or file data pool is
|
||||
marked NEARFULL. This restores the legacy client-side backpressure
|
||||
behavior. By default, CephFS writes are not forced synchronous solely
|
||||
because of NEARFULL.
|
||||
|
||||
recover_session=<no|clean>
|
||||
Set auto reconnect mode in the case where the client is blocklisted. The
|
||||
available modes are "no" and "clean". The default is "no".
|
||||
|
||||
@@ -2388,7 +2388,8 @@ static ssize_t ceph_splice_read(struct file *in, loff_t *ppos,
|
||||
* dropping our cap refs and allowing the pending snap to logically
|
||||
* complete _before_ this write occurs.
|
||||
*
|
||||
* If we are near ENOSPC, write synchronously.
|
||||
* If requested, nearfull writes are synced to preserve the legacy
|
||||
* client-side backpressure behavior.
|
||||
*/
|
||||
static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
|
||||
{
|
||||
@@ -2604,8 +2605,9 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
|
||||
}
|
||||
|
||||
if (written >= 0) {
|
||||
if ((map_flags & CEPH_OSDMAP_NEARFULL) ||
|
||||
(pool_flags & CEPH_POOL_FLAG_NEARFULL))
|
||||
if (ceph_test_mount_opt(fsc, NEARFULL_SYNC) &&
|
||||
((map_flags & CEPH_OSDMAP_NEARFULL) ||
|
||||
(pool_flags & CEPH_POOL_FLAG_NEARFULL)))
|
||||
iocb->ki_flags |= IOCB_DSYNC;
|
||||
written = generic_write_sync(iocb, written);
|
||||
}
|
||||
|
||||
@@ -177,6 +177,7 @@ enum {
|
||||
Opt_wsync,
|
||||
Opt_pagecache,
|
||||
Opt_sparseread,
|
||||
Opt_nearfull_sync,
|
||||
};
|
||||
|
||||
enum ceph_recover_session_mode {
|
||||
@@ -205,6 +206,7 @@ static const struct fs_parameter_spec ceph_mount_parameters[] = {
|
||||
fsparam_flag_no ("ino32", Opt_ino32),
|
||||
fsparam_string ("mds_namespace", Opt_mds_namespace),
|
||||
fsparam_string ("mon_addr", Opt_mon_addr),
|
||||
fsparam_flag_no ("nearfull_sync", Opt_nearfull_sync),
|
||||
fsparam_flag_no ("poolperm", Opt_poolperm),
|
||||
fsparam_flag_no ("quotadf", Opt_quotadf),
|
||||
fsparam_u32 ("rasize", Opt_rasize),
|
||||
@@ -593,6 +595,12 @@ static int ceph_parse_mount_param(struct fs_context *fc,
|
||||
else
|
||||
fsopt->flags |= CEPH_MOUNT_OPT_SPARSEREAD;
|
||||
break;
|
||||
case Opt_nearfull_sync:
|
||||
if (result.negated)
|
||||
fsopt->flags &= ~CEPH_MOUNT_OPT_NEARFULL_SYNC;
|
||||
else
|
||||
fsopt->flags |= CEPH_MOUNT_OPT_NEARFULL_SYNC;
|
||||
break;
|
||||
case Opt_test_dummy_encryption:
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
fscrypt_free_dummy_policy(&fsopt->dummy_enc_policy);
|
||||
@@ -749,6 +757,8 @@ static int ceph_show_options(struct seq_file *m, struct dentry *root)
|
||||
seq_puts(m, ",nopagecache");
|
||||
if (fsopt->flags & CEPH_MOUNT_OPT_SPARSEREAD)
|
||||
seq_puts(m, ",sparseread");
|
||||
if (fsopt->flags & CEPH_MOUNT_OPT_NEARFULL_SYNC)
|
||||
seq_puts(m, ",nearfull_sync");
|
||||
|
||||
fscrypt_show_test_dummy_encryption(m, ',', root->d_sb);
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#define CEPH_MOUNT_OPT_ASYNC_DIROPS (1<<15) /* allow async directory ops */
|
||||
#define CEPH_MOUNT_OPT_NOPAGECACHE (1<<16) /* bypass pagecache altogether */
|
||||
#define CEPH_MOUNT_OPT_SPARSEREAD (1<<17) /* always do sparse reads */
|
||||
#define CEPH_MOUNT_OPT_NEARFULL_SYNC (1<<18) /* sync writes when nearfull */
|
||||
|
||||
#define CEPH_MOUNT_OPT_DEFAULT \
|
||||
(CEPH_MOUNT_OPT_DCACHE | \
|
||||
|
||||
Reference in New Issue
Block a user