diff --git a/Documentation/filesystems/ceph.rst b/Documentation/filesystems/ceph.rst index 6d2276a87a5a..ee2ca0c0c654 100644 --- a/Documentation/filesystems/ceph.rst +++ b/Documentation/filesystems/ceph.rst @@ -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= Set auto reconnect mode in the case where the client is blocklisted. The available modes are "no" and "clean". The default is "no". diff --git a/fs/ceph/file.c b/fs/ceph/file.c index a0b9c2b5a583..bd3e3f5c269e 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -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); } diff --git a/fs/ceph/super.c b/fs/ceph/super.c index c05fbd4237f8..15edea30dc8b 100644 --- a/fs/ceph/super.c +++ b/fs/ceph/super.c @@ -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); diff --git a/fs/ceph/super.h b/fs/ceph/super.h index 1902b7cc55d3..0020ccd0f974 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h @@ -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 | \