fs: add generic_llseek_cookie()

This is similar to generic_file_llseek() but allows the caller to
specify a cookie that will be updated to indicate that a seek happened.
Caller's requiring that information in their readdir implementations can
use that.

Link: https://lore.kernel.org/r/20240830-vfs-file-f_version-v1-8-6d3e4816aa7b@kernel.org
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
Christian Brauner 2024-08-30 15:04:49 +02:00
parent ed904935c3
commit d688d65a84
No known key found for this signature in database
GPG Key ID: 91C61BC06578DCA2
2 changed files with 47 additions and 0 deletions

View File

@ -180,6 +180,51 @@ generic_file_llseek_size(struct file *file, loff_t offset, int whence,
}
EXPORT_SYMBOL(generic_file_llseek_size);
/**
* generic_llseek_cookie - versioned llseek implementation
* @file: file structure to seek on
* @offset: file offset to seek to
* @whence: type of seek
* @cookie: cookie to update
*
* See generic_file_llseek for a general description and locking assumptions.
*
* In contrast to generic_file_llseek, this function also resets a
* specified cookie to indicate a seek took place.
*/
loff_t generic_llseek_cookie(struct file *file, loff_t offset, int whence,
u64 *cookie)
{
struct inode *inode = file->f_mapping->host;
loff_t maxsize = inode->i_sb->s_maxbytes;
loff_t eof = i_size_read(inode);
int ret;
if (WARN_ON_ONCE(!cookie))
return -EINVAL;
/*
* Require that this is only used for directories that guarantee
* synchronization between readdir and seek so that an update to
* @cookie is correctly synchronized with concurrent readdir.
*/
if (WARN_ON_ONCE(!(file->f_mode & FMODE_ATOMIC_POS)))
return -EINVAL;
ret = must_set_pos(file, &offset, whence, eof);
if (ret < 0)
return ret;
if (ret == 0)
return offset;
/* No need to hold f_lock because we know that f_pos_lock is held. */
if (whence == SEEK_CUR)
return vfs_setpos_cookie(file, file->f_pos + offset, maxsize, cookie);
return vfs_setpos_cookie(file, offset, maxsize, cookie);
}
EXPORT_SYMBOL(generic_llseek_cookie);
/**
* generic_file_llseek - generic llseek implementation for regular files
* @file: file structure to seek on

View File

@ -3202,6 +3202,8 @@ extern loff_t vfs_setpos(struct file *file, loff_t offset, loff_t maxsize);
extern loff_t generic_file_llseek(struct file *file, loff_t offset, int whence);
extern loff_t generic_file_llseek_size(struct file *file, loff_t offset,
int whence, loff_t maxsize, loff_t eof);
loff_t generic_llseek_cookie(struct file *file, loff_t offset, int whence,
u64 *cookie);
extern loff_t fixed_size_llseek(struct file *file, loff_t offset,
int whence, loff_t size);
extern loff_t no_seek_end_llseek_size(struct file *, loff_t, int, loff_t);