Kernel compatibility changes for iomap on EL8

Add KC_USE_IOMAP_FOR_IO and only build the iomap R/W pieces
for EL9 and higher. We support iomap for fiemap and llseek
on EL8.

Signed-off-by: Chris Kirby <ckirby@versity.com>
This commit is contained in:
Chris Kirby
2026-06-29 13:27:14 -05:00
parent 83022dba68
commit 086797e7f6
4 changed files with 29 additions and 139 deletions
+10
View File
@@ -222,3 +222,13 @@ endif
ifneq (,$(shell grep 'define timer_container_of' include/linux/timer.h))
ccflags-y += -DKC_TIMER_CONTAINER_OF
endif
#
# v6.4-rc1-4f80818b4a58c
#
# iomap needs iterator nofault support in the read/write paths. We can still
# use iomap for fiemap and llseek though.
#
ifneq (,$(shell grep 'copy_page_to_iter_nofault' include/linux/uio.h))
ccflags-y += -DKC_USE_IOMAP_FOR_IO
endif
+10
View File
@@ -1173,6 +1173,7 @@ out:
return ret;
}
#ifdef KC_USE_IOMAP_FOR_IO
static int scoutfs_fadvise(struct file *file, loff_t start, loff_t end, int advice)
{
struct inode *inode = file_inode(file);
@@ -1203,6 +1204,7 @@ static int scoutfs_fadvise(struct file *file, loff_t start, loff_t end, int advi
return ret;
}
#endif
/*
* A special case of initializing a single large offline extent. This
@@ -2122,7 +2124,9 @@ static vm_fault_t scoutfs_data_filemap_fault(struct vm_fault *vmf)
loff_t pos;
int err;
vm_fault_t ret = VM_FAULT_SIGBUS;
#ifdef KC_USE_IOMAP_FOR_IO
void *semlock;
#endif
bool found_lock;
pos = vmf->pgoff;
@@ -2157,19 +2161,23 @@ retry:
found_lock = true;
}
#ifdef KC_USE_IOMAP_FOR_IO
semlock = scoutfs_per_task_get(&si->pt_extent_sem);
if (semlock == NULL) {
down_read(&si->extent_sem);
if (!scoutfs_per_task_add_excl(&si->pt_extent_sem, &pt_sem, &semlock))
WARN_ON_ONCE(true);
}
#endif
ret = filemap_fault(vmf);
#ifdef KC_USE_IOMAP_FOR_IO
if (semlock == NULL) {
up_read(&si->extent_sem);
scoutfs_per_task_del(&si->pt_extent_sem, &pt_sem);
}
#endif
out:
if (!found_lock) {
@@ -2232,7 +2240,9 @@ const struct file_operations scoutfs_file_fops = {
.fsync = scoutfs_file_fsync,
.llseek = scoutfs_file_llseek,
.fallocate = scoutfs_fallocate,
#ifdef KC_USE_IOMAP_FOR_IO
.fadvise = scoutfs_fadvise,
#endif
};
void scoutfs_data_init_btrees(struct super_block *sb,
+9 -118
View File
@@ -34,38 +34,8 @@
#include "trans.h"
#include "msg.h"
static int lock_for_iomap_read(struct inode *inode, bool nowait,
struct scoutfs_per_task_entry *pt_extent_ent)
{
#if 0
struct scoutfs_inode_info *si = SCOUTFS_I(inode);
if (nowait) {
if (!down_read_trylock(&si->extent_sem))
return -EAGAIN;
} else {
down_read(&si->extent_sem);
}
if (!scoutfs_per_task_add_excl(&si->pt_extent_sem, pt_extent_ent, pt_extent_ent))
WARN_ON_ONCE(true);
#endif
return 0;
}
static void unlock_for_iomap_read(struct inode *inode,
struct scoutfs_per_task_entry *pt_extent_ent)
{
#if 0
struct scoutfs_inode_info *si = SCOUTFS_I(inode);
scoutfs_per_task_del(&si->pt_extent_sem, pt_extent_ent);
up_read(&si->extent_sem);
#endif
}
#ifdef KC_USE_IOMAP_FOR_IO
static bool scoutfs_should_use_dio(struct kiocb *iocb, struct iov_iter *iter)
{
/* Current offset must be aligned */
@@ -139,11 +109,6 @@ retry:
if (!scoutfs_per_task_add_excl(&si->pt_extent_sem, &pt_extent_ent,
&pt_extent_ent))
WARN_ON_ONCE(true);
#if 0
ret = lock_for_iomap_read(inode, false, &pt_extent_ent);
if (ret)
return ret;
#endif
locked = true;
pagefault_disable();
@@ -157,9 +122,6 @@ retry:
if (should_fault_in_pages(to, iocb, &prev_count, &window_size)) {
scoutfs_per_task_del(&si->pt_extent_sem, &pt_extent_ent);
up_read(&si->extent_sem);
#if 0
unlock_for_iomap_read(inode, &pt_extent_ent);
#endif
locked = false;
window_size -= fault_in_iov_iter_writeable(to, window_size);
if (window_size != 0)
@@ -168,12 +130,8 @@ retry:
out:
if (locked) {
#if 1
scoutfs_per_task_del(&si->pt_extent_sem, &pt_extent_ent);
up_read(&si->extent_sem);
#else
unlock_for_iomap_read(inode, &pt_extent_ent);
#endif
}
return read ? read : ret;
@@ -183,12 +141,9 @@ static ssize_t scoutfs_file_direct_read(struct kiocb *iocb, struct iov_iter *to,
bool nowait)
{
struct file *file = iocb->ki_filp;
struct inode *inode = file_inode(file);
SCOUTFS_DECLARE_PER_TASK_ENTRY(pt_extent_ent);
size_t prev_count = 0;
size_t window_size = 0;
size_t read = 0;
bool locked = false;
ssize_t ret;
if (!scoutfs_should_use_dio(iocb, to)) {
@@ -197,12 +152,6 @@ static ssize_t scoutfs_file_direct_read(struct kiocb *iocb, struct iov_iter *to,
}
retry:
ret = lock_for_iomap_read(inode, nowait, &pt_extent_ent);
if (ret)
return ret;
locked = true;
pagefault_disable();
to->nofault = true;
ret = iomap_dio_rw(iocb, to, &scoutfs_iomap_ops, NULL, IOMAP_DIO_PARTIAL, 0);
@@ -210,22 +159,17 @@ retry:
pagefault_enable();
if (ret <= 0 && ret != -EFAULT)
goto out_unlock;
goto out;
if (ret > 0)
read = ret;
if (should_fault_in_pages(to, iocb, &prev_count, &window_size)) {
unlock_for_iomap_read(inode, &pt_extent_ent);
locked = false;
window_size -= fault_in_iov_iter_writeable(to, window_size);
if (window_size != 0)
goto retry;
}
out_unlock:
if (locked)
unlock_for_iomap_read(inode, &pt_extent_ent);
out:
file_accessed(file);
if (ret < 0)
@@ -317,16 +261,8 @@ out:
return ret;
}
/*
* We need to complete all of our locking before we get into the iomap iterator.
* The lock hierarchy isn't well defined, and some paths reverse the ordering of
* the inode index lock and the extent_sem because of how the get_block functions
* are called. So we have to use trylocks and retry as needed, unless nonblocking
* mode was requested.
*/
static int lock_for_iomap_write(struct inode *inode, struct list_head *ind_locks,
struct scoutfs_per_task_entry *pt_inode_ent,
struct scoutfs_per_task_entry *pt_extent_ent,
struct scoutfs_lock *scoutfs_inode_lock,
bool nowait)
{
@@ -349,28 +285,8 @@ static int lock_for_iomap_write(struct inode *inode, struct list_head *ind_locks
continue;
}
#if 0
if (!down_write_trylock(&si->extent_sem)) {
scoutfs_release_trans(sb);
scoutfs_inode_index_unlock(sb, ind_locks);
if (nowait)
return -EAGAIN;
continue;
}
#endif
scoutfs_per_task_add_excl(&si->pt_inode_locks, pt_inode_ent, ind_locks);
#if 0
/*
* We need to assign a pointer value to the per-task var. Since this
* one is just a marker that we hold the extent_sem, it can be anything
* that's non-NULL. So just use the entry itself.
*/
scoutfs_per_task_add_excl(&si->pt_extent_sem, pt_extent_ent,
pt_extent_ent);
#endif
ret = scoutfs_dirty_inode_item(inode, scoutfs_inode_lock);
break;
@@ -383,7 +299,6 @@ static void unlock_for_iomap_write(struct inode *inode,
struct scoutfs_lock *scoutfs_inode_lock,
struct list_head *ind_locks,
struct scoutfs_per_task_entry *pt_inode_ent,
struct scoutfs_per_task_entry *pt_extent_ent,
size_t written)
{
struct super_block *sb = inode->i_sb;
@@ -399,13 +314,6 @@ static void unlock_for_iomap_write(struct inode *inode,
BUG_ON(!t);
scoutfs_inode_index_unlock(sb, ind_locks);
#if 0
t = scoutfs_per_task_del(&si->pt_extent_sem, pt_extent_ent);
BUG_ON(!t);
up_write(&si->extent_sem);
#endif
}
static ssize_t scoutfs_file_direct_write(struct kiocb *iocb, struct iov_iter *from,
@@ -415,7 +323,6 @@ static ssize_t scoutfs_file_direct_write(struct kiocb *iocb, struct iov_iter *fr
struct inode *inode = file_inode(file);
bool nowait = (iocb->ki_flags & IOCB_NOWAIT);
SCOUTFS_DECLARE_PER_TASK_ENTRY(pt_inode_ent);
SCOUTFS_DECLARE_PER_TASK_ENTRY(pt_extent_ent);
LIST_HEAD(ind_locks);
size_t prev_count = 0;
size_t window_size = 0;
@@ -429,7 +336,7 @@ static ssize_t scoutfs_file_direct_write(struct kiocb *iocb, struct iov_iter *fr
}
retry:
ret = lock_for_iomap_write(inode, &ind_locks, &pt_inode_ent, &pt_extent_ent,
ret = lock_for_iomap_write(inode, &ind_locks, &pt_inode_ent,
scoutfs_inode_lock, nowait);
if (ret < 0)
goto out;
@@ -466,7 +373,7 @@ retry:
*/
if (should_fault_in_pages(from, iocb, &prev_count, &window_size)) {
unlock_for_iomap_write(inode, scoutfs_inode_lock, &ind_locks,
&pt_inode_ent, &pt_extent_ent, written);
&pt_inode_ent, written);
locked = false;
window_size -= fault_in_iov_iter_readable(from, window_size);
if (window_size != 0)
@@ -476,7 +383,7 @@ retry:
out:
if (locked) {
unlock_for_iomap_write(inode, scoutfs_inode_lock, &ind_locks,
&pt_inode_ent, &pt_extent_ent, written);
&pt_inode_ent, written);
}
return ret < 0 ? ret : written;
@@ -488,7 +395,6 @@ static ssize_t scoutfs_file_buffered_write(struct kiocb *iocb, struct iov_iter *
struct file *file = iocb->ki_filp;
struct inode *inode = file_inode(file);
SCOUTFS_DECLARE_PER_TASK_ENTRY(pt_inode_ent);
SCOUTFS_DECLARE_PER_TASK_ENTRY(pt_extent_ent);
LIST_HEAD(ind_locks);
size_t prev_count = 0;
size_t window_size = 0;
@@ -514,7 +420,7 @@ retry:
from->count = min(from->count, window_size);
}
ret = lock_for_iomap_write(inode, &ind_locks, &pt_inode_ent, &pt_extent_ent,
ret = lock_for_iomap_write(inode, &ind_locks, &pt_inode_ent,
scoutfs_inode_lock, false);
if (ret < 0)
goto out;
@@ -539,7 +445,7 @@ retry:
* try another pass.
*/
unlock_for_iomap_write(inode, scoutfs_inode_lock, &ind_locks,
&pt_inode_ent, &pt_extent_ent, written);
&pt_inode_ent, written);
locked = false;
goto retry;
}
@@ -547,7 +453,7 @@ retry:
out:
if (locked) {
unlock_for_iomap_write(inode, scoutfs_inode_lock, &ind_locks,
&pt_inode_ent, &pt_extent_ent, written);
&pt_inode_ent, written);
}
from->count = orig_count - written;
@@ -698,14 +604,10 @@ ssize_t scoutfs_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
struct super_block *sb = inode->i_sb;
struct scoutfs_lock *scoutfs_inode_lock = NULL;
SCOUTFS_DECLARE_PER_TASK_ENTRY(pt_ent);
SCOUTFS_DECLARE_PER_TASK_ENTRY(pt_extent_ent);
DECLARE_DATA_WAIT(dw);
bool locked;
int ret;
retry:
locked = false;
/* protect checked extents from release */
inode_lock(inode);
atomic_inc(&inode->i_dio_count);
@@ -716,12 +618,6 @@ retry:
if (ret)
goto out;
ret = lock_for_iomap_read(inode, false, &pt_extent_ent);
if (ret)
return ret;
locked = true;
if (scoutfs_per_task_add_excl(&si->pt_data_lock, &pt_ent, scoutfs_inode_lock)) {
ret = scoutfs_data_wait_check(inode, iocb->ki_pos, iov_iter_count(to), SEF_OFFLINE,
SCOUTFS_IOC_DWO_READ, &dw, scoutfs_inode_lock);
@@ -734,11 +630,6 @@ retry:
ret = generic_file_read_iter(iocb, to);
out:
if (locked) {
unlock_for_iomap_read(inode, &pt_extent_ent);
locked = false;
}
inode_dio_end(inode);
scoutfs_per_task_del(&si->pt_data_lock, &pt_ent);
scoutfs_unlock(sb, scoutfs_inode_lock, SCOUTFS_LOCK_READ);
-21
View File
@@ -148,9 +148,6 @@ static int scoutfs_iomap_begin(struct inode *inode, loff_t offset, loff_t length
struct iomap *srcmap)
{
struct scoutfs_inode_info *si = SCOUTFS_I(inode);
#if 0
SCOUTFS_DECLARE_PER_TASK_ENTRY(pt_extent_ent);
#endif
struct super_block *sb = inode->i_sb;
const u64 ino = scoutfs_ino(inode);
struct scoutfs_lock *data_lock = NULL;
@@ -164,9 +161,6 @@ static int scoutfs_iomap_begin(struct inode *inode, loff_t offset, loff_t length
int ret = 0;
WARN_ON_ONCE(flags & ~KNOWN_FLAGS);
#if 0
WARN_ON_ONCE(!rwsem_is_locked(&si->extent_sem));
#endif
iblock = offset >> SCOUTFS_BLOCK_SM_SHIFT;
@@ -216,21 +210,12 @@ static int scoutfs_iomap_begin(struct inode *inode, loff_t offset, loff_t length
if (ret == 0)
iomap->flags |= IOMAP_F_NEW;
} else {
#if 0
ret = lock_for_iomap_read(inode, nowait, &pt_extent_ent);
if (ret)
goto out;
#endif
down_read(&si->extent_sem);
ret = scoutfs_ext_next(sb, &data_ext_ops, &args, iblock, 1, &ext);
up_read(&si->extent_sem);
#if 0
unlock_for_iomap_read(inode, &pt_extent_ent);
#endif
if (ret == -ENOENT)
ret = 0;
@@ -272,12 +257,6 @@ static int scoutfs_iomap_end(struct inode *inode, loff_t offset, loff_t length,
data_lock = scoutfs_per_task_get(&si->pt_data_lock);
BUG_ON(!data_lock);
#if 0
ret = lock_for_iomap_write(inode, &inode_locks, &pt_inode_ent,
&pt_extent_ent, data_lock, nowait);
if (ret)
return ret;
#endif
down_write(&si->extent_sem);
/* convert unwritten to written, could be staging */