diff --git a/kmod/src/Makefile.kernelcompat b/kmod/src/Makefile.kernelcompat index 9c8bd9cb..88b97f89 100644 --- a/kmod/src/Makefile.kernelcompat +++ b/kmod/src/Makefile.kernelcompat @@ -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 diff --git a/kmod/src/data.c b/kmod/src/data.c index d301133e..d06553c1 100644 --- a/kmod/src/data.c +++ b/kmod/src/data.c @@ -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, diff --git a/kmod/src/file.c b/kmod/src/file.c index 5c4112e8..bae3c3c2 100644 --- a/kmod/src/file.c +++ b/kmod/src/file.c @@ -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); diff --git a/kmod/src/iomap.c b/kmod/src/iomap.c index d1cd8aec..06225654 100644 --- a/kmod/src/iomap.c +++ b/kmod/src/iomap.c @@ -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 */