On Fri 30-08-24 15:04:49, Christian Brauner wrote: > 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. > > Signed-off-by: Christian Brauner <brauner@xxxxxxxxxx> Looks good. Feel free to add: Reviewed-by: Jan Kara <jack@xxxxxxx> Honza > --- > fs/read_write.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ > include/linux/fs.h | 2 ++ > 2 files changed, 46 insertions(+) > > diff --git a/fs/read_write.c b/fs/read_write.c > index ad93b72cc378..47f7b4e32a53 100644 > --- a/fs/read_write.c > +++ b/fs/read_write.c > @@ -179,6 +179,50 @@ 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; > + > + ret = must_set_pos(file, &offset, whence, eof); > + if (ret < 0) > + return ret; > + if (ret == 0) > + return offset; > + > + if (whence == SEEK_CUR) { > + /* > + * f_lock protects against read/modify/write race with > + * other SEEK_CURs. Note that parallel writes and reads > + * behave like SEEK_SET. > + */ > + guard(spinlock)(&file->f_lock); > + 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 > diff --git a/include/linux/fs.h b/include/linux/fs.h > index 58c91a52cad1..3e6b3c1afb31 100644 > --- a/include/linux/fs.h > +++ b/include/linux/fs.h > @@ -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); > > -- > 2.45.2 > -- Jan Kara <jack@xxxxxxxx> SUSE Labs, CR