diff options
author | 2024-09-14 09:32:13 -0400 | |
---|---|---|
committer | 2024-09-15 02:43:05 -0400 | |
commit | 091b2ecaa3081b8dee90c4fb31e782e8e3107a77 (patch) | |
tree | e1ceb7ff6545709b26344cba562bb79f7c385d20 /fs/libfs.c | |
parent | KVM: x86: Use this_cpu_ptr() instead of per_cpu_ptr(smp_processor_id()) (diff) | |
parent | Merge branch kvm-arm64/visibility-cleanups into kvmarm-master/next (diff) | |
download | wireguard-linux-091b2ecaa3081b8dee90c4fb31e782e8e3107a77.tar.xz wireguard-linux-091b2ecaa3081b8dee90c4fb31e782e8e3107a77.zip |
Merge tag 'kvmarm-6.12' of git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm into HEAD
KVM/arm64 updates for 6.12
* New features:
- Add a Stage-2 page table dumper, reusing the main ptdump
infrastructure, and allowing easier debugging of the our
page-table infrastructure
- Add FP8 support to the KVM/arm64 floating point handling.
- Add NV support for the AT family of instructions, which mostly
results in adding a page table walker that deals with most of the
complexity of the architecture.
* Improvements, fixes and cleanups:
- Add selftest checks for a bunch of timer emulation corner cases
- Fix the multiple of cases where KVM/arm64 doesn't correctly handle
the guest trying to use a GICv3 that isn't advertised
- Remove REG_HIDDEN_USER from the sysreg infrastructure, making
things little more simple
- Prevent MTE tags being restored by userspace if we are actively
logging writes, as that's a recipe for disaster
- Correct the refcount on a page that is not considered for MTE tag
copying (such as a device)
- Relax the synchronisation when walking a page table to split block
mappings, moving it at the end the walk, as there is no need to
perform it on every store.
- Fix boundary check when transfering memory using FFA
- Fix pKVM TLB invalidation, only affecting currently out of tree
code but worth addressing for peace of mind
Diffstat (limited to 'fs/libfs.c')
-rw-r--r-- | fs/libfs.c | 35 |
1 files changed, 24 insertions, 11 deletions
diff --git a/fs/libfs.c b/fs/libfs.c index 8aa34870449f..02602d00939e 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -450,6 +450,14 @@ void simple_offset_destroy(struct offset_ctx *octx) mtree_destroy(&octx->mt); } +static int offset_dir_open(struct inode *inode, struct file *file) +{ + struct offset_ctx *ctx = inode->i_op->get_offset_ctx(inode); + + file->private_data = (void *)ctx->next_offset; + return 0; +} + /** * offset_dir_llseek - Advance the read position of a directory descriptor * @file: an open directory whose position is to be updated @@ -463,6 +471,9 @@ void simple_offset_destroy(struct offset_ctx *octx) */ static loff_t offset_dir_llseek(struct file *file, loff_t offset, int whence) { + struct inode *inode = file->f_inode; + struct offset_ctx *ctx = inode->i_op->get_offset_ctx(inode); + switch (whence) { case SEEK_CUR: offset += file->f_pos; @@ -476,7 +487,8 @@ static loff_t offset_dir_llseek(struct file *file, loff_t offset, int whence) } /* In this case, ->private_data is protected by f_pos_lock */ - file->private_data = NULL; + if (!offset) + file->private_data = (void *)ctx->next_offset; return vfs_setpos(file, offset, LONG_MAX); } @@ -507,7 +519,7 @@ static bool offset_dir_emit(struct dir_context *ctx, struct dentry *dentry) inode->i_ino, fs_umode_to_dtype(inode->i_mode)); } -static void *offset_iterate_dir(struct inode *inode, struct dir_context *ctx) +static void offset_iterate_dir(struct inode *inode, struct dir_context *ctx, long last_index) { struct offset_ctx *octx = inode->i_op->get_offset_ctx(inode); struct dentry *dentry; @@ -515,17 +527,21 @@ static void *offset_iterate_dir(struct inode *inode, struct dir_context *ctx) while (true) { dentry = offset_find_next(octx, ctx->pos); if (!dentry) - return ERR_PTR(-ENOENT); + return; + + if (dentry2offset(dentry) >= last_index) { + dput(dentry); + return; + } if (!offset_dir_emit(ctx, dentry)) { dput(dentry); - break; + return; } ctx->pos = dentry2offset(dentry) + 1; dput(dentry); } - return NULL; } /** @@ -552,22 +568,19 @@ static void *offset_iterate_dir(struct inode *inode, struct dir_context *ctx) static int offset_readdir(struct file *file, struct dir_context *ctx) { struct dentry *dir = file->f_path.dentry; + long last_index = (long)file->private_data; lockdep_assert_held(&d_inode(dir)->i_rwsem); if (!dir_emit_dots(file, ctx)) return 0; - /* In this case, ->private_data is protected by f_pos_lock */ - if (ctx->pos == DIR_OFFSET_MIN) - file->private_data = NULL; - else if (file->private_data == ERR_PTR(-ENOENT)) - return 0; - file->private_data = offset_iterate_dir(d_inode(dir), ctx); + offset_iterate_dir(d_inode(dir), ctx, last_index); return 0; } const struct file_operations simple_offset_dir_operations = { + .open = offset_dir_open, .llseek = offset_dir_llseek, .iterate_shared = offset_readdir, .read = generic_read_dir, |