^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright 2020 Google LLC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/fsnotify.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/namei.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/poll.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/syscalls.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <uapi/linux/incrementalfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "pseudo_files.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "data_mgmt.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "format.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "integrity.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "vfs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define READ_WRITE_FILE_MODE 0666
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) static bool is_pseudo_filename(struct mem_range name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) /*******************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * .pending_reads pseudo file definition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) ******************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define INCFS_PENDING_READS_INODE 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) static const char pending_reads_file_name[] = INCFS_PENDING_READS_FILENAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) /* State of an open .pending_reads file, unique for each file descriptor. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) struct pending_reads_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) /* A serial number of the last pending read obtained from this file. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) int last_pending_read_sn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static ssize_t pending_reads_read(struct file *f, char __user *buf, size_t len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) struct pending_reads_state *pr_state = f->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) struct mount_info *mi = get_mount_info(file_superblock(f));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) bool report_uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) unsigned long page = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct incfs_pending_read_info *reads_buf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct incfs_pending_read_info2 *reads_buf2 = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) size_t record_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) size_t reads_to_collect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) int last_known_read_sn = READ_ONCE(pr_state->last_pending_read_sn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) int new_max_sn = last_known_read_sn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) int reads_collected = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) ssize_t result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) if (!mi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) report_uid = mi->mi_options.report_uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) record_size = report_uid ? sizeof(*reads_buf2) : sizeof(*reads_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) reads_to_collect = len / record_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (!incfs_fresh_pending_reads_exist(mi, last_known_read_sn))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) page = get_zeroed_page(GFP_NOFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (!page)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) if (report_uid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) reads_buf2 = (struct incfs_pending_read_info2 *) page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) reads_buf = (struct incfs_pending_read_info *) page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) reads_to_collect =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) min_t(size_t, PAGE_SIZE / record_size, reads_to_collect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) reads_collected = incfs_collect_pending_reads(mi, last_known_read_sn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) reads_buf, reads_buf2, reads_to_collect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) &new_max_sn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) if (reads_collected < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) result = reads_collected;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * Just to make sure that we don't accidentally copy more data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * to reads buffer than userspace can handle.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) reads_collected = min_t(size_t, reads_collected, reads_to_collect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) result = reads_collected * record_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) /* Copy reads info to the userspace buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) if (copy_to_user(buf, (void *)page, result)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) result = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) WRITE_ONCE(pr_state->last_pending_read_sn, new_max_sn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) *ppos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) free_page(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) static __poll_t pending_reads_poll(struct file *file, poll_table *wait)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) struct pending_reads_state *state = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) struct mount_info *mi = get_mount_info(file_superblock(file));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) __poll_t ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) poll_wait(file, &mi->mi_pending_reads_notif_wq, wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (incfs_fresh_pending_reads_exist(mi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) state->last_pending_read_sn))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) ret = EPOLLIN | EPOLLRDNORM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) static int pending_reads_open(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) struct pending_reads_state *state = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) state = kzalloc(sizeof(*state), GFP_NOFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) if (!state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) file->private_data = state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static int pending_reads_release(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) kfree(file->private_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) static long ioctl_permit_fill(struct file *f, void __user *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) struct incfs_permit_fill __user *usr_permit_fill = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) struct incfs_permit_fill permit_fill;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) long error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) struct file *file = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) struct incfs_file_data *fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) if (copy_from_user(&permit_fill, usr_permit_fill, sizeof(permit_fill)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) file = fget(permit_fill.file_descriptor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) if (IS_ERR_OR_NULL(file)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) if (!file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) return PTR_ERR(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (file->f_op != &incfs_file_ops) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) error = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (file->f_inode->i_sb != f->f_inode->i_sb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) error = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) fd = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) switch (fd->fd_fill_permission) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) case CANT_FILL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) fd->fd_fill_permission = CAN_FILL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) case CAN_FILL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) pr_debug("CAN_FILL already set");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) pr_warn("Invalid file private data");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) error = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) fput(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) static int chmod(struct dentry *dentry, umode_t mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) struct inode *inode = dentry->d_inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) struct inode *delegated_inode = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) struct iattr newattrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) retry_deleg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) inode_lock(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) error = notify_change(dentry, &newattrs, &delegated_inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) inode_unlock(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (delegated_inode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) error = break_deleg_wait(&delegated_inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) if (!error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) goto retry_deleg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) static bool incfs_equal_ranges(struct mem_range lhs, struct mem_range rhs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (lhs.len != rhs.len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) return memcmp(lhs.data, rhs.data, lhs.len) == 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) static int validate_name(char *file_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) struct mem_range name = range(file_name, strlen(file_name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (name.len > INCFS_MAX_NAME_LEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) return -ENAMETOOLONG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (is_pseudo_filename(name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) for (i = 0; i < name.len; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (name.data[i] == '/')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) static int dir_relative_path_resolve(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) struct mount_info *mi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) const char __user *relative_path,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) struct path *result_path,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) struct path *base_path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) int dir_fd = get_unused_fd_flags(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) struct file *dir_f = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) int error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if (!base_path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) base_path = &mi->mi_backing_dir_path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if (dir_fd < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) return dir_fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) dir_f = dentry_open(base_path, O_RDONLY | O_NOATIME, current_cred());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) if (IS_ERR(dir_f)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) error = PTR_ERR(dir_f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) fd_install(dir_fd, dir_f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (!relative_path) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) /* No relative path given, just return the base dir. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) *result_path = *base_path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) path_get(result_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) error = user_path_at_empty(dir_fd, relative_path,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) LOOKUP_FOLLOW | LOOKUP_DIRECTORY, result_path, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) ksys_close(dir_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) pr_debug("Error: %d\n", error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) static struct mem_range incfs_copy_signature_info_from_user(u8 __user *original,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) u64 size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) u8 *result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if (!original)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) return range(NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) if (size > INCFS_MAX_SIGNATURE_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) return range(ERR_PTR(-EFAULT), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) result = kzalloc(size, GFP_NOFS | __GFP_COMP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if (!result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) return range(ERR_PTR(-ENOMEM), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) if (copy_from_user(result, original, size)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) kfree(result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) return range(ERR_PTR(-EFAULT), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) return range(result, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) static int init_new_file(struct mount_info *mi, struct dentry *dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) incfs_uuid_t *uuid, u64 size, struct mem_range attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) u8 __user *user_signature_info, u64 signature_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) struct path path = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) struct file *new_file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) int error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) struct backing_file_context *bfc = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) u32 block_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) struct mem_range raw_signature = { NULL };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) struct mtree *hash_tree = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) if (!mi || !dentry || !uuid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) /* Resize newly created file to its true size. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) path = (struct path) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) .mnt = mi->mi_backing_dir_path.mnt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) .dentry = dentry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) new_file = dentry_open(&path, O_RDWR | O_NOATIME | O_LARGEFILE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) current_cred());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if (IS_ERR(new_file)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) error = PTR_ERR(new_file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) bfc = incfs_alloc_bfc(mi, new_file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) fput(new_file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) if (IS_ERR(bfc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) error = PTR_ERR(bfc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) bfc = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) mutex_lock(&bfc->bc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) error = incfs_write_fh_to_backing_file(bfc, uuid, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) block_count = (u32)get_blocks_count_for_size(size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) if (user_signature_info) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) raw_signature = incfs_copy_signature_info_from_user(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) user_signature_info, signature_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) if (IS_ERR(raw_signature.data)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) error = PTR_ERR(raw_signature.data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) raw_signature.data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) hash_tree = incfs_alloc_mtree(raw_signature, block_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) if (IS_ERR(hash_tree)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) error = PTR_ERR(hash_tree);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) hash_tree = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) error = incfs_write_signature_to_backing_file(bfc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) raw_signature, hash_tree->hash_tree_area_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) block_count += get_blocks_count_for_size(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) hash_tree->hash_tree_area_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) if (block_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) error = incfs_write_blockmap_to_backing_file(bfc, block_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) if (bfc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) mutex_unlock(&bfc->bc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) incfs_free_bfc(bfc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) incfs_free_mtree(hash_tree);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) kfree(raw_signature.data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) pr_debug("incfs: %s error: %d\n", __func__, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) static void notify_create(struct file *pending_reads_file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) const char __user *dir_name, const char *file_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) const char *file_id_str, bool incomplete_file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) struct mount_info *mi =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) get_mount_info(file_superblock(pending_reads_file));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) struct path base_path = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) .mnt = pending_reads_file->f_path.mnt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) .dentry = pending_reads_file->f_path.dentry->d_parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) struct path dir_path = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) struct dentry *file = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) struct dentry *dir = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) error = dir_relative_path_resolve(mi, dir_name, &dir_path, &base_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) file = incfs_lookup_dentry(dir_path.dentry, file_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) if (IS_ERR(file)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) error = PTR_ERR(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) file = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) fsnotify_create(d_inode(dir_path.dentry), file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) if (file_id_str) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) dir = incfs_lookup_dentry(base_path.dentry, INCFS_INDEX_NAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) if (IS_ERR(dir)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) error = PTR_ERR(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) dir = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) dput(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) file = incfs_lookup_dentry(dir, file_id_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) if (IS_ERR(file)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) error = PTR_ERR(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) file = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) fsnotify_create(d_inode(dir), file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) if (incomplete_file) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) dput(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) dir = incfs_lookup_dentry(base_path.dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) INCFS_INCOMPLETE_NAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) if (IS_ERR(dir)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) error = PTR_ERR(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) dir = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) dput(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) file = incfs_lookup_dentry(dir, file_id_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) if (IS_ERR(file)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) error = PTR_ERR(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) file = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) fsnotify_create(d_inode(dir), file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) pr_warn("%s failed with error %d\n", __func__, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) dput(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) dput(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) path_put(&dir_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) static long ioctl_create_file(struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) struct incfs_new_file_args __user *usr_args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) struct mount_info *mi = get_mount_info(file_superblock(file));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) struct incfs_new_file_args args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) char *file_id_str = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) struct dentry *index_file_dentry = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) struct dentry *named_file_dentry = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) struct dentry *incomplete_file_dentry = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) struct path parent_dir_path = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) struct inode *index_dir_inode = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) __le64 size_attr_value = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) char *file_name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) char *attr_value = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) int error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) bool locked = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) bool index_linked = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) bool name_linked = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) bool incomplete_linked = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) if (!mi || !mi->mi_index_dir || !mi->mi_incomplete_dir) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) error = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) if (copy_from_user(&args, usr_args, sizeof(args)) > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) error = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) file_name = strndup_user(u64_to_user_ptr(args.file_name), PATH_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) if (IS_ERR(file_name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) error = PTR_ERR(file_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) file_name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) error = validate_name(file_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) file_id_str = file_id_to_str(args.file_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) if (!file_id_str) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) error = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) error = mutex_lock_interruptible(&mi->mi_dir_struct_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) locked = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) /* Find a directory to put the file into. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) error = dir_relative_path_resolve(mi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) u64_to_user_ptr(args.directory_path),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) &parent_dir_path, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) if (parent_dir_path.dentry == mi->mi_index_dir) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) /* Can't create a file directly inside .index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) error = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) if (parent_dir_path.dentry == mi->mi_incomplete_dir) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) /* Can't create a file directly inside .incomplete */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) error = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) /* Look up a dentry in the parent dir. It should be negative. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) named_file_dentry = incfs_lookup_dentry(parent_dir_path.dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) file_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) if (!named_file_dentry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) error = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) if (IS_ERR(named_file_dentry)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) error = PTR_ERR(named_file_dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) named_file_dentry = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) if (d_really_is_positive(named_file_dentry)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) /* File with this path already exists. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) error = -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) /* Look up a dentry in the incomplete dir. It should be negative. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) incomplete_file_dentry = incfs_lookup_dentry(mi->mi_incomplete_dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) file_id_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) if (!incomplete_file_dentry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) error = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) if (IS_ERR(incomplete_file_dentry)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) error = PTR_ERR(incomplete_file_dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) incomplete_file_dentry = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) if (d_really_is_positive(incomplete_file_dentry)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) /* File with this path already exists. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) error = -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) /* Look up a dentry in the .index dir. It should be negative. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) index_file_dentry = incfs_lookup_dentry(mi->mi_index_dir, file_id_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) if (!index_file_dentry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) error = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) if (IS_ERR(index_file_dentry)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) error = PTR_ERR(index_file_dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) index_file_dentry = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) if (d_really_is_positive(index_file_dentry)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) /* File with this ID already exists in index. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) error = -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) /* Creating a file in the .index dir. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) index_dir_inode = d_inode(mi->mi_index_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) inode_lock_nested(index_dir_inode, I_MUTEX_PARENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) error = vfs_create(index_dir_inode, index_file_dentry, args.mode | 0222,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) inode_unlock(index_dir_inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) if (!d_really_is_positive(index_file_dentry)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) error = chmod(index_file_dentry, args.mode | 0222);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) pr_debug("incfs: chmod err: %d\n", error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) /* Save the file's ID as an xattr for easy fetching in future. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) error = vfs_setxattr(index_file_dentry, INCFS_XATTR_ID_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) file_id_str, strlen(file_id_str), XATTR_CREATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) pr_debug("incfs: vfs_setxattr err:%d\n", error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) /* Save the file's size as an xattr for easy fetching in future. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) size_attr_value = cpu_to_le64(args.size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) error = vfs_setxattr(index_file_dentry, INCFS_XATTR_SIZE_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) (char *)&size_attr_value, sizeof(size_attr_value),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) XATTR_CREATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) pr_debug("incfs: vfs_setxattr err:%d\n", error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) /* Save the file's attribute as an xattr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) if (args.file_attr_len && args.file_attr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) if (args.file_attr_len > INCFS_MAX_FILE_ATTR_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) error = -E2BIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) attr_value = kmalloc(args.file_attr_len, GFP_NOFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) if (!attr_value) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) error = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) if (copy_from_user(attr_value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) u64_to_user_ptr(args.file_attr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) args.file_attr_len) > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) error = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) error = vfs_setxattr(index_file_dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) INCFS_XATTR_METADATA_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) attr_value, args.file_attr_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) XATTR_CREATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) /* Initializing a newly created file. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) error = init_new_file(mi, index_file_dentry, &args.file_id, args.size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) range(attr_value, args.file_attr_len),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) u64_to_user_ptr(args.signature_info),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) args.signature_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) index_linked = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) /* Linking a file with its real name from the requested dir. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) error = incfs_link(index_file_dentry, named_file_dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) name_linked = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) if (args.size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) /* Linking a file with its incomplete entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) error = incfs_link(index_file_dentry, incomplete_file_dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) incomplete_linked = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) notify_create(file, u64_to_user_ptr(args.directory_path), file_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) file_id_str, args.size != 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) pr_debug("incfs: %s err:%d\n", __func__, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) if (index_linked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) incfs_unlink(index_file_dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) if (name_linked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) incfs_unlink(named_file_dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) if (incomplete_linked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) incfs_unlink(incomplete_file_dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) kfree(file_id_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) kfree(file_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) kfree(attr_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) dput(named_file_dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) dput(index_file_dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) dput(incomplete_file_dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) path_put(&parent_dir_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) if (locked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) mutex_unlock(&mi->mi_dir_struct_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) static int init_new_mapped_file(struct mount_info *mi, struct dentry *dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) incfs_uuid_t *uuid, u64 size, u64 offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) struct path path = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) struct file *new_file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) int error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) struct backing_file_context *bfc = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) if (!mi || !dentry || !uuid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) /* Resize newly created file to its true size. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) path = (struct path) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) .mnt = mi->mi_backing_dir_path.mnt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) .dentry = dentry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) new_file = dentry_open(&path, O_RDWR | O_NOATIME | O_LARGEFILE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) current_cred());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) if (IS_ERR(new_file)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) error = PTR_ERR(new_file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) bfc = incfs_alloc_bfc(mi, new_file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) fput(new_file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) if (IS_ERR(bfc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) error = PTR_ERR(bfc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) bfc = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) mutex_lock(&bfc->bc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) error = incfs_write_mapping_fh_to_backing_file(bfc, uuid, size, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) if (bfc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) mutex_unlock(&bfc->bc_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) incfs_free_bfc(bfc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) pr_debug("incfs: %s error: %d\n", __func__, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) static long ioctl_create_mapped_file(struct file *file, void __user *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) struct mount_info *mi = get_mount_info(file_superblock(file));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) struct incfs_create_mapped_file_args __user *args_usr_ptr = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) struct incfs_create_mapped_file_args args = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) char *file_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) int error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) struct path parent_dir_path = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) char *source_file_name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) struct dentry *source_file_dentry = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) u64 source_file_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) struct dentry *file_dentry = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) struct inode *parent_inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) __le64 size_attr_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) if (copy_from_user(&args, args_usr_ptr, sizeof(args)) > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) file_name = strndup_user(u64_to_user_ptr(args.file_name), PATH_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) if (IS_ERR(file_name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) error = PTR_ERR(file_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) file_name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) error = validate_name(file_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) if (args.source_offset % INCFS_DATA_FILE_BLOCK_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) /* Validate file mapping is in range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) source_file_name = file_id_to_str(args.source_file_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) if (!source_file_name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) pr_warn("Failed to alloc source_file_name\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) error = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) source_file_dentry = incfs_lookup_dentry(mi->mi_index_dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) source_file_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) if (!source_file_dentry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) pr_warn("Source file does not exist\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) if (IS_ERR(source_file_dentry)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) pr_warn("Error opening source file\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) error = PTR_ERR(source_file_dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) source_file_dentry = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) if (!d_really_is_positive(source_file_dentry)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) pr_warn("Source file dentry negative\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) error = vfs_getxattr(source_file_dentry, INCFS_XATTR_SIZE_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) (char *)&size_attr_value, sizeof(size_attr_value));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) if (error < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) if (error != sizeof(size_attr_value)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) pr_warn("Mapped file has no size attr\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) source_file_size = le64_to_cpu(size_attr_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) if (args.source_offset + args.size > source_file_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) pr_warn("Mapped file out of range\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) /* Find a directory to put the file into. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) error = dir_relative_path_resolve(mi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) u64_to_user_ptr(args.directory_path),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) &parent_dir_path, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) if (parent_dir_path.dentry == mi->mi_index_dir) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) /* Can't create a file directly inside .index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) error = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) /* Look up a dentry in the parent dir. It should be negative. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) file_dentry = incfs_lookup_dentry(parent_dir_path.dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) file_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) if (!file_dentry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) error = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) if (IS_ERR(file_dentry)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) error = PTR_ERR(file_dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) file_dentry = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) if (d_really_is_positive(file_dentry)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) error = -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) parent_inode = d_inode(parent_dir_path.dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) inode_lock_nested(parent_inode, I_MUTEX_PARENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) error = vfs_create(parent_inode, file_dentry, args.mode | 0222, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) inode_unlock(parent_inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) error = chmod(file_dentry, args.mode | 0222);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) pr_debug("incfs: chmod err: %d\n", error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) goto delete_file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) /* Save the file's size as an xattr for easy fetching in future. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) size_attr_value = cpu_to_le64(args.size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) error = vfs_setxattr(file_dentry, INCFS_XATTR_SIZE_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) (char *)&size_attr_value, sizeof(size_attr_value),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) XATTR_CREATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) pr_debug("incfs: vfs_setxattr err:%d\n", error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) goto delete_file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) error = init_new_mapped_file(mi, file_dentry, &args.source_file_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) args.size, args.source_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) goto delete_file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) notify_create(file, u64_to_user_ptr(args.directory_path), file_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) NULL, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) delete_file:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) incfs_unlink(file_dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) dput(file_dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) dput(source_file_dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) path_put(&parent_dir_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) kfree(file_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) kfree(source_file_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) static long ioctl_get_read_timeouts(struct mount_info *mi, void __user *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) struct incfs_get_read_timeouts_args __user *args_usr_ptr = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) struct incfs_get_read_timeouts_args args = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) int error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) struct incfs_per_uid_read_timeouts *buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) int size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) if (copy_from_user(&args, args_usr_ptr, sizeof(args)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) if (args.timeouts_array_size_out > INCFS_DATA_FILE_BLOCK_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) buffer = kzalloc(args.timeouts_array_size_out, GFP_NOFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) if (!buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) spin_lock(&mi->mi_per_uid_read_timeouts_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) size = mi->mi_per_uid_read_timeouts_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) if (args.timeouts_array_size < size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) error = -E2BIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) else if (size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) memcpy(buffer, mi->mi_per_uid_read_timeouts, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) spin_unlock(&mi->mi_per_uid_read_timeouts_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) args.timeouts_array_size_out = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) if (!error && size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) if (copy_to_user(u64_to_user_ptr(args.timeouts_array), buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) size))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) error = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) if (!error || error == -E2BIG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) if (copy_to_user(args_usr_ptr, &args, sizeof(args)) > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) error = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) kfree(buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) static long ioctl_set_read_timeouts(struct mount_info *mi, void __user *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) struct incfs_set_read_timeouts_args __user *args_usr_ptr = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) struct incfs_set_read_timeouts_args args = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) int error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) int size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) struct incfs_per_uid_read_timeouts *buffer = NULL, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) if (copy_from_user(&args, args_usr_ptr, sizeof(args)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) size = args.timeouts_array_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) if (size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) if (size > INCFS_DATA_FILE_BLOCK_SIZE ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) size % sizeof(*buffer) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) buffer = kzalloc(size, GFP_NOFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) if (!buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) if (copy_from_user(buffer, u64_to_user_ptr(args.timeouts_array),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) size)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) for (i = 0; i < size / sizeof(*buffer); ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) struct incfs_per_uid_read_timeouts *t = &buffer[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) if (t->min_pending_time_us > t->max_pending_time_us) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) spin_lock(&mi->mi_per_uid_read_timeouts_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) mi->mi_per_uid_read_timeouts_size = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) tmp = mi->mi_per_uid_read_timeouts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) mi->mi_per_uid_read_timeouts = buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) buffer = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) spin_unlock(&mi->mi_per_uid_read_timeouts_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) kfree(buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) static long ioctl_get_last_read_error(struct mount_info *mi, void __user *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) struct incfs_get_last_read_error_args __user *args_usr_ptr = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) struct incfs_get_last_read_error_args args = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) error = mutex_lock_interruptible(&mi->mi_le_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) args.file_id_out = mi->mi_le_file_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) args.time_us_out = mi->mi_le_time_us;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) args.page_out = mi->mi_le_page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) args.errno_out = mi->mi_le_errno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) args.uid_out = mi->mi_le_uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) mutex_unlock(&mi->mi_le_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) if (copy_to_user(args_usr_ptr, &args, sizeof(args)) > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) error = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) static long pending_reads_dispatch_ioctl(struct file *f, unsigned int req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) struct mount_info *mi = get_mount_info(file_superblock(f));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) switch (req) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) case INCFS_IOC_CREATE_FILE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) return ioctl_create_file(f, (void __user *)arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) case INCFS_IOC_PERMIT_FILL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) return ioctl_permit_fill(f, (void __user *)arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) case INCFS_IOC_CREATE_MAPPED_FILE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) return ioctl_create_mapped_file(f, (void __user *)arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) case INCFS_IOC_GET_READ_TIMEOUTS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) return ioctl_get_read_timeouts(mi, (void __user *)arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) case INCFS_IOC_SET_READ_TIMEOUTS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) return ioctl_set_read_timeouts(mi, (void __user *)arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) case INCFS_IOC_GET_LAST_READ_ERROR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) return ioctl_get_last_read_error(mi, (void __user *)arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) static const struct file_operations incfs_pending_reads_file_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) .read = pending_reads_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) .poll = pending_reads_poll,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) .open = pending_reads_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) .release = pending_reads_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) .llseek = noop_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) .unlocked_ioctl = pending_reads_dispatch_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) .compat_ioctl = pending_reads_dispatch_ioctl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) /*******************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) * .log pseudo file definition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) ******************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) #define INCFS_LOG_INODE 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) static const char log_file_name[] = INCFS_LOG_FILENAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) /* State of an open .log file, unique for each file descriptor. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) struct log_file_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) struct read_log_state state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) static ssize_t log_read(struct file *f, char __user *buf, size_t len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) struct log_file_state *log_state = f->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) struct mount_info *mi = get_mount_info(file_superblock(f));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) int total_reads_collected = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) int rl_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) ssize_t result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) bool report_uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) unsigned long page = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) struct incfs_pending_read_info *reads_buf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) struct incfs_pending_read_info2 *reads_buf2 = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) size_t record_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) ssize_t reads_to_collect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) ssize_t reads_per_page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) if (!mi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) report_uid = mi->mi_options.report_uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) record_size = report_uid ? sizeof(*reads_buf2) : sizeof(*reads_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) reads_to_collect = len / record_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) reads_per_page = PAGE_SIZE / record_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) rl_size = READ_ONCE(mi->mi_log.rl_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) if (rl_size == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) page = __get_free_page(GFP_NOFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) if (!page)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) if (report_uid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) reads_buf2 = (struct incfs_pending_read_info2 *)page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) reads_buf = (struct incfs_pending_read_info *)page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) reads_to_collect = min_t(ssize_t, rl_size, reads_to_collect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) while (reads_to_collect > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) struct read_log_state next_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) int reads_collected;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) memcpy(&next_state, &log_state->state, sizeof(next_state));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) reads_collected = incfs_collect_logged_reads(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) mi, &next_state, reads_buf, reads_buf2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) min_t(ssize_t, reads_to_collect, reads_per_page));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) if (reads_collected <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) result = total_reads_collected ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) total_reads_collected * record_size :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) reads_collected;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) if (copy_to_user(buf, (void *)page,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) reads_collected * record_size)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) result = total_reads_collected ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) total_reads_collected * record_size :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) memcpy(&log_state->state, &next_state, sizeof(next_state));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) total_reads_collected += reads_collected;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) buf += reads_collected * record_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) reads_to_collect -= reads_collected;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) result = total_reads_collected * record_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) *ppos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) free_page(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) static __poll_t log_poll(struct file *file, poll_table *wait)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) struct log_file_state *log_state = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) struct mount_info *mi = get_mount_info(file_superblock(file));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) __poll_t ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) poll_wait(file, &mi->mi_log.ml_notif_wq, wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) count = incfs_get_uncollected_logs_count(mi, &log_state->state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) if (count >= mi->mi_options.read_log_wakeup_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) ret = EPOLLIN | EPOLLRDNORM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) static int log_open(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) struct log_file_state *log_state = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) struct mount_info *mi = get_mount_info(file_superblock(file));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) log_state = kzalloc(sizeof(*log_state), GFP_NOFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) if (!log_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) log_state->state = incfs_get_log_state(mi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) file->private_data = log_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) static int log_release(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) kfree(file->private_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) static const struct file_operations incfs_log_file_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) .read = log_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) .poll = log_poll,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) .open = log_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) .release = log_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) .llseek = noop_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) /*******************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) * .blocks_written pseudo file definition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) ******************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) #define INCFS_BLOCKS_WRITTEN_INODE 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) static const char blocks_written_file_name[] = INCFS_BLOCKS_WRITTEN_FILENAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) /* State of an open .blocks_written file, unique for each file descriptor. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) struct blocks_written_file_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) unsigned long blocks_written;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) static ssize_t blocks_written_read(struct file *f, char __user *buf, size_t len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) struct mount_info *mi = get_mount_info(file_superblock(f));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) struct blocks_written_file_state *state = f->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) unsigned long blocks_written;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) char string[21];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) int result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) if (!mi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) blocks_written = atomic_read(&mi->mi_blocks_written);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) if (state->blocks_written == blocks_written)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) result = snprintf(string, sizeof(string), "%lu", blocks_written);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) if (result > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) result = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) if (copy_to_user(buf, string, result))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) state->blocks_written = blocks_written;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) static __poll_t blocks_written_poll(struct file *f, poll_table *wait)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) struct mount_info *mi = get_mount_info(file_superblock(f));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) struct blocks_written_file_state *state = f->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) unsigned long blocks_written;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) if (!mi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) poll_wait(f, &mi->mi_blocks_written_notif_wq, wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) blocks_written = atomic_read(&mi->mi_blocks_written);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) if (state->blocks_written == blocks_written)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) return EPOLLIN | EPOLLRDNORM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) static int blocks_written_open(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) struct blocks_written_file_state *state =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) kzalloc(sizeof(*state), GFP_NOFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) if (!state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) state->blocks_written = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) file->private_data = state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) static int blocks_written_release(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) kfree(file->private_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) static const struct file_operations incfs_blocks_written_file_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) .read = blocks_written_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) .poll = blocks_written_poll,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) .open = blocks_written_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) .release = blocks_written_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) .llseek = noop_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) /*******************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) * Generic inode lookup functionality
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) ******************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) const struct mem_range incfs_pseudo_file_names[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) { .data = (u8 *)pending_reads_file_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) .len = ARRAY_SIZE(pending_reads_file_name) - 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) { .data = (u8 *)log_file_name, .len = ARRAY_SIZE(log_file_name) - 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) { .data = (u8 *)blocks_written_file_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) .len = ARRAY_SIZE(blocks_written_file_name) - 1 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) const unsigned long incfs_pseudo_file_inodes[] = { INCFS_PENDING_READS_INODE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) INCFS_LOG_INODE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) INCFS_BLOCKS_WRITTEN_INODE };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) static const struct file_operations *const pseudo_file_operations[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) &incfs_pending_reads_file_ops, &incfs_log_file_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) &incfs_blocks_written_file_ops
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) static bool is_pseudo_filename(struct mem_range name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) for (; i < ARRAY_SIZE(incfs_pseudo_file_names); ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) if (incfs_equal_ranges(incfs_pseudo_file_names[i], name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) static bool get_pseudo_inode(int ino, struct inode *inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) for (; i < ARRAY_SIZE(incfs_pseudo_file_inodes); ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) if (ino == incfs_pseudo_file_inodes[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) if (i == ARRAY_SIZE(incfs_pseudo_file_inodes))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) inode->i_ctime = (struct timespec64){};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) inode->i_mtime = inode->i_ctime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) inode->i_atime = inode->i_ctime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) inode->i_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) inode->i_ino = ino;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) inode->i_private = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) inode_init_owner(inode, NULL, S_IFREG | READ_WRITE_FILE_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) inode->i_op = &incfs_file_inode_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) inode->i_fop = pseudo_file_operations[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) struct inode_search {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) unsigned long ino;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) static int inode_test(struct inode *inode, void *opaque)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) struct inode_search *search = opaque;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) return inode->i_ino == search->ino;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) static int inode_set(struct inode *inode, void *opaque)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) struct inode_search *search = opaque;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) if (get_pseudo_inode(search->ino, inode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) /* Unknown inode requested. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) static struct inode *fetch_inode(struct super_block *sb, unsigned long ino)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) struct inode_search search = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) .ino = ino
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) struct inode *inode = iget5_locked(sb, search.ino, inode_test,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) inode_set, &search);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) if (!inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) if (inode->i_state & I_NEW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) unlock_new_inode(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) return inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) int dir_lookup_pseudo_files(struct super_block *sb, struct dentry *dentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) struct mem_range name_range =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) range((u8 *)dentry->d_name.name, dentry->d_name.len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) unsigned long ino;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) struct inode *inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) for (; i < ARRAY_SIZE(incfs_pseudo_file_names); ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) if (incfs_equal_ranges(incfs_pseudo_file_names[i], name_range))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) if (i == ARRAY_SIZE(incfs_pseudo_file_names))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) ino = incfs_pseudo_file_inodes[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) inode = fetch_inode(sb, ino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) if (IS_ERR(inode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) return PTR_ERR(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) d_add(dentry, inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) int emit_pseudo_files(struct dir_context *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) loff_t i = ctx->pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) for (; i < ARRAY_SIZE(incfs_pseudo_file_names); ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) if (!dir_emit(ctx, incfs_pseudo_file_names[i].data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) incfs_pseudo_file_names[i].len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) incfs_pseudo_file_inodes[i], DT_REG))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) ctx->pos++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) }