summaryrefslogtreecommitdiffstats
path: root/fs/kernfs/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/kernfs/file.c')
-rw-r--r--fs/kernfs/file.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/fs/kernfs/file.c b/fs/kernfs/file.c
index 4a5863b79de9..fa053151fa96 100644
--- a/fs/kernfs/file.c
+++ b/fs/kernfs/file.c
@@ -421,6 +421,16 @@ static int kernfs_file_mmap(struct file *file, struct vm_area_struct *vma)
const struct kernfs_ops *ops;
int rc;
+ /*
+ * mmap path and of->mutex are prone to triggering spurious lockdep
+ * warnings and we don't want to add spurious locking dependency
+ * between the two. Check whether mmap is actually implemented
+ * without grabbing @of->mutex by testing HAS_MMAP flag. See the
+ * comment in kernfs_file_open() for more details.
+ */
+ if (!(of->sd->s_flags & SYSFS_FLAG_HAS_MMAP))
+ return -ENODEV;
+
mutex_lock(&of->mutex);
rc = -ENODEV;
@@ -428,10 +438,7 @@ static int kernfs_file_mmap(struct file *file, struct vm_area_struct *vma)
goto out_unlock;
ops = kernfs_ops(of->sd);
- if (ops->mmap)
- rc = ops->mmap(of, vma);
- if (rc)
- goto out_put;
+ rc = ops->mmap(of, vma);
/*
* PowerPC's pci_mmap of legacy_mem uses shmem_zero_setup()
@@ -596,6 +603,9 @@ static int kernfs_file_open(struct inode *inode, struct file *file)
* happen on the same file. At this point, we can't easily give
* each file a separate locking class. Let's differentiate on
* whether the file has mmap or not for now.
+ *
+ * Both paths of the branch look the same. They're supposed to
+ * look that way and give @of->mutex different static lockdep keys.
*/
if (has_mmap)
mutex_init(&of->mutex);