^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (c) International Business Machines Corp., 2006
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Author: Artem Bityutskiy (Битюцкий Артём)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * This file includes implementation of UBI character device operations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * There are two kinds of character devices in UBI: UBI character devices and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * UBI volume character devices. UBI character devices allow users to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * manipulate whole volumes: create, remove, and re-size them. Volume character
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * devices provide volume I/O capabilities.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * Major and minor numbers are assigned dynamically to both UBI and volume
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * character devices.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * Well, there is the third kind of character devices - the UBI control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * character device, which allows to manipulate by UBI devices - create and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * delete them. In other words, it is used for attaching and detaching MTD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * devices.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/stat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/ioctl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/capability.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/compat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/math64.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <mtd/ubi-user.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include "ubi.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * get_exclusive - get exclusive access to an UBI volume.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * @desc: volume descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * This function changes UBI volume open mode to "exclusive". Returns previous
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * mode value (positive integer) in case of success and a negative error code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * in case of failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static int get_exclusive(struct ubi_volume_desc *desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) int users, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct ubi_volume *vol = desc->vol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) spin_lock(&vol->ubi->volumes_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) users = vol->readers + vol->writers + vol->exclusive + vol->metaonly;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) ubi_assert(users > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) if (users > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) ubi_err(vol->ubi, "%d users for volume %d", users, vol->vol_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) vol->readers = vol->writers = vol->metaonly = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) vol->exclusive = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) err = desc->mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) desc->mode = UBI_EXCLUSIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) spin_unlock(&vol->ubi->volumes_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * revoke_exclusive - revoke exclusive mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * @desc: volume descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * @mode: new mode to switch to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) static void revoke_exclusive(struct ubi_volume_desc *desc, int mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) struct ubi_volume *vol = desc->vol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) spin_lock(&vol->ubi->volumes_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) ubi_assert(vol->readers == 0 && vol->writers == 0 && vol->metaonly == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) ubi_assert(vol->exclusive == 1 && desc->mode == UBI_EXCLUSIVE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) vol->exclusive = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if (mode == UBI_READONLY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) vol->readers = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) else if (mode == UBI_READWRITE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) vol->writers = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) else if (mode == UBI_METAONLY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) vol->metaonly = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) vol->exclusive = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) spin_unlock(&vol->ubi->volumes_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) desc->mode = mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) static int vol_cdev_open(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) struct ubi_volume_desc *desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) int vol_id = iminor(inode) - 1, mode, ubi_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) ubi_num = ubi_major2num(imajor(inode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) if (ubi_num < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return ubi_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) if (file->f_mode & FMODE_WRITE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) mode = UBI_READWRITE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) mode = UBI_READONLY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) dbg_gen("open device %d, volume %d, mode %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) ubi_num, vol_id, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) desc = ubi_open_volume(ubi_num, vol_id, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) if (IS_ERR(desc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) return PTR_ERR(desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) file->private_data = desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static int vol_cdev_release(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) struct ubi_volume_desc *desc = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) struct ubi_volume *vol = desc->vol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) dbg_gen("release device %d, volume %d, mode %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) vol->ubi->ubi_num, vol->vol_id, desc->mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) if (vol->updating) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) ubi_warn(vol->ubi, "update of volume %d not finished, volume is damaged",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) vol->vol_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) ubi_assert(!vol->changing_leb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) vol->updating = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) vfree(vol->upd_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) } else if (vol->changing_leb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) dbg_gen("only %lld of %lld bytes received for atomic LEB change for volume %d:%d, cancel",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) vol->upd_received, vol->upd_bytes, vol->ubi->ubi_num,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) vol->vol_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) vol->changing_leb = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) vfree(vol->upd_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) ubi_close_volume(desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) static loff_t vol_cdev_llseek(struct file *file, loff_t offset, int origin)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) struct ubi_volume_desc *desc = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) struct ubi_volume *vol = desc->vol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (vol->updating) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) /* Update is in progress, seeking is prohibited */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) ubi_err(vol->ubi, "updating");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) return fixed_size_llseek(file, offset, origin, vol->used_bytes);
^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) static int vol_cdev_fsync(struct file *file, loff_t start, loff_t end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) int datasync)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) struct ubi_volume_desc *desc = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) struct ubi_device *ubi = desc->vol->ubi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) struct inode *inode = file_inode(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) inode_lock(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) err = ubi_sync(ubi->ubi_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) inode_unlock(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) static ssize_t vol_cdev_read(struct file *file, __user char *buf, size_t count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) loff_t *offp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) struct ubi_volume_desc *desc = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) struct ubi_volume *vol = desc->vol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) struct ubi_device *ubi = vol->ubi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) int err, lnum, off, len, tbuf_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) size_t count_save = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) void *tbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) dbg_gen("read %zd bytes from offset %lld of volume %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) count, *offp, vol->vol_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) if (vol->updating) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) ubi_err(vol->ubi, "updating");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) if (vol->upd_marker) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) ubi_err(vol->ubi, "damaged volume, update marker is set");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) return -EBADF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (*offp == vol->used_bytes || count == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) if (vol->corrupted)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) dbg_gen("read from corrupted volume %d", vol->vol_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (*offp + count > vol->used_bytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) count_save = count = vol->used_bytes - *offp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) tbuf_size = vol->usable_leb_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (count < tbuf_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) tbuf_size = ALIGN(count, ubi->min_io_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) tbuf = vmalloc(tbuf_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) if (!tbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) len = count > tbuf_size ? tbuf_size : count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) lnum = div_u64_rem(*offp, vol->usable_leb_size, &off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) cond_resched();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if (off + len >= vol->usable_leb_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) len = vol->usable_leb_size - off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) err = ubi_eba_read_leb(ubi, vol, lnum, tbuf, off, len, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) off += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (off == vol->usable_leb_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) lnum += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) off -= vol->usable_leb_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) count -= len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) *offp += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) err = copy_to_user(buf, tbuf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) buf += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) len = count > tbuf_size ? tbuf_size : count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) } while (count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) vfree(tbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) return err ? err : count_save - count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) * This function allows to directly write to dynamic UBI volumes, without
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) * issuing the volume update operation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) size_t count, loff_t *offp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) struct ubi_volume_desc *desc = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) struct ubi_volume *vol = desc->vol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) struct ubi_device *ubi = vol->ubi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) int lnum, off, len, tbuf_size, err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) size_t count_save = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) char *tbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) if (!vol->direct_writes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) dbg_gen("requested: write %zd bytes to offset %lld of volume %u",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) count, *offp, vol->vol_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) if (vol->vol_type == UBI_STATIC_VOLUME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) return -EROFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) lnum = div_u64_rem(*offp, vol->usable_leb_size, &off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) if (off & (ubi->min_io_size - 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) ubi_err(ubi, "unaligned position");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if (*offp + count > vol->used_bytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) count_save = count = vol->used_bytes - *offp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) /* We can write only in fractions of the minimum I/O unit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if (count & (ubi->min_io_size - 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) ubi_err(ubi, "unaligned write length");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) tbuf_size = vol->usable_leb_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) if (count < tbuf_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) tbuf_size = ALIGN(count, ubi->min_io_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) tbuf = vmalloc(tbuf_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) if (!tbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) len = count > tbuf_size ? tbuf_size : count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) while (count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) cond_resched();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) if (off + len >= vol->usable_leb_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) len = vol->usable_leb_size - off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) err = copy_from_user(tbuf, buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) err = ubi_eba_write_leb(ubi, vol, lnum, tbuf, off, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) off += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (off == vol->usable_leb_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) lnum += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) off -= vol->usable_leb_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) count -= len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) *offp += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) buf += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) len = count > tbuf_size ? tbuf_size : count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) vfree(tbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) return err ? err : count_save - count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) static ssize_t vol_cdev_write(struct file *file, const char __user *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) size_t count, loff_t *offp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) struct ubi_volume_desc *desc = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) struct ubi_volume *vol = desc->vol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) struct ubi_device *ubi = vol->ubi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) if (!vol->updating && !vol->changing_leb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) return vol_cdev_direct_write(file, buf, count, offp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (vol->updating)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) err = ubi_more_update_data(ubi, vol, buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) err = ubi_more_leb_change_data(ubi, vol, buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) ubi_err(ubi, "cannot accept more %zd bytes of data, error %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) count, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) * The operation is finished, @err contains number of actually
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) * written bytes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) count = err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) if (vol->changing_leb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) revoke_exclusive(desc, UBI_READWRITE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) * We voluntarily do not take into account the skip_check flag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) * as we want to make sure what we wrote was correctly written.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) err = ubi_check_volume(ubi, vol->vol_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) ubi_warn(ubi, "volume %d on UBI device %d is corrupted",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) vol->vol_id, ubi->ubi_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) vol->corrupted = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) vol->checked = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) ubi_volume_notify(ubi, vol, UBI_VOLUME_UPDATED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) revoke_exclusive(desc, UBI_READWRITE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) static long vol_cdev_ioctl(struct file *file, unsigned int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) struct ubi_volume_desc *desc = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) struct ubi_volume *vol = desc->vol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) struct ubi_device *ubi = vol->ubi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) void __user *argp = (void __user *)arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) /* Volume update command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) case UBI_IOCVOLUP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) int64_t bytes, rsvd_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) if (!capable(CAP_SYS_RESOURCE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) err = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) err = copy_from_user(&bytes, argp, sizeof(int64_t));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) if (desc->mode == UBI_READONLY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) err = -EROFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) rsvd_bytes = (long long)vol->reserved_pebs *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) vol->usable_leb_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) if (bytes < 0 || bytes > rsvd_bytes) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) err = get_exclusive(desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) err = ubi_start_update(ubi, vol, bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) if (bytes == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) ubi_volume_notify(ubi, vol, UBI_VOLUME_UPDATED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) revoke_exclusive(desc, UBI_READWRITE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) /* Atomic logical eraseblock change command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) case UBI_IOCEBCH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) struct ubi_leb_change_req req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) err = copy_from_user(&req, argp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) sizeof(struct ubi_leb_change_req));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (desc->mode == UBI_READONLY ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) vol->vol_type == UBI_STATIC_VOLUME) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) err = -EROFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) /* Validate the request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (!ubi_leb_valid(vol, req.lnum) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) req.bytes < 0 || req.bytes > vol->usable_leb_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) err = get_exclusive(desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) err = ubi_start_leb_change(ubi, vol, &req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) if (req.bytes == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) revoke_exclusive(desc, UBI_READWRITE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) /* Logical eraseblock erasure command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) case UBI_IOCEBER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) int32_t lnum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) err = get_user(lnum, (__user int32_t *)argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) if (desc->mode == UBI_READONLY ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) vol->vol_type == UBI_STATIC_VOLUME) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) err = -EROFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) if (!ubi_leb_valid(vol, lnum)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) dbg_gen("erase LEB %d:%d", vol->vol_id, lnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) err = ubi_eba_unmap_leb(ubi, vol, lnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) err = ubi_wl_flush(ubi, UBI_ALL, UBI_ALL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) /* Logical eraseblock map command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) case UBI_IOCEBMAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) struct ubi_map_req req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) err = copy_from_user(&req, argp, sizeof(struct ubi_map_req));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) err = ubi_leb_map(desc, req.lnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) /* Logical eraseblock un-map command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) case UBI_IOCEBUNMAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) int32_t lnum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) err = get_user(lnum, (__user int32_t *)argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) err = ubi_leb_unmap(desc, lnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) /* Check if logical eraseblock is mapped command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) case UBI_IOCEBISMAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) int32_t lnum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) err = get_user(lnum, (__user int32_t *)argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) err = ubi_is_mapped(desc, lnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) /* Set volume property command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) case UBI_IOCSETVOLPROP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) struct ubi_set_vol_prop_req req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) err = copy_from_user(&req, argp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) sizeof(struct ubi_set_vol_prop_req));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) switch (req.property) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) case UBI_VOL_PROP_DIRECT_WRITE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) mutex_lock(&ubi->device_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) desc->vol->direct_writes = !!req.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) mutex_unlock(&ubi->device_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) /* Create a R/O block device on top of the UBI volume */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) case UBI_IOCVOLCRBLK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) struct ubi_volume_info vi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) ubi_get_volume_info(desc, &vi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) err = ubiblock_create(&vi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) /* Remove the R/O block device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) case UBI_IOCVOLRMBLK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) struct ubi_volume_info vi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) ubi_get_volume_info(desc, &vi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) err = ubiblock_remove(&vi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) err = -ENOTTY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) * verify_mkvol_req - verify volume creation request.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) * @ubi: UBI device description object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) * @req: the request to check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) * This function zero if the request is correct, and %-EINVAL if not.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) static int verify_mkvol_req(const struct ubi_device *ubi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) const struct ubi_mkvol_req *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) int n, err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) if (req->bytes < 0 || req->alignment < 0 || req->vol_type < 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) req->name_len < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) goto bad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) if ((req->vol_id < 0 || req->vol_id >= ubi->vtbl_slots) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) req->vol_id != UBI_VOL_NUM_AUTO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) goto bad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) if (req->alignment == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) goto bad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) if (req->bytes == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) goto bad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) if (req->vol_type != UBI_DYNAMIC_VOLUME &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) req->vol_type != UBI_STATIC_VOLUME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) goto bad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) if (req->flags & ~UBI_VOL_VALID_FLGS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) goto bad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) if (req->flags & UBI_VOL_SKIP_CRC_CHECK_FLG &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) req->vol_type != UBI_STATIC_VOLUME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) goto bad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) if (req->alignment > ubi->leb_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) goto bad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) n = req->alignment & (ubi->min_io_size - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) if (req->alignment != 1 && n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) goto bad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) if (!req->name[0] || !req->name_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) goto bad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) if (req->name_len > UBI_VOL_NAME_MAX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) err = -ENAMETOOLONG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) goto bad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) n = strnlen(req->name, req->name_len + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) if (n != req->name_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) goto bad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) bad:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) ubi_err(ubi, "bad volume creation request");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) ubi_dump_mkvol_req(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) * verify_rsvol_req - verify volume re-size request.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) * @ubi: UBI device description object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) * @req: the request to check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) * This function returns zero if the request is correct, and %-EINVAL if not.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) static int verify_rsvol_req(const struct ubi_device *ubi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) const struct ubi_rsvol_req *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) if (req->bytes <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) if (req->vol_id < 0 || req->vol_id >= ubi->vtbl_slots)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) * rename_volumes - rename UBI volumes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) * @ubi: UBI device description object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) * @req: volumes re-name request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) * This is a helper function for the volume re-name IOCTL which validates the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) * the request, opens the volume and calls corresponding volumes management
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) * function. Returns zero in case of success and a negative error code in case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) * of failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) static int rename_volumes(struct ubi_device *ubi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) struct ubi_rnvol_req *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) int i, n, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) struct list_head rename_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) struct ubi_rename_entry *re, *re1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) if (req->count < 0 || req->count > UBI_MAX_RNVOL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) if (req->count == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) /* Validate volume IDs and names in the request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) for (i = 0; i < req->count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) if (req->ents[i].vol_id < 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) req->ents[i].vol_id >= ubi->vtbl_slots)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) if (req->ents[i].name_len < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) if (req->ents[i].name_len > UBI_VOL_NAME_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) return -ENAMETOOLONG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) req->ents[i].name[req->ents[i].name_len] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) n = strlen(req->ents[i].name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) if (n != req->ents[i].name_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) /* Make sure volume IDs and names are unique */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) for (i = 0; i < req->count - 1; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) for (n = i + 1; n < req->count; n++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) if (req->ents[i].vol_id == req->ents[n].vol_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) ubi_err(ubi, "duplicated volume id %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) req->ents[i].vol_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) if (!strcmp(req->ents[i].name, req->ents[n].name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) ubi_err(ubi, "duplicated volume name \"%s\"",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) req->ents[i].name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) /* Create the re-name list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) INIT_LIST_HEAD(&rename_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) for (i = 0; i < req->count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) int vol_id = req->ents[i].vol_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) int name_len = req->ents[i].name_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) const char *name = req->ents[i].name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) re = kzalloc(sizeof(struct ubi_rename_entry), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) if (!re) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) re->desc = ubi_open_volume(ubi->ubi_num, vol_id, UBI_METAONLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) if (IS_ERR(re->desc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) err = PTR_ERR(re->desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) ubi_err(ubi, "cannot open volume %d, error %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) vol_id, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) kfree(re);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) /* Skip this re-naming if the name does not really change */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) if (re->desc->vol->name_len == name_len &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) !memcmp(re->desc->vol->name, name, name_len)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) ubi_close_volume(re->desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) kfree(re);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) re->new_name_len = name_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) memcpy(re->new_name, name, name_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) list_add_tail(&re->list, &rename_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) dbg_gen("will rename volume %d from \"%s\" to \"%s\"",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) vol_id, re->desc->vol->name, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) if (list_empty(&rename_list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) /* Find out the volumes which have to be removed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) list_for_each_entry(re, &rename_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) struct ubi_volume_desc *desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) int no_remove_needed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) * Volume @re->vol_id is going to be re-named to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) * @re->new_name, while its current name is @name. If a volume
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) * with name @re->new_name currently exists, it has to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) * removed, unless it is also re-named in the request (@req).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) list_for_each_entry(re1, &rename_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) if (re->new_name_len == re1->desc->vol->name_len &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) !memcmp(re->new_name, re1->desc->vol->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) re1->desc->vol->name_len)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) no_remove_needed = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) if (no_remove_needed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) * It seems we need to remove volume with name @re->new_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) * if it exists.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) desc = ubi_open_volume_nm(ubi->ubi_num, re->new_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) UBI_EXCLUSIVE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) if (IS_ERR(desc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) err = PTR_ERR(desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) if (err == -ENODEV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) /* Re-naming into a non-existing volume name */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) /* The volume exists but busy, or an error occurred */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) ubi_err(ubi, "cannot open volume \"%s\", error %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) re->new_name, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) re1 = kzalloc(sizeof(struct ubi_rename_entry), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) if (!re1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) ubi_close_volume(desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) re1->remove = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) re1->desc = desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) list_add(&re1->list, &rename_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) dbg_gen("will remove volume %d, name \"%s\"",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) re1->desc->vol->vol_id, re1->desc->vol->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) mutex_lock(&ubi->device_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) err = ubi_rename_volumes(ubi, &rename_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) mutex_unlock(&ubi->device_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) list_for_each_entry_safe(re, re1, &rename_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) ubi_close_volume(re->desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) list_del(&re->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) kfree(re);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) static long ubi_cdev_ioctl(struct file *file, unsigned int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) struct ubi_device *ubi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) struct ubi_volume_desc *desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) void __user *argp = (void __user *)arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) if (!capable(CAP_SYS_RESOURCE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) ubi = ubi_get_by_major(imajor(file->f_mapping->host));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) if (!ubi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) /* Create volume command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) case UBI_IOCMKVOL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) struct ubi_mkvol_req req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) dbg_gen("create volume");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) err = copy_from_user(&req, argp, sizeof(struct ubi_mkvol_req));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) err = verify_mkvol_req(ubi, &req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) mutex_lock(&ubi->device_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) err = ubi_create_volume(ubi, &req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) mutex_unlock(&ubi->device_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) err = put_user(req.vol_id, (__user int32_t *)argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) break;
^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) /* Remove volume command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) case UBI_IOCRMVOL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) int vol_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) dbg_gen("remove volume");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) err = get_user(vol_id, (__user int32_t *)argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) desc = ubi_open_volume(ubi->ubi_num, vol_id, UBI_EXCLUSIVE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) if (IS_ERR(desc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) err = PTR_ERR(desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) mutex_lock(&ubi->device_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) err = ubi_remove_volume(desc, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) mutex_unlock(&ubi->device_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) * The volume is deleted (unless an error occurred), and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) * 'struct ubi_volume' object will be freed when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) * 'ubi_close_volume()' will call 'put_device()'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) ubi_close_volume(desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) /* Re-size volume command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) case UBI_IOCRSVOL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) int pebs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) struct ubi_rsvol_req req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) dbg_gen("re-size volume");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) err = copy_from_user(&req, argp, sizeof(struct ubi_rsvol_req));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) err = verify_rsvol_req(ubi, &req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) desc = ubi_open_volume(ubi->ubi_num, req.vol_id, UBI_EXCLUSIVE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) if (IS_ERR(desc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) err = PTR_ERR(desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) pebs = div_u64(req.bytes + desc->vol->usable_leb_size - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) desc->vol->usable_leb_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) mutex_lock(&ubi->device_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) err = ubi_resize_volume(desc, pebs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) mutex_unlock(&ubi->device_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) ubi_close_volume(desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) /* Re-name volumes command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) case UBI_IOCRNVOL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) struct ubi_rnvol_req *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) dbg_gen("re-name volumes");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) req = kmalloc(sizeof(struct ubi_rnvol_req), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) if (!req) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) err = copy_from_user(req, argp, sizeof(struct ubi_rnvol_req));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) kfree(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) err = rename_volumes(ubi, req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) kfree(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) /* Check a specific PEB for bitflips and scrub it if needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) case UBI_IOCRPEB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) int pnum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) err = get_user(pnum, (__user int32_t *)argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) err = ubi_bitflip_check(ubi, pnum, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) /* Force scrubbing for a specific PEB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) case UBI_IOCSPEB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) int pnum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) err = get_user(pnum, (__user int32_t *)argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) err = ubi_bitflip_check(ubi, pnum, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) err = -ENOTTY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) ubi_put_device(ubi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) static long ctrl_cdev_ioctl(struct file *file, unsigned int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) void __user *argp = (void __user *)arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) if (!capable(CAP_SYS_RESOURCE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) /* Attach an MTD device command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) case UBI_IOCATT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) struct ubi_attach_req req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) struct mtd_info *mtd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) dbg_gen("attach MTD device");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) err = copy_from_user(&req, argp, sizeof(struct ubi_attach_req));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) if (req.mtd_num < 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) (req.ubi_num < 0 && req.ubi_num != UBI_DEV_NUM_AUTO)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) mtd = get_mtd_device(NULL, req.mtd_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) if (IS_ERR(mtd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) err = PTR_ERR(mtd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) * Note, further request verification is done by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) * 'ubi_attach_mtd_dev()'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) mutex_lock(&ubi_devices_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) err = ubi_attach_mtd_dev(mtd, req.ubi_num, req.vid_hdr_offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) req.max_beb_per1024);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) mutex_unlock(&ubi_devices_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) put_mtd_device(mtd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) /* @err contains UBI device number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) err = put_user(err, (__user int32_t *)argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) break;
^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) /* Detach an MTD device command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) case UBI_IOCDET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) int ubi_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) dbg_gen("detach MTD device");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) err = get_user(ubi_num, (__user int32_t *)argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) mutex_lock(&ubi_devices_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) err = ubi_detach_mtd_dev(ubi_num, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) mutex_unlock(&ubi_devices_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) err = -ENOTTY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) /* UBI volume character device operations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) const struct file_operations ubi_vol_cdev_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) .open = vol_cdev_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) .release = vol_cdev_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) .llseek = vol_cdev_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) .read = vol_cdev_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) .write = vol_cdev_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) .fsync = vol_cdev_fsync,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) .unlocked_ioctl = vol_cdev_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) .compat_ioctl = compat_ptr_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) /* UBI character device operations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) const struct file_operations ubi_cdev_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) .llseek = no_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) .unlocked_ioctl = ubi_cdev_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) .compat_ioctl = compat_ptr_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) /* UBI control character device operations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) const struct file_operations ubi_ctrl_cdev_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) .unlocked_ioctl = ctrl_cdev_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) .compat_ioctl = compat_ptr_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) .llseek = no_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) };