Lines Matching +full:sda +full:- +full:open +full:- +full:drain

1 // SPDX-License-Identifier: GPL-2.0-only
3 * fs/kernfs/file.c - kernfs file implementation
5 * Copyright (c) 2001-3 Patrick Mochel
19 #include "kernfs-internal.h"
47 return &kernfs_locks->open_file_mutex[idx]; in kernfs_open_file_mutex_ptr()
62 * of_on - Get the kernfs_open_node of the specified kernfs_open_file
69 return rcu_dereference_protected(of->kn->attr.open, in of_on()
70 !list_empty(&of->list)); in of_on()
74 * kernfs_deref_open_node_locked - Get kernfs_open_node corresponding to @kn
78 * Fetch and return ->attr.open of @kn when caller holds the
81 * Update of ->attr.open happens under kernfs_open_file_mutex_ptr(kn). So when
83 * change ->attr.open and this means that we can safely deref ->attr.open
84 * outside RCU read-side critical section.
88 * Return: @kn->attr.open when kernfs_open_file_mutex is held.
93 return rcu_dereference_protected(kn->attr.open, in kernfs_deref_open_node_locked()
99 return ((struct seq_file *)file->private_data)->private; in kernfs_of()
108 if (kn->flags & KERNFS_LOCKDEP) in kernfs_ops()
110 return kn->attr.ops; in kernfs_ops()
120 * directly visible to userland, ERR_PTR(-ENODEV) is the only acceptable
124 * operations which may return ERR_PTR(-ENODEV) too. kernfs_seq_stop()
125 * can't distinguish whether ERR_PTR(-ENODEV) is from get_active failure or
127 * should be performed or not only on ERR_PTR(-ENODEV).
131 * kernfs_seq_stop() if ERR_PTR(-ENODEV) while invoking it directly after
132 * custom seq_file operations fail with ERR_PTR(-ENODEV) - this ensures
137 struct kernfs_open_file *of = sf->private; in kernfs_seq_stop_active()
138 const struct kernfs_ops *ops = kernfs_ops(of->kn); in kernfs_seq_stop_active()
140 if (ops->seq_stop) in kernfs_seq_stop_active()
141 ops->seq_stop(sf, v); in kernfs_seq_stop_active()
142 kernfs_put_active(of->kn); in kernfs_seq_stop_active()
147 struct kernfs_open_file *of = sf->private; in kernfs_seq_start()
151 * @of->mutex nests outside active ref and is primarily to ensure that in kernfs_seq_start()
152 * the ops aren't called concurrently for the same open file. in kernfs_seq_start()
154 mutex_lock(&of->mutex); in kernfs_seq_start()
155 if (!kernfs_get_active(of->kn)) in kernfs_seq_start()
156 return ERR_PTR(-ENODEV); in kernfs_seq_start()
158 ops = kernfs_ops(of->kn); in kernfs_seq_start()
159 if (ops->seq_start) { in kernfs_seq_start()
160 void *next = ops->seq_start(sf, ppos); in kernfs_seq_start()
162 if (next == ERR_PTR(-ENODEV)) in kernfs_seq_start()
171 struct kernfs_open_file *of = sf->private; in kernfs_seq_next()
172 const struct kernfs_ops *ops = kernfs_ops(of->kn); in kernfs_seq_next()
174 if (ops->seq_next) { in kernfs_seq_next()
175 void *next = ops->seq_next(sf, v, ppos); in kernfs_seq_next()
177 if (next == ERR_PTR(-ENODEV)) in kernfs_seq_next()
192 struct kernfs_open_file *of = sf->private; in kernfs_seq_stop()
194 if (v != ERR_PTR(-ENODEV)) in kernfs_seq_stop()
196 mutex_unlock(&of->mutex); in kernfs_seq_stop()
201 struct kernfs_open_file *of = sf->private; in kernfs_seq_show()
203 of->event = atomic_read(&of_on(of)->event); in kernfs_seq_show()
205 return of->kn->attr.ops->seq_show(sf, v); in kernfs_seq_show()
216 * As reading a bin file can have side-effects, the exact offset and bytes
223 struct kernfs_open_file *of = kernfs_of(iocb->ki_filp); in kernfs_file_read_iter()
228 buf = of->prealloc_buf; in kernfs_file_read_iter()
230 mutex_lock(&of->prealloc_mutex); in kernfs_file_read_iter()
234 return -ENOMEM; in kernfs_file_read_iter()
237 * @of->mutex nests outside active ref and is used both to ensure that in kernfs_file_read_iter()
238 * the ops aren't called concurrently for the same open file. in kernfs_file_read_iter()
240 mutex_lock(&of->mutex); in kernfs_file_read_iter()
241 if (!kernfs_get_active(of->kn)) { in kernfs_file_read_iter()
242 len = -ENODEV; in kernfs_file_read_iter()
243 mutex_unlock(&of->mutex); in kernfs_file_read_iter()
247 of->event = atomic_read(&of_on(of)->event); in kernfs_file_read_iter()
249 ops = kernfs_ops(of->kn); in kernfs_file_read_iter()
250 if (ops->read) in kernfs_file_read_iter()
251 len = ops->read(of, buf, len, iocb->ki_pos); in kernfs_file_read_iter()
253 len = -EINVAL; in kernfs_file_read_iter()
255 kernfs_put_active(of->kn); in kernfs_file_read_iter()
256 mutex_unlock(&of->mutex); in kernfs_file_read_iter()
262 len = -EFAULT; in kernfs_file_read_iter()
266 iocb->ki_pos += len; in kernfs_file_read_iter()
269 if (buf == of->prealloc_buf) in kernfs_file_read_iter()
270 mutex_unlock(&of->prealloc_mutex); in kernfs_file_read_iter()
278 if (kernfs_of(iocb->ki_filp)->kn->flags & KERNFS_HAS_SEQ_SHOW) in kernfs_fop_read_iter()
295 struct kernfs_open_file *of = kernfs_of(iocb->ki_filp); in kernfs_fop_write_iter()
300 if (of->atomic_write_len) { in kernfs_fop_write_iter()
301 if (len > of->atomic_write_len) in kernfs_fop_write_iter()
302 return -E2BIG; in kernfs_fop_write_iter()
307 buf = of->prealloc_buf; in kernfs_fop_write_iter()
309 mutex_lock(&of->prealloc_mutex); in kernfs_fop_write_iter()
313 return -ENOMEM; in kernfs_fop_write_iter()
316 len = -EFAULT; in kernfs_fop_write_iter()
322 * @of->mutex nests outside active ref and is used both to ensure that in kernfs_fop_write_iter()
323 * the ops aren't called concurrently for the same open file. in kernfs_fop_write_iter()
325 mutex_lock(&of->mutex); in kernfs_fop_write_iter()
326 if (!kernfs_get_active(of->kn)) { in kernfs_fop_write_iter()
327 mutex_unlock(&of->mutex); in kernfs_fop_write_iter()
328 len = -ENODEV; in kernfs_fop_write_iter()
332 ops = kernfs_ops(of->kn); in kernfs_fop_write_iter()
333 if (ops->write) in kernfs_fop_write_iter()
334 len = ops->write(of, buf, len, iocb->ki_pos); in kernfs_fop_write_iter()
336 len = -EINVAL; in kernfs_fop_write_iter()
338 kernfs_put_active(of->kn); in kernfs_fop_write_iter()
339 mutex_unlock(&of->mutex); in kernfs_fop_write_iter()
342 iocb->ki_pos += len; in kernfs_fop_write_iter()
345 if (buf == of->prealloc_buf) in kernfs_fop_write_iter()
346 mutex_unlock(&of->prealloc_mutex); in kernfs_fop_write_iter()
354 struct file *file = vma->vm_file; in kernfs_vma_open()
357 if (!of->vm_ops) in kernfs_vma_open()
360 if (!kernfs_get_active(of->kn)) in kernfs_vma_open()
363 if (of->vm_ops->open) in kernfs_vma_open()
364 of->vm_ops->open(vma); in kernfs_vma_open()
366 kernfs_put_active(of->kn); in kernfs_vma_open()
371 struct file *file = vmf->vma->vm_file; in kernfs_vma_fault()
375 if (!of->vm_ops) in kernfs_vma_fault()
378 if (!kernfs_get_active(of->kn)) in kernfs_vma_fault()
382 if (of->vm_ops->fault) in kernfs_vma_fault()
383 ret = of->vm_ops->fault(vmf); in kernfs_vma_fault()
385 kernfs_put_active(of->kn); in kernfs_vma_fault()
391 struct file *file = vmf->vma->vm_file; in kernfs_vma_page_mkwrite()
395 if (!of->vm_ops) in kernfs_vma_page_mkwrite()
398 if (!kernfs_get_active(of->kn)) in kernfs_vma_page_mkwrite()
402 if (of->vm_ops->page_mkwrite) in kernfs_vma_page_mkwrite()
403 ret = of->vm_ops->page_mkwrite(vmf); in kernfs_vma_page_mkwrite()
407 kernfs_put_active(of->kn); in kernfs_vma_page_mkwrite()
414 struct file *file = vma->vm_file; in kernfs_vma_access()
418 if (!of->vm_ops) in kernfs_vma_access()
419 return -EINVAL; in kernfs_vma_access()
421 if (!kernfs_get_active(of->kn)) in kernfs_vma_access()
422 return -EINVAL; in kernfs_vma_access()
424 ret = -EINVAL; in kernfs_vma_access()
425 if (of->vm_ops->access) in kernfs_vma_access()
426 ret = of->vm_ops->access(vma, addr, buf, len, write); in kernfs_vma_access()
428 kernfs_put_active(of->kn); in kernfs_vma_access()
433 .open = kernfs_vma_open,
446 * mmap path and of->mutex are prone to triggering spurious lockdep in kernfs_fop_mmap()
449 * without grabbing @of->mutex by testing HAS_MMAP flag. See the in kernfs_fop_mmap()
452 if (!(of->kn->flags & KERNFS_HAS_MMAP)) in kernfs_fop_mmap()
453 return -ENODEV; in kernfs_fop_mmap()
455 mutex_lock(&of->mutex); in kernfs_fop_mmap()
457 rc = -ENODEV; in kernfs_fop_mmap()
458 if (!kernfs_get_active(of->kn)) in kernfs_fop_mmap()
461 ops = kernfs_ops(of->kn); in kernfs_fop_mmap()
462 rc = ops->mmap(of, vma); in kernfs_fop_mmap()
471 if (vma->vm_file != file) in kernfs_fop_mmap()
474 rc = -EINVAL; in kernfs_fop_mmap()
475 if (of->mmapped && of->vm_ops != vma->vm_ops) in kernfs_fop_mmap()
482 if (vma->vm_ops && vma->vm_ops->close) in kernfs_fop_mmap()
486 if (!of->mmapped) { in kernfs_fop_mmap()
487 of->mmapped = true; in kernfs_fop_mmap()
488 of_on(of)->nr_mmapped++; in kernfs_fop_mmap()
489 of->vm_ops = vma->vm_ops; in kernfs_fop_mmap()
491 vma->vm_ops = &kernfs_vm_ops; in kernfs_fop_mmap()
493 kernfs_put_active(of->kn); in kernfs_fop_mmap()
495 mutex_unlock(&of->mutex); in kernfs_fop_mmap()
501 * kernfs_get_open_node - get or create kernfs_open_node
503 * @of: kernfs_open_file for this instance of open
505 * If @kn->attr.open exists, increment its reference count; otherwise,
512 * %0 on success, -errno on failure.
528 return -ENOMEM; in kernfs_get_open_node()
530 atomic_set(&on->event, 1); in kernfs_get_open_node()
531 init_waitqueue_head(&on->poll); in kernfs_get_open_node()
532 INIT_LIST_HEAD(&on->files); in kernfs_get_open_node()
533 rcu_assign_pointer(kn->attr.open, on); in kernfs_get_open_node()
536 list_add_tail(&of->list, &on->files); in kernfs_get_open_node()
537 if (kn->flags & KERNFS_HAS_RELEASE) in kernfs_get_open_node()
538 on->nr_to_release++; in kernfs_get_open_node()
545 * kernfs_unlink_open_file - Unlink @of from @kn.
549 * @open_failed: ->open() failed, cancel ->release()
551 * Unlink @of from list of @kn's associated open files. If list of
552 * associated open files becomes empty, disassociate and free
574 if (kn->flags & KERNFS_HAS_RELEASE) { in kernfs_unlink_open_file()
575 WARN_ON_ONCE(of->released == open_failed); in kernfs_unlink_open_file()
577 on->nr_to_release--; in kernfs_unlink_open_file()
579 if (of->mmapped) in kernfs_unlink_open_file()
580 on->nr_mmapped--; in kernfs_unlink_open_file()
581 list_del(&of->list); in kernfs_unlink_open_file()
584 if (list_empty(&on->files)) { in kernfs_unlink_open_file()
585 rcu_assign_pointer(kn->attr.open, NULL); in kernfs_unlink_open_file()
594 struct kernfs_node *kn = inode->i_private; in kernfs_fop_open()
599 int error = -EACCES; in kernfs_fop_open()
602 return -ENODEV; in kernfs_fop_open()
606 has_read = ops->seq_show || ops->read || ops->mmap; in kernfs_fop_open()
607 has_write = ops->write || ops->mmap; in kernfs_fop_open()
608 has_mmap = ops->mmap; in kernfs_fop_open()
611 if (root->flags & KERNFS_ROOT_EXTRA_OPEN_PERM_CHECK) { in kernfs_fop_open()
612 if ((file->f_mode & FMODE_WRITE) && in kernfs_fop_open()
613 (!(inode->i_mode & S_IWUGO) || !has_write)) in kernfs_fop_open()
616 if ((file->f_mode & FMODE_READ) && in kernfs_fop_open()
617 (!(inode->i_mode & S_IRUGO) || !has_read)) in kernfs_fop_open()
622 error = -ENOMEM; in kernfs_fop_open()
629 * @of->mutex for files which implement mmap. This is a rather in kernfs_fop_open()
631 * mm->mmap_lock - mmap nests @of->mutex under mm->mmap_lock and in kernfs_fop_open()
632 * reading /sys/block/sda/trace/act_mask grabs sr_mutex, under in kernfs_fop_open()
633 * which mm->mmap_lock nests, while holding @of->mutex. As each in kernfs_fop_open()
634 * open file has a separate mutex, it's okay as long as those don't in kernfs_fop_open()
645 * look that way and give @of->mutex different static lockdep keys. in kernfs_fop_open()
648 mutex_init(&of->mutex); in kernfs_fop_open()
649 else if (file->f_mode & FMODE_WRITE) in kernfs_fop_open()
650 mutex_init(&of->mutex); in kernfs_fop_open()
652 mutex_init(&of->mutex); in kernfs_fop_open()
654 of->kn = kn; in kernfs_fop_open()
655 of->file = file; in kernfs_fop_open()
661 of->atomic_write_len = ops->atomic_write_len; in kernfs_fop_open()
663 error = -EINVAL; in kernfs_fop_open()
665 * ->seq_show is incompatible with ->prealloc, in kernfs_fop_open()
667 * ->read must be used instead. in kernfs_fop_open()
669 if (ops->prealloc && ops->seq_show) in kernfs_fop_open()
671 if (ops->prealloc) { in kernfs_fop_open()
672 int len = of->atomic_write_len ?: PAGE_SIZE; in kernfs_fop_open()
673 of->prealloc_buf = kmalloc(len + 1, GFP_KERNEL); in kernfs_fop_open()
674 error = -ENOMEM; in kernfs_fop_open()
675 if (!of->prealloc_buf) in kernfs_fop_open()
677 mutex_init(&of->prealloc_mutex); in kernfs_fop_open()
685 if (ops->seq_show) in kernfs_fop_open()
692 of->seq_file = file->private_data; in kernfs_fop_open()
693 of->seq_file->private = of; in kernfs_fop_open()
696 if (file->f_mode & FMODE_WRITE) in kernfs_fop_open()
697 file->f_mode |= FMODE_PWRITE; in kernfs_fop_open()
699 /* make sure we have open node struct */ in kernfs_fop_open()
704 if (ops->open) { in kernfs_fop_open()
705 /* nobody has access to @of yet, skip @of->mutex */ in kernfs_fop_open()
706 error = ops->open(of); in kernfs_fop_open()
711 /* open succeeded, put active references */ in kernfs_fop_open()
720 kfree(of->prealloc_buf); in kernfs_fop_open()
727 /* used from release/drain to ensure that ->release() is called exactly once */
733 * we just want to synchronize release and drain paths. in kernfs_release_file()
734 * @kernfs_open_file_mutex_ptr(kn) is enough. @of->mutex can't be used in kernfs_release_file()
735 * here because drain path may be called from places which can in kernfs_release_file()
740 if (!of->released) { in kernfs_release_file()
746 kn->attr.ops->release(of); in kernfs_release_file()
747 of->released = true; in kernfs_release_file()
748 of_on(of)->nr_to_release--; in kernfs_release_file()
754 struct kernfs_node *kn = inode->i_private; in kernfs_fop_release()
757 if (kn->flags & KERNFS_HAS_RELEASE) { in kernfs_fop_release()
767 kfree(of->prealloc_buf); in kernfs_fop_release()
779 * @kn being deactivated guarantees that @kn->attr.open can't change in kernfs_should_drain_open_files()
782 WARN_ON_ONCE(atomic_read(&kn->active) != KN_DEACTIVATED_BIAS); in kernfs_should_drain_open_files()
785 on = rcu_dereference(kn->attr.open); in kernfs_should_drain_open_files()
786 ret = on && (on->nr_mmapped || on->nr_to_release); in kernfs_should_drain_open_files()
805 list_for_each_entry(of, &on->files, list) { in kernfs_drain_open_files()
806 struct inode *inode = file_inode(of->file); in kernfs_drain_open_files()
808 if (of->mmapped) { in kernfs_drain_open_files()
809 unmap_mapping_range(inode->i_mapping, 0, 0, 1); in kernfs_drain_open_files()
810 of->mmapped = false; in kernfs_drain_open_files()
811 on->nr_mmapped--; in kernfs_drain_open_files()
814 if (kn->flags & KERNFS_HAS_RELEASE) in kernfs_drain_open_files()
818 WARN_ON_ONCE(on->nr_mmapped || on->nr_to_release); in kernfs_drain_open_files()
830 * need to close and re-open the file, or seek to 0 and read again.
840 poll_wait(of->file, &on->poll, wait); in kernfs_generic_poll()
842 if (of->event != atomic_read(&on->event)) in kernfs_generic_poll()
851 struct kernfs_node *kn = kernfs_dentry_node(filp->f_path.dentry); in kernfs_fop_poll()
857 if (kn->attr.ops->poll) in kernfs_fop_poll()
858 ret = kn->attr.ops->poll(of, wait); in kernfs_fop_poll()
873 * @of->mutex nests outside active ref and is primarily to ensure that in kernfs_fop_llseek()
874 * the ops aren't called concurrently for the same open file. in kernfs_fop_llseek()
876 mutex_lock(&of->mutex); in kernfs_fop_llseek()
877 if (!kernfs_get_active(of->kn)) { in kernfs_fop_llseek()
878 mutex_unlock(&of->mutex); in kernfs_fop_llseek()
879 return -ENODEV; in kernfs_fop_llseek()
882 ops = kernfs_ops(of->kn); in kernfs_fop_llseek()
883 if (ops->llseek) in kernfs_fop_llseek()
884 ret = ops->llseek(of, offset, whence); in kernfs_fop_llseek()
888 kernfs_put_active(of->kn); in kernfs_fop_llseek()
889 mutex_unlock(&of->mutex); in kernfs_fop_llseek()
906 kernfs_notify_list = kn->attr.notify_next; in kernfs_notify_workfn()
907 kn->attr.notify_next = NULL; in kernfs_notify_workfn()
913 down_read(&root->kernfs_supers_rwsem); in kernfs_notify_workfn()
914 list_for_each_entry(info, &kernfs_root(kn)->supers, node) { in kernfs_notify_workfn()
926 inode = ilookup(info->sb, kernfs_ino(kn)); in kernfs_notify_workfn()
930 name = (struct qstr)QSTR_INIT(kn->name, strlen(kn->name)); in kernfs_notify_workfn()
933 p_inode = ilookup(info->sb, kernfs_ino(parent)); in kernfs_notify_workfn()
950 up_read(&root->kernfs_supers_rwsem); in kernfs_notify_workfn()
956 * kernfs_notify - notify a kernfs file
973 on = rcu_dereference(kn->attr.open); in kernfs_notify()
975 atomic_inc(&on->event); in kernfs_notify()
976 wake_up_interruptible(&on->poll); in kernfs_notify()
982 if (!kn->attr.notify_next) { in kernfs_notify()
984 kn->attr.notify_next = kernfs_notify_list; in kernfs_notify()
997 .open = kernfs_fop_open,
1006 * __kernfs_create_file - kernfs internal function to create a file
1037 return ERR_PTR(-ENOMEM); in __kernfs_create_file()
1039 kn->attr.ops = ops; in __kernfs_create_file()
1040 kn->attr.size = size; in __kernfs_create_file()
1041 kn->ns = ns; in __kernfs_create_file()
1042 kn->priv = priv; in __kernfs_create_file()
1046 lockdep_init_map(&kn->dep_map, "kn->active", key, 0); in __kernfs_create_file()
1047 kn->flags |= KERNFS_LOCKDEP; in __kernfs_create_file()
1052 * kn->attr.ops is accessible only while holding active ref. We in __kernfs_create_file()
1056 if (ops->seq_show) in __kernfs_create_file()
1057 kn->flags |= KERNFS_HAS_SEQ_SHOW; in __kernfs_create_file()
1058 if (ops->mmap) in __kernfs_create_file()
1059 kn->flags |= KERNFS_HAS_MMAP; in __kernfs_create_file()
1060 if (ops->release) in __kernfs_create_file()
1061 kn->flags |= KERNFS_HAS_RELEASE; in __kernfs_create_file()