* [PATCH v8 1/2] kernfs: sysfs: support custom llseek method for sysfs entries
@ 2023-09-22 12:06 Valentine Sinitsyn
2023-09-22 12:06 ` [PATCH v8 2/2] PCI: Implement custom llseek for sysfs resource entries Valentine Sinitsyn
2023-09-22 12:12 ` [PATCH v8 1/2] kernfs: sysfs: support custom llseek method for sysfs entries Valentin Sinitsyn
0 siblings, 2 replies; 10+ messages in thread
From: Valentine Sinitsyn @ 2023-09-22 12:06 UTC (permalink / raw)
To: Greg Kroah-Hartman, Tejun Heo, Rafael J. Wysocki, Bjorn Helgaas
Cc: Daniel Vetter, Dan Williams, linux-kernel, linux-pci
As of now, seeking in sysfs files is handled by generic_file_llseek().
There are situations where one may want to customize seeking logic:
- Many sysfs entries are fixed files while generic_file_llseek() accepts
past-the-end positions. Not only being useless by itself, this
also means a bug in userspace code will trigger not at lseek(), but at
some later point making debugging harder.
- generic_file_llseek() relies on f_mapping->host to get the file size
which might not be correct for all sysfs entries.
See commit 636b21b50152 ("PCI: Revoke mappings like devmem") as an example.
Implement llseek method to override this behavior at sysfs attribute
level. The method is optional, and if it is absent,
generic_file_llseek() is called to preserve backwards compatibility.
Cc: stable@vger.kernel.org
Signed-off-by: Valentine Sinitsyn <valesini@yandex-team.ru>
----
Perhaps this got burried to deep in the original thread [a],
resubmitting afresh.
a.
https://lore.kernel.org/all/20230814190850.948032-1-valesini@yandex-team.ru/
Changelog:
v8:
- This is real v7; previous v7 is a buggy earlier patch sent by
mistake
v7:
- Use proper locking in kernfs_fop_llseek()
v6:
- Mark pci_llseek_resource() as __maybe_unused
- Fix a typo in pci_create_legacy_files()
v5:
- Fix builds without PCI mmap support (e.g. Alpha)
v4:
- Fix builds which #define HAVE_PCI_LEGACY (e.g. PowerPC)
v3:
- Grammar fixes
- Add base-patch: and prerequisite-patch-id: to make kernel test
robot happy
v2:
- Add infrastructure to customize llseek per sysfs entry type
- Override llseek for PCI sysfs entries with fixed_file_llseek()--
fs/kernfs/file.c | 29 ++++++++++++++++++++++++++++-
fs/sysfs/file.c | 13 +++++++++++++
include/linux/kernfs.h | 1 +
include/linux/sysfs.h | 2 ++
4 files changed, 44 insertions(+), 1 deletion(-)
diff --git a/fs/kernfs/file.c b/fs/kernfs/file.c
index 180906c36f51..855e3f9d8dcc 100644
--- a/fs/kernfs/file.c
+++ b/fs/kernfs/file.c
@@ -903,6 +903,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;
@@ -1005,7 +1032,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,
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index a12ac0356c69..6b7652fb8050 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -167,6 +167,18 @@ static int sysfs_kf_bin_mmap(struct kernfs_open_file *of,
return battr->mmap(of->file, kobj, battr, vma);
}
+static loff_t sysfs_kf_bin_llseek(struct kernfs_open_file *of, loff_t offset,
+ int whence)
+{
+ struct bin_attribute *battr = of->kn->priv;
+ struct kobject *kobj = of->kn->parent->priv;
+
+ if (battr->llseek)
+ return battr->llseek(of->file, kobj, battr, offset, whence);
+ else
+ return generic_file_llseek(of->file, offset, whence);
+}
+
static int sysfs_kf_bin_open(struct kernfs_open_file *of)
{
struct bin_attribute *battr = of->kn->priv;
@@ -249,6 +261,7 @@ static const struct kernfs_ops sysfs_bin_kfops_mmap = {
.write = sysfs_kf_bin_write,
.mmap = sysfs_kf_bin_mmap,
.open = sysfs_kf_bin_open,
+ .llseek = sysfs_kf_bin_llseek,
};
int sysfs_add_file_mode_ns(struct kernfs_node *parent,
diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h
index 2a36f3218b51..99aaa050ccb7 100644
--- a/include/linux/kernfs.h
+++ b/include/linux/kernfs.h
@@ -316,6 +316,7 @@ struct kernfs_ops {
struct poll_table_struct *pt);
int (*mmap)(struct kernfs_open_file *of, struct vm_area_struct *vma);
+ loff_t (*llseek)(struct kernfs_open_file *of, loff_t offset, int whence);
};
/*
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index fd3fe5c8c17f..b717a70219f6 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -181,6 +181,8 @@ struct bin_attribute {
char *, loff_t, size_t);
ssize_t (*write)(struct file *, struct kobject *, struct bin_attribute *,
char *, loff_t, size_t);
+ loff_t (*llseek)(struct file *, struct kobject *, struct bin_attribute *,
+ loff_t, int);
int (*mmap)(struct file *, struct kobject *, struct bin_attribute *attr,
struct vm_area_struct *vma);
};
base-commit: a48fa7efaf1161c1c898931fe4c7f0070964233a
--
2.34.1
^ permalink raw reply [flat|nested] 10+ messages in thread* [PATCH v8 2/2] PCI: Implement custom llseek for sysfs resource entries
2023-09-22 12:06 [PATCH v8 1/2] kernfs: sysfs: support custom llseek method for sysfs entries Valentine Sinitsyn
@ 2023-09-22 12:06 ` Valentine Sinitsyn
2023-09-22 12:12 ` [PATCH v8 1/2] kernfs: sysfs: support custom llseek method for sysfs entries Valentin Sinitsyn
1 sibling, 0 replies; 10+ messages in thread
From: Valentine Sinitsyn @ 2023-09-22 12:06 UTC (permalink / raw)
To: Greg Kroah-Hartman, Tejun Heo, Rafael J. Wysocki, Bjorn Helgaas
Cc: Daniel Vetter, Dan Williams, linux-kernel, linux-pci
Since commit 636b21b50152 ("PCI: Revoke mappings like devmem"), mmappable
sysfs entries have started to receive their f_mapping from the iomem
pseudo filesystem, so that CONFIG_IO_STRICT_DEVMEM is honored in sysfs
(and procfs) as well as in /dev/[k]mem.
This resulted in a userspace-visible regression:
1. Open a sysfs PCI resource file (eg. /sys/bus/pci/devices/*/resource0)
2. Use lseek(fd, 0, SEEK_END) to determine its size
Expected result: a PCI region size is returned.
Actual result: 0 is returned.
The reason is that PCI resource files residing in sysfs use
generic_file_llseek(), which relies on f_mapping->host inode to get the
file size. As f_mapping is now redefined, f_mapping->host points to an
anonymous zero-sized iomem_inode which has nothing to do with sysfs file
in question.
Implement a custom llseek method for sysfs PCI resources, which is
almost the same as proc_bus_pci_lseek() used for procfs entries.
This makes sysfs and procfs entries consistent with regards to seeking,
but also introduces userspace-visible changes to seeking PCI resources
in sysfs:
- SEEK_DATA and SEEK_HOLE are no longer supported;
- Seeking past the end of the file is prohibited while previously
offsets up to MAX_NON_LFS were accepted (reading from these offsets
was always invalid).
Fixes: 636b21b50152 ("PCI: Revoke mappings like devmem")
Cc: stable@vger.kernel.org
Signed-off-by: Valentine Sinitsyn <valesini@yandex-team.ru>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
---
drivers/pci/pci-sysfs.c | 26 +++++++++++++++++++++++++-
1 file changed, 25 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index d9eede2dbc0e..97c9c62d5e3e 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -835,6 +835,19 @@ static const struct attribute_group pci_dev_config_attr_group = {
.is_bin_visible = pci_dev_config_attr_is_visible,
};
+/*
+ * llseek operation for mmappable PCI resources.
+ * May be left unused if the arch doesn't provide them.
+ */
+static __maybe_unused loff_t
+pci_llseek_resource(struct file *filep,
+ struct kobject *kobj __always_unused,
+ struct bin_attribute *attr,
+ loff_t offset, int whence)
+{
+ return fixed_size_llseek(filep, offset, whence, attr->size);
+}
+
#ifdef HAVE_PCI_LEGACY
/**
* pci_read_legacy_io - read byte(s) from legacy I/O port space
@@ -967,6 +980,8 @@ void pci_create_legacy_files(struct pci_bus *b)
b->legacy_io->attr.mode = 0600;
b->legacy_io->read = pci_read_legacy_io;
b->legacy_io->write = pci_write_legacy_io;
+ /* See pci_create_attr() for motivation */
+ b->legacy_io->llseek = pci_llseek_resource;
b->legacy_io->mmap = pci_mmap_legacy_io;
b->legacy_io->f_mapping = iomem_get_mapping;
pci_adjust_legacy_attr(b, pci_mmap_io);
@@ -981,6 +996,8 @@ void pci_create_legacy_files(struct pci_bus *b)
b->legacy_mem->size = 1024*1024;
b->legacy_mem->attr.mode = 0600;
b->legacy_mem->mmap = pci_mmap_legacy_mem;
+ /* See pci_create_attr() for motivation */
+ b->legacy_mem->llseek = pci_llseek_resource;
b->legacy_mem->f_mapping = iomem_get_mapping;
pci_adjust_legacy_attr(b, pci_mmap_mem);
error = device_create_bin_file(&b->dev, b->legacy_mem);
@@ -1199,8 +1216,15 @@ static int pci_create_attr(struct pci_dev *pdev, int num, int write_combine)
res_attr->mmap = pci_mmap_resource_uc;
}
}
- if (res_attr->mmap)
+ if (res_attr->mmap) {
res_attr->f_mapping = iomem_get_mapping;
+ /*
+ * generic_file_llseek() consults f_mapping->host to determine
+ * the file size. As iomem_inode knows nothing about the
+ * attribute, it's not going to work, so override it as well.
+ */
+ res_attr->llseek = pci_llseek_resource;
+ }
res_attr->attr.name = res_attr_name;
res_attr->attr.mode = 0600;
res_attr->size = pci_resource_len(pdev, num);
--
2.34.1
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [PATCH v8 1/2] kernfs: sysfs: support custom llseek method for sysfs entries
2023-09-22 12:06 [PATCH v8 1/2] kernfs: sysfs: support custom llseek method for sysfs entries Valentine Sinitsyn
2023-09-22 12:06 ` [PATCH v8 2/2] PCI: Implement custom llseek for sysfs resource entries Valentine Sinitsyn
@ 2023-09-22 12:12 ` Valentin Sinitsyn
2023-09-22 15:10 ` Greg KH
1 sibling, 1 reply; 10+ messages in thread
From: Valentin Sinitsyn @ 2023-09-22 12:12 UTC (permalink / raw)
To: valesini
Cc: bhelgaas, dan.j.williams, daniel.vetter, gregkh, linux-kernel,
linux-pci, rafael, tj
Obviously, the subject is meant to be [PATCH v8 x/2 RESEND].
Best,
Valentin
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v8 1/2] kernfs: sysfs: support custom llseek method for sysfs entries
2023-09-22 12:12 ` [PATCH v8 1/2] kernfs: sysfs: support custom llseek method for sysfs entries Valentin Sinitsyn
@ 2023-09-22 15:10 ` Greg KH
2023-09-25 8:40 ` [PATCH v9 " Valentine Sinitsyn
2023-09-25 8:40 ` [PATCH v9 2/2] PCI: Implement custom llseek for sysfs resource entries Valentine Sinitsyn
0 siblings, 2 replies; 10+ messages in thread
From: Greg KH @ 2023-09-22 15:10 UTC (permalink / raw)
To: Valentin Sinitsyn
Cc: bhelgaas, dan.j.williams, daniel.vetter, linux-kernel, linux-pci,
rafael, tj
On Fri, Sep 22, 2023 at 05:12:19PM +0500, Valentin Sinitsyn wrote:
> Obviously, the subject is meant to be [PATCH v8 x/2 RESEND].
Can you do a v9 then please?
I am behind in catching up on patches due to the merge window and then
travel, so please be patient. If you want to help out, please review
other pending patches to help yours move to the front.
thanks,
greg k-h
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v9 1/2] kernfs: sysfs: support custom llseek method for sysfs entries
2023-09-22 15:10 ` Greg KH
@ 2023-09-25 8:40 ` Valentine Sinitsyn
2023-09-25 8:40 ` [PATCH v9 2/2] PCI: Implement custom llseek for sysfs resource entries Valentine Sinitsyn
1 sibling, 0 replies; 10+ messages in thread
From: Valentine Sinitsyn @ 2023-09-25 8:40 UTC (permalink / raw)
To: Greg Kroah-Hartman, Tejun Heo, Rafael J. Wysocki, Bjorn Helgaas
Cc: Daniel Vetter, Dan Williams, linux-kernel, linux-pci
As of now, seeking in sysfs files is handled by generic_file_llseek().
There are situations where one may want to customize seeking logic:
- Many sysfs entries are fixed files while generic_file_llseek() accepts
past-the-end positions. Not only being useless by itself, this
also means a bug in userspace code will trigger not at lseek(), but at
some later point making debugging harder.
- generic_file_llseek() relies on f_mapping->host to get the file size
which might not be correct for all sysfs entries.
See commit 636b21b50152 ("PCI: Revoke mappings like devmem") as an example.
Implement llseek method to override this behavior at sysfs attribute
level. The method is optional, and if it is absent,
generic_file_llseek() is called to preserve backwards compatibility.
Cc: stable@vger.kernel.org
Signed-off-by: Valentine Sinitsyn <valesini@yandex-team.ru>
---
Changelog:
v9:
- Rebased on the latest Linus tree per GregKH's request
v8:
- This is real v7; previous v7 is a buggy earlier patch sent by
mistake
v7:
- Use proper locking in kernfs_fop_llseek()
v6:
- Mark pci_llseek_resource() as __maybe_unused
- Fix a typo in pci_create_legacy_files()
v5:
- Fix builds without PCI mmap support (e.g. Alpha)
v4:
- Fix builds which #define HAVE_PCI_LEGACY (e.g. PowerPC)
v3:
- Grammar fixes
- Add base-patch: and prerequisite-patch-id: to make kernel test
robot happy
v2:
- Add infrastructure to customize llseek per sysfs entry type
- Override llseek for PCI sysfs entries with fixed_file_llseek()--
fs/kernfs/file.c | 29 ++++++++++++++++++++++++++++-
fs/sysfs/file.c | 13 +++++++++++++
include/linux/kernfs.h | 1 +
include/linux/sysfs.h | 2 ++
4 files changed, 44 insertions(+), 1 deletion(-)
diff --git a/fs/kernfs/file.c b/fs/kernfs/file.c
index 180906c36f51..855e3f9d8dcc 100644
--- a/fs/kernfs/file.c
+++ b/fs/kernfs/file.c
@@ -903,6 +903,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;
@@ -1005,7 +1032,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,
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index a12ac0356c69..6b7652fb8050 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -167,6 +167,18 @@ static int sysfs_kf_bin_mmap(struct kernfs_open_file *of,
return battr->mmap(of->file, kobj, battr, vma);
}
+static loff_t sysfs_kf_bin_llseek(struct kernfs_open_file *of, loff_t offset,
+ int whence)
+{
+ struct bin_attribute *battr = of->kn->priv;
+ struct kobject *kobj = of->kn->parent->priv;
+
+ if (battr->llseek)
+ return battr->llseek(of->file, kobj, battr, offset, whence);
+ else
+ return generic_file_llseek(of->file, offset, whence);
+}
+
static int sysfs_kf_bin_open(struct kernfs_open_file *of)
{
struct bin_attribute *battr = of->kn->priv;
@@ -249,6 +261,7 @@ static const struct kernfs_ops sysfs_bin_kfops_mmap = {
.write = sysfs_kf_bin_write,
.mmap = sysfs_kf_bin_mmap,
.open = sysfs_kf_bin_open,
+ .llseek = sysfs_kf_bin_llseek,
};
int sysfs_add_file_mode_ns(struct kernfs_node *parent,
diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h
index 2a36f3218b51..99aaa050ccb7 100644
--- a/include/linux/kernfs.h
+++ b/include/linux/kernfs.h
@@ -316,6 +316,7 @@ struct kernfs_ops {
struct poll_table_struct *pt);
int (*mmap)(struct kernfs_open_file *of, struct vm_area_struct *vma);
+ loff_t (*llseek)(struct kernfs_open_file *of, loff_t offset, int whence);
};
/*
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index fd3fe5c8c17f..b717a70219f6 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -181,6 +181,8 @@ struct bin_attribute {
char *, loff_t, size_t);
ssize_t (*write)(struct file *, struct kobject *, struct bin_attribute *,
char *, loff_t, size_t);
+ loff_t (*llseek)(struct file *, struct kobject *, struct bin_attribute *,
+ loff_t, int);
int (*mmap)(struct file *, struct kobject *, struct bin_attribute *attr,
struct vm_area_struct *vma);
};
base-commit: 27bbf45eae9ca98877a2d52a92a188147cd61b07
--
2.34.1
^ permalink raw reply [flat|nested] 10+ messages in thread* [PATCH v9 2/2] PCI: Implement custom llseek for sysfs resource entries
2023-09-22 15:10 ` Greg KH
2023-09-25 8:40 ` [PATCH v9 " Valentine Sinitsyn
@ 2023-09-25 8:40 ` Valentine Sinitsyn
2023-10-05 11:41 ` Greg Kroah-Hartman
2023-10-05 18:16 ` Dan Williams
1 sibling, 2 replies; 10+ messages in thread
From: Valentine Sinitsyn @ 2023-09-25 8:40 UTC (permalink / raw)
To: Greg Kroah-Hartman, Tejun Heo, Rafael J. Wysocki, Bjorn Helgaas
Cc: Daniel Vetter, Dan Williams, linux-kernel, linux-pci
Since commit 636b21b50152 ("PCI: Revoke mappings like devmem"), mmappable
sysfs entries have started to receive their f_mapping from the iomem
pseudo filesystem, so that CONFIG_IO_STRICT_DEVMEM is honored in sysfs
(and procfs) as well as in /dev/[k]mem.
This resulted in a userspace-visible regression:
1. Open a sysfs PCI resource file (eg. /sys/bus/pci/devices/*/resource0)
2. Use lseek(fd, 0, SEEK_END) to determine its size
Expected result: a PCI region size is returned.
Actual result: 0 is returned.
The reason is that PCI resource files residing in sysfs use
generic_file_llseek(), which relies on f_mapping->host inode to get the
file size. As f_mapping is now redefined, f_mapping->host points to an
anonymous zero-sized iomem_inode which has nothing to do with sysfs file
in question.
Implement a custom llseek method for sysfs PCI resources, which is
almost the same as proc_bus_pci_lseek() used for procfs entries.
This makes sysfs and procfs entries consistent with regards to seeking,
but also introduces userspace-visible changes to seeking PCI resources
in sysfs:
- SEEK_DATA and SEEK_HOLE are no longer supported;
- Seeking past the end of the file is prohibited while previously
offsets up to MAX_NON_LFS were accepted (reading from these offsets
was always invalid).
Fixes: 636b21b50152 ("PCI: Revoke mappings like devmem")
Cc: stable@vger.kernel.org
Signed-off-by: Valentine Sinitsyn <valesini@yandex-team.ru>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
---
drivers/pci/pci-sysfs.c | 26 +++++++++++++++++++++++++-
1 file changed, 25 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index d9eede2dbc0e..97c9c62d5e3e 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -835,6 +835,19 @@ static const struct attribute_group pci_dev_config_attr_group = {
.is_bin_visible = pci_dev_config_attr_is_visible,
};
+/*
+ * llseek operation for mmappable PCI resources.
+ * May be left unused if the arch doesn't provide them.
+ */
+static __maybe_unused loff_t
+pci_llseek_resource(struct file *filep,
+ struct kobject *kobj __always_unused,
+ struct bin_attribute *attr,
+ loff_t offset, int whence)
+{
+ return fixed_size_llseek(filep, offset, whence, attr->size);
+}
+
#ifdef HAVE_PCI_LEGACY
/**
* pci_read_legacy_io - read byte(s) from legacy I/O port space
@@ -967,6 +980,8 @@ void pci_create_legacy_files(struct pci_bus *b)
b->legacy_io->attr.mode = 0600;
b->legacy_io->read = pci_read_legacy_io;
b->legacy_io->write = pci_write_legacy_io;
+ /* See pci_create_attr() for motivation */
+ b->legacy_io->llseek = pci_llseek_resource;
b->legacy_io->mmap = pci_mmap_legacy_io;
b->legacy_io->f_mapping = iomem_get_mapping;
pci_adjust_legacy_attr(b, pci_mmap_io);
@@ -981,6 +996,8 @@ void pci_create_legacy_files(struct pci_bus *b)
b->legacy_mem->size = 1024*1024;
b->legacy_mem->attr.mode = 0600;
b->legacy_mem->mmap = pci_mmap_legacy_mem;
+ /* See pci_create_attr() for motivation */
+ b->legacy_mem->llseek = pci_llseek_resource;
b->legacy_mem->f_mapping = iomem_get_mapping;
pci_adjust_legacy_attr(b, pci_mmap_mem);
error = device_create_bin_file(&b->dev, b->legacy_mem);
@@ -1199,8 +1216,15 @@ static int pci_create_attr(struct pci_dev *pdev, int num, int write_combine)
res_attr->mmap = pci_mmap_resource_uc;
}
}
- if (res_attr->mmap)
+ if (res_attr->mmap) {
res_attr->f_mapping = iomem_get_mapping;
+ /*
+ * generic_file_llseek() consults f_mapping->host to determine
+ * the file size. As iomem_inode knows nothing about the
+ * attribute, it's not going to work, so override it as well.
+ */
+ res_attr->llseek = pci_llseek_resource;
+ }
res_attr->attr.name = res_attr_name;
res_attr->attr.mode = 0600;
res_attr->size = pci_resource_len(pdev, num);
--
2.34.1
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [PATCH v9 2/2] PCI: Implement custom llseek for sysfs resource entries
2023-09-25 8:40 ` [PATCH v9 2/2] PCI: Implement custom llseek for sysfs resource entries Valentine Sinitsyn
@ 2023-10-05 11:41 ` Greg Kroah-Hartman
2023-10-08 21:51 ` Valentin Sinitsyn
2023-10-05 18:16 ` Dan Williams
1 sibling, 1 reply; 10+ messages in thread
From: Greg Kroah-Hartman @ 2023-10-05 11:41 UTC (permalink / raw)
To: Valentine Sinitsyn
Cc: Tejun Heo, Rafael J. Wysocki, Bjorn Helgaas, Daniel Vetter,
Dan Williams, linux-kernel, linux-pci
On Mon, Sep 25, 2023 at 11:40:13AM +0300, Valentine Sinitsyn wrote:
> Since commit 636b21b50152 ("PCI: Revoke mappings like devmem"), mmappable
> sysfs entries have started to receive their f_mapping from the iomem
> pseudo filesystem, so that CONFIG_IO_STRICT_DEVMEM is honored in sysfs
> (and procfs) as well as in /dev/[k]mem.
>
> This resulted in a userspace-visible regression:
>
> 1. Open a sysfs PCI resource file (eg. /sys/bus/pci/devices/*/resource0)
> 2. Use lseek(fd, 0, SEEK_END) to determine its size
>
> Expected result: a PCI region size is returned.
> Actual result: 0 is returned.
>
> The reason is that PCI resource files residing in sysfs use
> generic_file_llseek(), which relies on f_mapping->host inode to get the
> file size. As f_mapping is now redefined, f_mapping->host points to an
> anonymous zero-sized iomem_inode which has nothing to do with sysfs file
> in question.
>
> Implement a custom llseek method for sysfs PCI resources, which is
> almost the same as proc_bus_pci_lseek() used for procfs entries.
>
> This makes sysfs and procfs entries consistent with regards to seeking,
> but also introduces userspace-visible changes to seeking PCI resources
> in sysfs:
>
> - SEEK_DATA and SEEK_HOLE are no longer supported;
> - Seeking past the end of the file is prohibited while previously
> offsets up to MAX_NON_LFS were accepted (reading from these offsets
> was always invalid).
>
> Fixes: 636b21b50152 ("PCI: Revoke mappings like devmem")
> Cc: stable@vger.kernel.org
> Signed-off-by: Valentine Sinitsyn <valesini@yandex-team.ru>
> Acked-by: Bjorn Helgaas <bhelgaas@google.com>
> ---
> drivers/pci/pci-sysfs.c | 26 +++++++++++++++++++++++++-
> 1 file changed, 25 insertions(+), 1 deletion(-)
I'll take these now, for 6.7-rc1, but not mark them as fixes or cc:
stable as this is a new functionality, the code has never worked for
lseek on these files so it's not like anything was broken :)
thanks,
greg k-h
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [PATCH v9 2/2] PCI: Implement custom llseek for sysfs resource entries
2023-10-05 11:41 ` Greg Kroah-Hartman
@ 2023-10-08 21:51 ` Valentin Sinitsyn
0 siblings, 0 replies; 10+ messages in thread
From: Valentin Sinitsyn @ 2023-10-08 21:51 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: Tejun Heo, Rafael J. Wysocki, Bjorn Helgaas, Daniel Vetter,
Dan Williams, linux-kernel, linux-pci
On 05.10.2023 16:41, Greg Kroah-Hartman wrote:
> On Mon, Sep 25, 2023 at 11:40:13AM +0300, Valentine Sinitsyn wrote:
>> Since commit 636b21b50152 ("PCI: Revoke mappings like devmem"), mmappable
>> sysfs entries have started to receive their f_mapping from the iomem
>> pseudo filesystem, so that CONFIG_IO_STRICT_DEVMEM is honored in sysfs
>> (and procfs) as well as in /dev/[k]mem.
>>
>> This resulted in a userspace-visible regression:
>>
>> 1. Open a sysfs PCI resource file (eg. /sys/bus/pci/devices/*/resource0)
>> 2. Use lseek(fd, 0, SEEK_END) to determine its size
>>
>> Expected result: a PCI region size is returned.
>> Actual result: 0 is returned.
>>
>> The reason is that PCI resource files residing in sysfs use
>> generic_file_llseek(), which relies on f_mapping->host inode to get the
>> file size. As f_mapping is now redefined, f_mapping->host points to an
>> anonymous zero-sized iomem_inode which has nothing to do with sysfs file
>> in question.
>>
>> Implement a custom llseek method for sysfs PCI resources, which is
>> almost the same as proc_bus_pci_lseek() used for procfs entries.
>>
>> This makes sysfs and procfs entries consistent with regards to seeking,
>> but also introduces userspace-visible changes to seeking PCI resources
>> in sysfs:
>>
>> - SEEK_DATA and SEEK_HOLE are no longer supported;
>> - Seeking past the end of the file is prohibited while previously
>> offsets up to MAX_NON_LFS were accepted (reading from these offsets
>> was always invalid).
>>
>> Fixes: 636b21b50152 ("PCI: Revoke mappings like devmem")
>> Cc: stable@vger.kernel.org
>> Signed-off-by: Valentine Sinitsyn <valesini@yandex-team.ru>
>> Acked-by: Bjorn Helgaas <bhelgaas@google.com>
>> ---
>> drivers/pci/pci-sysfs.c | 26 +++++++++++++++++++++++++-
>> 1 file changed, 25 insertions(+), 1 deletion(-)
>
> I'll take these now, for 6.7-rc1, but not mark them as fixes or cc:
Thanks, appreciated.
> stable as this is a new functionality, the code has never worked for
> lseek on these files so it's not like anything was broken :)
In fact, lseek() on PCI resource files in sysfs was broken since commit
636b21b50152. That was the reason why I started to investigate the
issue: one of our applications stopped working after a kernel update.
I'm not hundred percent sure if it belongs to stable, but it does fix a
user-visible regression.
Best,
Valentin
^ permalink raw reply [flat|nested] 10+ messages in thread
* RE: [PATCH v9 2/2] PCI: Implement custom llseek for sysfs resource entries
2023-09-25 8:40 ` [PATCH v9 2/2] PCI: Implement custom llseek for sysfs resource entries Valentine Sinitsyn
2023-10-05 11:41 ` Greg Kroah-Hartman
@ 2023-10-05 18:16 ` Dan Williams
1 sibling, 0 replies; 10+ messages in thread
From: Dan Williams @ 2023-10-05 18:16 UTC (permalink / raw)
To: Valentine Sinitsyn, Greg Kroah-Hartman, Tejun Heo,
Rafael J. Wysocki, Bjorn Helgaas
Cc: Daniel Vetter, Dan Williams, linux-kernel, linux-pci
Valentine Sinitsyn wrote:
> Since commit 636b21b50152 ("PCI: Revoke mappings like devmem"), mmappable
> sysfs entries have started to receive their f_mapping from the iomem
> pseudo filesystem, so that CONFIG_IO_STRICT_DEVMEM is honored in sysfs
> (and procfs) as well as in /dev/[k]mem.
>
> This resulted in a userspace-visible regression:
>
> 1. Open a sysfs PCI resource file (eg. /sys/bus/pci/devices/*/resource0)
> 2. Use lseek(fd, 0, SEEK_END) to determine its size
>
> Expected result: a PCI region size is returned.
> Actual result: 0 is returned.
>
> The reason is that PCI resource files residing in sysfs use
> generic_file_llseek(), which relies on f_mapping->host inode to get the
> file size. As f_mapping is now redefined, f_mapping->host points to an
> anonymous zero-sized iomem_inode which has nothing to do with sysfs file
> in question.
>
> Implement a custom llseek method for sysfs PCI resources, which is
> almost the same as proc_bus_pci_lseek() used for procfs entries.
>
> This makes sysfs and procfs entries consistent with regards to seeking,
> but also introduces userspace-visible changes to seeking PCI resources
> in sysfs:
>
> - SEEK_DATA and SEEK_HOLE are no longer supported;
> - Seeking past the end of the file is prohibited while previously
> offsets up to MAX_NON_LFS were accepted (reading from these offsets
> was always invalid).
>
> Fixes: 636b21b50152 ("PCI: Revoke mappings like devmem")
> Cc: stable@vger.kernel.org
> Signed-off-by: Valentine Sinitsyn <valesini@yandex-team.ru>
> Acked-by: Bjorn Helgaas <bhelgaas@google.com>
Thanks for doing this reorganization and the follow-up, looks good to me:
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v6 1/2] kernfs: sysfs: support custom llseek method for sysfs entries
@ 2023-09-05 7:02 kernel test robot
2023-09-08 13:56 ` [PATCH v8 " Valentine Sinitsyn
0 siblings, 1 reply; 10+ messages in thread
From: kernel test robot @ 2023-09-05 7:02 UTC (permalink / raw)
To: Valentine Sinitsyn
Cc: oe-lkp, lkp, linux-fsdevel, linux-kernel, Greg Kroah-Hartman,
Tejun Heo, Bjorn Helgaas, Daniel Vetter, Dan Williams,
oliver.sang
Hello,
kernel test robot noticed "WARNING:at_fs/kernfs/file.c:#kernfs_ops" on:
commit: c6eefad61209dab3de7446cf8151d38e70440484 ("[PATCH v6 1/2] kernfs: sysfs: support custom llseek method for sysfs entries")
url: https://github.com/intel-lab-lkp/linux/commits/Valentine-Sinitsyn/PCI-Implement-custom-llseek-for-sysfs-resource-entries/20230902-235234
patch link: https://lore.kernel.org/all/20230902155038.1661970-1-valesini@yandex-team.ru/
patch subject: [PATCH v6 1/2] kernfs: sysfs: support custom llseek method for sysfs entries
in testcase: boot
compiler: clang-16
test machine: qemu-system-x86_64 -enable-kvm -cpu SandyBridge -smp 2 -m 16G
(please refer to attached dmesg/kmsg for entire log/backtrace)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <oliver.sang@intel.com>
| Closes: https://lore.kernel.org/oe-lkp/202309051442.bd6f9879-oliver.sang@intel.com
[ 96.320907][ T252] ------------[ cut here ]------------
[ 96.321715][ T252] WARNING: CPU: 1 PID: 252 at fs/kernfs/file.c:109 kernfs_ops (fs/kernfs/file.c:109)
[ 96.322853][ T252] Modules linked in:
[ 96.323438][ T252] CPU: 1 PID: 252 Comm: systemd-logind Not tainted 6.5.0-10888-gc6eefad61209 #1
[ 96.324966][ T252] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.2-debian-1.16.2-1 04/01/2014
[ 96.326330][ T252] RIP: 0010:kernfs_ops (fs/kernfs/file.c:109)
[ 96.327026][ T252] Code: 48 83 c3 68 48 89 d8 48 c1 e8 03 42 80 3c 38 00 74 08 48 89 df e8 de f3 e2 ff 48 8b 03 5b 41 5e 41 5f 31 c9 31 ff 31 f6 c3 cc <0f> 0b eb d2 44 89 f1 80 e1 07 fe c1 38 c1 7c 91 4c 89 f7 e8 76 f3
All code
========
0: 48 83 c3 68 add $0x68,%rbx
4: 48 89 d8 mov %rbx,%rax
7: 48 c1 e8 03 shr $0x3,%rax
b: 42 80 3c 38 00 cmpb $0x0,(%rax,%r15,1)
10: 74 08 je 0x1a
12: 48 89 df mov %rbx,%rdi
15: e8 de f3 e2 ff call 0xffffffffffe2f3f8
1a: 48 8b 03 mov (%rbx),%rax
1d: 5b pop %rbx
1e: 41 5e pop %r14
20: 41 5f pop %r15
22: 31 c9 xor %ecx,%ecx
24: 31 ff xor %edi,%edi
26: 31 f6 xor %esi,%esi
28: c3 ret
29: cc int3
2a:* 0f 0b ud2 <-- trapping instruction
2c: eb d2 jmp 0x0
2e: 44 89 f1 mov %r14d,%ecx
31: 80 e1 07 and $0x7,%cl
34: fe c1 inc %cl
36: 38 c1 cmp %al,%cl
38: 7c 91 jl 0xffffffffffffffcb
3a: 4c 89 f7 mov %r14,%rdi
3d: e8 .byte 0xe8
3e: 76 f3 jbe 0x33
Code starting with the faulting instruction
===========================================
0: 0f 0b ud2
2: eb d2 jmp 0xffffffffffffffd6
4: 44 89 f1 mov %r14d,%ecx
7: 80 e1 07 and $0x7,%cl
a: fe c1 inc %cl
c: 38 c1 cmp %al,%cl
e: 7c 91 jl 0xffffffffffffffa1
10: 4c 89 f7 mov %r14,%rdi
13: e8 .byte 0xe8
14: 76 f3 jbe 0x9
[ 96.329439][ T252] RSP: 0018:ffff8881638e7ea0 EFLAGS: 00010246
[ 96.330261][ T252] RAX: 0000000000000000 RBX: ffff888111e4a2b8 RCX: 0000000000000000
[ 96.331346][ T252] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
[ 96.332425][ T252] RBP: dffffc0000000000 R08: 0000000000000000 R09: 0000000000000000
[ 96.333503][ T252] R10: 0000000000000000 R11: ffffffff8184fd65 R12: ffff8881538a5c00
[ 96.334649][ T252] R13: ffff888161bc5ec0 R14: ffff888111e4a350 R15: dffffc0000000000
[ 96.335717][ T252] FS: 00007f2d9c6a8980(0000) GS:ffff8883aeb00000(0000) knlGS:0000000000000000
[ 96.336833][ T252] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 96.337593][ T252] CR2: 00005600c8ef1595 CR3: 0000000162f96000 CR4: 00000000000406a0
[ 96.338544][ T252] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[ 96.339487][ T252] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
[ 96.340472][ T252] Call Trace:
[ 96.340983][ T252] <TASK>
[ 96.341447][ T252] ? __warn (kernel/panic.c:673)
[ 96.342078][ T252] ? kernfs_ops (fs/kernfs/file.c:109)
[ 96.342740][ T252] ? kernfs_ops (fs/kernfs/file.c:109)
[ 96.343391][ T252] ? report_bug (lib/bug.c:?)
[ 96.344046][ T252] ? find_held_lock (kernel/locking/lockdep.c:?)
[ 96.344738][ T252] ? handle_bug (arch/x86/kernel/traps.c:237)
[ 96.345314][ T252] ? exc_invalid_op (arch/x86/kernel/traps.c:258)
[ 96.345963][ T252] ? asm_exc_invalid_op (arch/x86/include/asm/idtentry.h:568)
[ 96.346694][ T252] ? __cfi_kernfs_fop_llseek (fs/kernfs/file.c:907)
[ 96.347473][ T252] ? kernfs_ops (fs/kernfs/file.c:109)
[ 96.348135][ T252] kernfs_fop_llseek (fs/kernfs/file.c:911)
[ 96.348869][ T252] ksys_lseek (fs/read_write.c:289)
[ 96.349497][ T252] do_syscall_64 (arch/x86/entry/common.c:?)
[ 96.350141][ T252] entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:120)
[ 96.350952][ T252] RIP: 0033:0x7f2d9cf82fc7
[ 96.351602][ T252] Code: c7 c0 ff ff ff ff c3 0f 1f 40 00 48 8b 15 c1 ee 0c 00 f7 d8 64 89 02 48 c7 c0 ff ff ff ff eb ba 0f 1f 00 b8 08 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 01 c3 48 8b 15 99 ee 0c 00 f7 d8 64 89 02 48
All code
========
0: c7 c0 ff ff ff ff mov $0xffffffff,%eax
6: c3 ret
7: 0f 1f 40 00 nopl 0x0(%rax)
b: 48 8b 15 c1 ee 0c 00 mov 0xceec1(%rip),%rdx # 0xceed3
12: f7 d8 neg %eax
14: 64 89 02 mov %eax,%fs:(%rdx)
17: 48 c7 c0 ff ff ff ff mov $0xffffffffffffffff,%rax
1e: eb ba jmp 0xffffffffffffffda
20: 0f 1f 00 nopl (%rax)
23: b8 08 00 00 00 mov $0x8,%eax
28: 0f 05 syscall
2a:* 48 3d 00 f0 ff ff cmp $0xfffffffffffff000,%rax <-- trapping instruction
30: 77 01 ja 0x33
32: c3 ret
33: 48 8b 15 99 ee 0c 00 mov 0xcee99(%rip),%rdx # 0xceed3
3a: f7 d8 neg %eax
3c: 64 89 02 mov %eax,%fs:(%rdx)
3f: 48 rex.W
Code starting with the faulting instruction
===========================================
0: 48 3d 00 f0 ff ff cmp $0xfffffffffffff000,%rax
6: 77 01 ja 0x9
8: c3 ret
9: 48 8b 15 99 ee 0c 00 mov 0xcee99(%rip),%rdx # 0xceea9
10: f7 d8 neg %eax
12: 64 89 02 mov %eax,%fs:(%rdx)
15: 48 rex.W
[ 96.357571][ T252] RSP: 002b:00007fff4e4c3fc8 EFLAGS: 00000246 ORIG_RAX: 0000000000000008
[ 96.358740][ T252] RAX: ffffffffffffffda RBX: 0000563f1ffa0a80 RCX: 00007f2d9cf82fc7
[ 96.359842][ T252] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000007
[ 96.360873][ T252] RBP: 0000563f1ffa0a80 R08: 00007fff4e4c3fc0 R09: 0000000000000000
[ 96.361934][ T252] R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000001
[ 96.363024][ T252] R13: 0000000000000000 R14: 00007fff4e4c4188 R15: 00007fff4e4c41a0
[ 96.364155][ T252] </TASK>
[ 96.364719][ T252] irq event stamp: 64209
[ 96.365341][ T252] hardirqs last enabled at (64219): __up_console_sem (arch/x86/include/asm/irqflags.h:26 arch/x86/include/asm/irqflags.h:67 arch/x86/include/asm/irqflags.h:127 kernel/printk/printk.c:347)
[ 96.366558][ T252] hardirqs last disabled at (64228): __up_console_sem (kernel/printk/printk.c:345)
[ 96.367774][ T252] softirqs last enabled at (64128): __do_softirq (arch/x86/include/asm/preempt.h:27 kernel/softirq.c:400 kernel/softirq.c:582)
[ 96.368971][ T252] softirqs last disabled at (64119): __irq_exit_rcu (kernel/softirq.c:612)
[ 96.370158][ T252] ---[ end trace 0000000000000000 ]---
Starting LKP bootstrap...
Starting /etc/rc.local Compatibility...
Starting OpenBSD Secure Shell server...
Starting Permit User Sessions...
[FAILED] Failed to start LSB: OpenIPMI Driver init script.
See 'systemctl status openipmi.service' for details.
[ OK ] Started User Login Management.
[ OK ] Started LKP bootstrap.
[ OK ] Started LSB: Load kernel image with kexec.
LKP: ttyS0: 296: skip deploy intel ucode as no ucode is specified
[ OK ] Finished Permit User Sessions.
[ OK ] Started OpenBSD Secure Shell server.
LKP: ttyS0: 296: Kernel tests: Boot OK!
LKP: ttyS0: 296: HOSTNAME vm-snb, MAC 52:54:00:12:34:56, kernel 6.5.0-10888-gc6eefad61209 1
LKP: ttyS0: 296: /lkp/lkp/src/bin/run-lkp /lkp/jobs/scheduled/vm-meta-300/boot-1-debian-11.1-x86_64-20220510.cgz-x86_64-randconfig-071-20230903-c6eefad61209-20230903-11038-o17p1l-0.yaml
[ 104.602900][ T165] kmemleak: Automatic memory scanning thread ended
[ OK ] Started System Logging Service.
[ 106.970306][ T310] is_virt=true
[ 106.970347][ T310]
[ 108.079565][ T310] lkp: kernel tainted state: 512
[ 108.079600][ T310]
[ 108.704632][ T310] LKP: stdout: 296: Kernel tests: Boot OK!
[ 108.704672][ T310]
[ 112.730026][ T310] LKP: stdout: 296: HOSTNAME vm-snb, MAC 52:54:00:12:34:56, kernel 6.5.0-10888-gc6eefad61209 1
[ 112.730070][ T310]
[ 112.732401][ T310] NO_NETWORK=
[ 112.732437][ T310]
[ 118.521298][ T310] LKP: stdout: 296: /lkp/lkp/src/bin/run-lkp /lkp/jobs/scheduled/vm-meta-300/boot-1-debian-11.1-x86_64-20220510.cgz-x86_64-randconfig-071-20230903-c6eefad61209-20230903-11038-o17p1l-0.yaml
[ 118.521368][ T310]
[ 118.537313][ T310] RESULT_ROOT=/result/boot/1/vm-snb/debian-11.1-x86_64-20220510.cgz/x86_64-randconfig-071-20230903/clang-16/c6eefad61209dab3de7446cf8151d38e70440484/0
[ 118.537382][ T310]
[ 118.542693][ T310] job=/lkp/jobs/scheduled/vm-meta-300/boot-1-debian-11.1-x86_64-20220510.cgz-x86_64-randconfig-071-20230903-c6eefad61209-20230903-11038-o17p1l-0.yaml
The kernel config and materials to reproduce are available at:
https://download.01.org/0day-ci/archive/20230905/202309051442.bd6f9879-oliver.sang@intel.com
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 10+ messages in thread* [PATCH v8 1/2] kernfs: sysfs: support custom llseek method for sysfs entries
2023-09-05 7:02 [PATCH v6 1/2] kernfs: sysfs: support custom llseek method for sysfs entries kernel test robot
@ 2023-09-08 13:56 ` Valentine Sinitsyn
0 siblings, 0 replies; 10+ messages in thread
From: Valentine Sinitsyn @ 2023-09-08 13:56 UTC (permalink / raw)
To: Greg Kroah-Hartman, Tejun Heo
Cc: Daniel Vetter, Bjorn Helgaas, Dan Williams, linux-kernel
As of now, seeking in sysfs files is handled by generic_file_llseek().
There are situations where one may want to customize seeking logic:
- Many sysfs entries are fixed files while generic_file_llseek() accepts
past-the-end positions. Not only being useless by itself, this
also means a bug in userspace code will trigger not at lseek(), but at
some later point making debugging harder.
- generic_file_llseek() relies on f_mapping->host to get the file size
which might not be correct for all sysfs entries.
See commit 636b21b50152 ("PCI: Revoke mappings like devmem") as an example.
Implement llseek method to override this behavior at sysfs attribute
level. The method is optional, and if it is absent,
generic_file_llseek() is called to preserve backwards compatibility.
Cc: stable@vger.kernel.org
Signed-off-by: Valentine Sinitsyn <valesini@yandex-team.ru>
----
v8:
- This is real v7; previous v7 is a buggy earlier patch sent by
mistake
v7:
- Use proper locking in kernfs_fop_llseek()
v6:
- Mark pci_llseek_resource() as __maybe_unused
- Fix a typo in pci_create_legacy_files()
v5:
- Fix builds without PCI mmap support (e.g. Alpha)
v4:
- Fix builds which #define HAVE_PCI_LEGACY (e.g. PowerPC)
v3:
- Grammar fixes
- Add base-patch: and prerequisite-patch-id: to make kernel test
robot happy
v2:
- Add infrastructure to customize llseek per sysfs entry type
- Override llseek for PCI sysfs entries with fixed_file_llseek()--
fs/kernfs/file.c | 29 ++++++++++++++++++++++++++++-
fs/sysfs/file.c | 13 +++++++++++++
include/linux/kernfs.h | 1 +
include/linux/sysfs.h | 2 ++
4 files changed, 44 insertions(+), 1 deletion(-)
diff --git a/fs/kernfs/file.c b/fs/kernfs/file.c
index 180906c36f51..855e3f9d8dcc 100644
--- a/fs/kernfs/file.c
+++ b/fs/kernfs/file.c
@@ -903,6 +903,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;
@@ -1005,7 +1032,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,
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index a12ac0356c69..6b7652fb8050 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -167,6 +167,18 @@ static int sysfs_kf_bin_mmap(struct kernfs_open_file *of,
return battr->mmap(of->file, kobj, battr, vma);
}
+static loff_t sysfs_kf_bin_llseek(struct kernfs_open_file *of, loff_t offset,
+ int whence)
+{
+ struct bin_attribute *battr = of->kn->priv;
+ struct kobject *kobj = of->kn->parent->priv;
+
+ if (battr->llseek)
+ return battr->llseek(of->file, kobj, battr, offset, whence);
+ else
+ return generic_file_llseek(of->file, offset, whence);
+}
+
static int sysfs_kf_bin_open(struct kernfs_open_file *of)
{
struct bin_attribute *battr = of->kn->priv;
@@ -249,6 +261,7 @@ static const struct kernfs_ops sysfs_bin_kfops_mmap = {
.write = sysfs_kf_bin_write,
.mmap = sysfs_kf_bin_mmap,
.open = sysfs_kf_bin_open,
+ .llseek = sysfs_kf_bin_llseek,
};
int sysfs_add_file_mode_ns(struct kernfs_node *parent,
diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h
index 2a36f3218b51..99aaa050ccb7 100644
--- a/include/linux/kernfs.h
+++ b/include/linux/kernfs.h
@@ -316,6 +316,7 @@ struct kernfs_ops {
struct poll_table_struct *pt);
int (*mmap)(struct kernfs_open_file *of, struct vm_area_struct *vma);
+ loff_t (*llseek)(struct kernfs_open_file *of, loff_t offset, int whence);
};
/*
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index fd3fe5c8c17f..b717a70219f6 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -181,6 +181,8 @@ struct bin_attribute {
char *, loff_t, size_t);
ssize_t (*write)(struct file *, struct kobject *, struct bin_attribute *,
char *, loff_t, size_t);
+ loff_t (*llseek)(struct file *, struct kobject *, struct bin_attribute *,
+ loff_t, int);
int (*mmap)(struct file *, struct kobject *, struct bin_attribute *attr,
struct vm_area_struct *vma);
};
base-commit: a48fa7efaf1161c1c898931fe4c7f0070964233a
--
2.34.1
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2023-10-08 21:51 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-09-22 12:06 [PATCH v8 1/2] kernfs: sysfs: support custom llseek method for sysfs entries Valentine Sinitsyn
2023-09-22 12:06 ` [PATCH v8 2/2] PCI: Implement custom llseek for sysfs resource entries Valentine Sinitsyn
2023-09-22 12:12 ` [PATCH v8 1/2] kernfs: sysfs: support custom llseek method for sysfs entries Valentin Sinitsyn
2023-09-22 15:10 ` Greg KH
2023-09-25 8:40 ` [PATCH v9 " Valentine Sinitsyn
2023-09-25 8:40 ` [PATCH v9 2/2] PCI: Implement custom llseek for sysfs resource entries Valentine Sinitsyn
2023-10-05 11:41 ` Greg Kroah-Hartman
2023-10-08 21:51 ` Valentin Sinitsyn
2023-10-05 18:16 ` Dan Williams
-- strict thread matches above, loose matches on Subject: below --
2023-09-05 7:02 [PATCH v6 1/2] kernfs: sysfs: support custom llseek method for sysfs entries kernel test robot
2023-09-08 13:56 ` [PATCH v8 " Valentine Sinitsyn
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®