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()
436 struct file *file = vma->vm_file; in kernfs_vma_set_policy()
440 if (!of->vm_ops) in kernfs_vma_set_policy()
443 if (!kernfs_get_active(of->kn)) in kernfs_vma_set_policy()
444 return -EINVAL; in kernfs_vma_set_policy()
447 if (of->vm_ops->set_policy) in kernfs_vma_set_policy()
448 ret = of->vm_ops->set_policy(vma, new); in kernfs_vma_set_policy()
450 kernfs_put_active(of->kn); in kernfs_vma_set_policy()
457 struct file *file = vma->vm_file; in kernfs_vma_get_policy()
461 if (!of->vm_ops) in kernfs_vma_get_policy()
462 return vma->vm_policy; in kernfs_vma_get_policy()
464 if (!kernfs_get_active(of->kn)) in kernfs_vma_get_policy()
465 return vma->vm_policy; in kernfs_vma_get_policy()
467 pol = vma->vm_policy; in kernfs_vma_get_policy()
468 if (of->vm_ops->get_policy) in kernfs_vma_get_policy()
469 pol = of->vm_ops->get_policy(vma, addr); in kernfs_vma_get_policy()
471 kernfs_put_active(of->kn); in kernfs_vma_get_policy()
478 .open = kernfs_vma_open,
495 * mmap path and of->mutex are prone to triggering spurious lockdep in kernfs_fop_mmap()
498 * without grabbing @of->mutex by testing HAS_MMAP flag. See the in kernfs_fop_mmap()
501 if (!(of->kn->flags & KERNFS_HAS_MMAP)) in kernfs_fop_mmap()
502 return -ENODEV; in kernfs_fop_mmap()
504 mutex_lock(&of->mutex); in kernfs_fop_mmap()
506 rc = -ENODEV; in kernfs_fop_mmap()
507 if (!kernfs_get_active(of->kn)) in kernfs_fop_mmap()
510 ops = kernfs_ops(of->kn); in kernfs_fop_mmap()
511 rc = ops->mmap(of, vma); in kernfs_fop_mmap()
520 if (vma->vm_file != file) in kernfs_fop_mmap()
523 rc = -EINVAL; in kernfs_fop_mmap()
524 if (of->mmapped && of->vm_ops != vma->vm_ops) in kernfs_fop_mmap()
531 if (vma->vm_ops && vma->vm_ops->close) in kernfs_fop_mmap()
535 if (!of->mmapped) { in kernfs_fop_mmap()
536 of->mmapped = true; in kernfs_fop_mmap()
537 of_on(of)->nr_mmapped++; in kernfs_fop_mmap()
538 of->vm_ops = vma->vm_ops; in kernfs_fop_mmap()
540 vma->vm_ops = &kernfs_vm_ops; in kernfs_fop_mmap()
542 kernfs_put_active(of->kn); in kernfs_fop_mmap()
544 mutex_unlock(&of->mutex); in kernfs_fop_mmap()
550 * kernfs_get_open_node - get or create kernfs_open_node
552 * @of: kernfs_open_file for this instance of open
554 * If @kn->attr.open exists, increment its reference count; otherwise,
561 * %0 on success, -errno on failure.
577 return -ENOMEM; in kernfs_get_open_node()
579 atomic_set(&on->event, 1); in kernfs_get_open_node()
580 init_waitqueue_head(&on->poll); in kernfs_get_open_node()
581 INIT_LIST_HEAD(&on->files); in kernfs_get_open_node()
582 rcu_assign_pointer(kn->attr.open, on); in kernfs_get_open_node()
585 list_add_tail(&of->list, &on->files); in kernfs_get_open_node()
586 if (kn->flags & KERNFS_HAS_RELEASE) in kernfs_get_open_node()
587 on->nr_to_release++; in kernfs_get_open_node()
594 * kernfs_unlink_open_file - Unlink @of from @kn.
598 * @open_failed: ->open() failed, cancel ->release()
600 * Unlink @of from list of @kn's associated open files. If list of
601 * associated open files becomes empty, disassociate and free
623 if (kn->flags & KERNFS_HAS_RELEASE) { in kernfs_unlink_open_file()
624 WARN_ON_ONCE(of->released == open_failed); in kernfs_unlink_open_file()
626 on->nr_to_release--; in kernfs_unlink_open_file()
628 if (of->mmapped) in kernfs_unlink_open_file()
629 on->nr_mmapped--; in kernfs_unlink_open_file()
630 list_del(&of->list); in kernfs_unlink_open_file()
633 if (list_empty(&on->files)) { in kernfs_unlink_open_file()
634 rcu_assign_pointer(kn->attr.open, NULL); in kernfs_unlink_open_file()
643 struct kernfs_node *kn = inode->i_private; in kernfs_fop_open()
648 int error = -EACCES; in kernfs_fop_open()
651 return -ENODEV; in kernfs_fop_open()
655 has_read = ops->seq_show || ops->read || ops->mmap; in kernfs_fop_open()
656 has_write = ops->write || ops->mmap; in kernfs_fop_open()
657 has_mmap = ops->mmap; in kernfs_fop_open()
660 if (root->flags & KERNFS_ROOT_EXTRA_OPEN_PERM_CHECK) { in kernfs_fop_open()
661 if ((file->f_mode & FMODE_WRITE) && in kernfs_fop_open()
662 (!(inode->i_mode & S_IWUGO) || !has_write)) in kernfs_fop_open()
665 if ((file->f_mode & FMODE_READ) && in kernfs_fop_open()
666 (!(inode->i_mode & S_IRUGO) || !has_read)) in kernfs_fop_open()
671 error = -ENOMEM; in kernfs_fop_open()
678 * @of->mutex for files which implement mmap. This is a rather in kernfs_fop_open()
680 * mm->mmap_lock - mmap nests @of->mutex under mm->mmap_lock and in kernfs_fop_open()
681 * reading /sys/block/sda/trace/act_mask grabs sr_mutex, under in kernfs_fop_open()
682 * which mm->mmap_lock nests, while holding @of->mutex. As each in kernfs_fop_open()
683 * open file has a separate mutex, it's okay as long as those don't in kernfs_fop_open()
689 * look that way and give @of->mutex different static lockdep keys. in kernfs_fop_open()
692 mutex_init(&of->mutex); in kernfs_fop_open()
694 mutex_init(&of->mutex); in kernfs_fop_open()
696 of->kn = kn; in kernfs_fop_open()
697 of->file = file; in kernfs_fop_open()
703 of->atomic_write_len = ops->atomic_write_len; in kernfs_fop_open()
705 error = -EINVAL; in kernfs_fop_open()
707 * ->seq_show is incompatible with ->prealloc, in kernfs_fop_open()
709 * ->read must be used instead. in kernfs_fop_open()
711 if (ops->prealloc && ops->seq_show) in kernfs_fop_open()
713 if (ops->prealloc) { in kernfs_fop_open()
714 int len = of->atomic_write_len ?: PAGE_SIZE; in kernfs_fop_open()
715 of->prealloc_buf = kmalloc(len + 1, GFP_KERNEL); in kernfs_fop_open()
716 error = -ENOMEM; in kernfs_fop_open()
717 if (!of->prealloc_buf) in kernfs_fop_open()
719 mutex_init(&of->prealloc_mutex); in kernfs_fop_open()
727 if (ops->seq_show) in kernfs_fop_open()
734 of->seq_file = file->private_data; in kernfs_fop_open()
735 of->seq_file->private = of; in kernfs_fop_open()
738 if (file->f_mode & FMODE_WRITE) in kernfs_fop_open()
739 file->f_mode |= FMODE_PWRITE; in kernfs_fop_open()
741 /* make sure we have open node struct */ in kernfs_fop_open()
746 if (ops->open) { in kernfs_fop_open()
747 /* nobody has access to @of yet, skip @of->mutex */ in kernfs_fop_open()
748 error = ops->open(of); in kernfs_fop_open()
753 /* open succeeded, put active references */ in kernfs_fop_open()
762 kfree(of->prealloc_buf); in kernfs_fop_open()
769 /* used from release/drain to ensure that ->release() is called exactly once */
775 * we just want to synchronize release and drain paths. in kernfs_release_file()
776 * @kernfs_open_file_mutex_ptr(kn) is enough. @of->mutex can't be used in kernfs_release_file()
777 * here because drain path may be called from places which can in kernfs_release_file()
782 if (!of->released) { in kernfs_release_file()
788 kn->attr.ops->release(of); in kernfs_release_file()
789 of->released = true; in kernfs_release_file()
790 of_on(of)->nr_to_release--; in kernfs_release_file()
796 struct kernfs_node *kn = inode->i_private; in kernfs_fop_release()
799 if (kn->flags & KERNFS_HAS_RELEASE) { in kernfs_fop_release()
809 kfree(of->prealloc_buf); in kernfs_fop_release()
821 * @kn being deactivated guarantees that @kn->attr.open can't change in kernfs_should_drain_open_files()
824 WARN_ON_ONCE(atomic_read(&kn->active) != KN_DEACTIVATED_BIAS); in kernfs_should_drain_open_files()
827 on = rcu_dereference(kn->attr.open); in kernfs_should_drain_open_files()
828 ret = on && (on->nr_mmapped || on->nr_to_release); in kernfs_should_drain_open_files()
847 list_for_each_entry(of, &on->files, list) { in kernfs_drain_open_files()
848 struct inode *inode = file_inode(of->file); in kernfs_drain_open_files()
850 if (of->mmapped) { in kernfs_drain_open_files()
851 unmap_mapping_range(inode->i_mapping, 0, 0, 1); in kernfs_drain_open_files()
852 of->mmapped = false; in kernfs_drain_open_files()
853 on->nr_mmapped--; in kernfs_drain_open_files()
856 if (kn->flags & KERNFS_HAS_RELEASE) in kernfs_drain_open_files()
860 WARN_ON_ONCE(on->nr_mmapped || on->nr_to_release); in kernfs_drain_open_files()
872 * need to close and re-open the file, or seek to 0 and read again.
882 poll_wait(of->file, &on->poll, wait); in kernfs_generic_poll()
884 if (of->event != atomic_read(&on->event)) in kernfs_generic_poll()
893 struct kernfs_node *kn = kernfs_dentry_node(filp->f_path.dentry); in kernfs_fop_poll()
899 if (kn->attr.ops->poll) in kernfs_fop_poll()
900 ret = kn->attr.ops->poll(of, wait); in kernfs_fop_poll()
921 kernfs_notify_list = kn->attr.notify_next; in kernfs_notify_workfn()
922 kn->attr.notify_next = NULL; in kernfs_notify_workfn()
928 down_read(&root->kernfs_supers_rwsem); in kernfs_notify_workfn()
929 list_for_each_entry(info, &kernfs_root(kn)->supers, node) { in kernfs_notify_workfn()
941 inode = ilookup(info->sb, kernfs_ino(kn)); in kernfs_notify_workfn()
945 name = (struct qstr)QSTR_INIT(kn->name, strlen(kn->name)); in kernfs_notify_workfn()
948 p_inode = ilookup(info->sb, kernfs_ino(parent)); in kernfs_notify_workfn()
965 up_read(&root->kernfs_supers_rwsem); in kernfs_notify_workfn()
971 * kernfs_notify - notify a kernfs file
988 on = rcu_dereference(kn->attr.open); in kernfs_notify()
990 atomic_inc(&on->event); in kernfs_notify()
991 wake_up_interruptible(&on->poll); in kernfs_notify()
997 if (!kn->attr.notify_next) { in kernfs_notify()
999 kn->attr.notify_next = kernfs_notify_list; in kernfs_notify()
1012 .open = kernfs_fop_open,
1021 * __kernfs_create_file - kernfs internal function to create a file
1052 return ERR_PTR(-ENOMEM); in __kernfs_create_file()
1054 kn->attr.ops = ops; in __kernfs_create_file()
1055 kn->attr.size = size; in __kernfs_create_file()
1056 kn->ns = ns; in __kernfs_create_file()
1057 kn->priv = priv; in __kernfs_create_file()
1061 lockdep_init_map(&kn->dep_map, "kn->active", key, 0); in __kernfs_create_file()
1062 kn->flags |= KERNFS_LOCKDEP; in __kernfs_create_file()
1067 * kn->attr.ops is accessible only while holding active ref. We in __kernfs_create_file()
1071 if (ops->seq_show) in __kernfs_create_file()
1072 kn->flags |= KERNFS_HAS_SEQ_SHOW; in __kernfs_create_file()
1073 if (ops->mmap) in __kernfs_create_file()
1074 kn->flags |= KERNFS_HAS_MMAP; in __kernfs_create_file()
1075 if (ops->release) in __kernfs_create_file()
1076 kn->flags |= KERNFS_HAS_RELEASE; in __kernfs_create_file()