Merge tag 'driver-core-6.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-microblaze.git] / fs / kernfs / file.c
index aaa7641..f0cb729 100644 (file)
@@ -854,6 +854,33 @@ static __poll_t kernfs_fop_poll(struct file *filp, poll_table *wait)
        return ret;
 }
 
+static loff_t kernfs_fop_llseek(struct file *file, loff_t offset, int whence)
+{
+       struct kernfs_open_file *of = kernfs_of(file);
+       const struct kernfs_ops *ops;
+       loff_t ret;
+
+       /*
+        * @of->mutex nests outside active ref and is primarily to ensure that
+        * the ops aren't called concurrently for the same open file.
+        */
+       mutex_lock(&of->mutex);
+       if (!kernfs_get_active(of->kn)) {
+               mutex_unlock(&of->mutex);
+               return -ENODEV;
+       }
+
+       ops = kernfs_ops(of->kn);
+       if (ops->llseek)
+               ret = ops->llseek(of, offset, whence);
+       else
+               ret = generic_file_llseek(file, offset, whence);
+
+       kernfs_put_active(of->kn);
+       mutex_unlock(&of->mutex);
+       return ret;
+}
+
 static void kernfs_notify_workfn(struct work_struct *work)
 {
        struct kernfs_node *kn;
@@ -956,7 +983,7 @@ EXPORT_SYMBOL_GPL(kernfs_notify);
 const struct file_operations kernfs_file_fops = {
        .read_iter      = kernfs_fop_read_iter,
        .write_iter     = kernfs_fop_write_iter,
-       .llseek         = generic_file_llseek,
+       .llseek         = kernfs_fop_llseek,
        .mmap           = kernfs_fop_mmap,
        .open           = kernfs_fop_open,
        .release        = kernfs_fop_release,