--- zzzz-none-000/linux-3.10.107/drivers/mtd/ubi/cdev.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/drivers/mtd/ubi/cdev.c 2021-02-04 17:41:59.000000000 +0000 @@ -60,13 +60,13 @@ struct ubi_volume *vol = desc->vol; spin_lock(&vol->ubi->volumes_lock); - users = vol->readers + vol->writers + vol->exclusive; + users = vol->readers + vol->writers + vol->exclusive + vol->metaonly; ubi_assert(users > 0); if (users > 1) { - ubi_err("%d users for volume %d", users, vol->vol_id); + ubi_err(vol->ubi, "%d users for volume %d", users, vol->vol_id); err = -EBUSY; } else { - vol->readers = vol->writers = 0; + vol->readers = vol->writers = vol->metaonly = 0; vol->exclusive = 1; err = desc->mode; desc->mode = UBI_EXCLUSIVE; @@ -86,13 +86,15 @@ struct ubi_volume *vol = desc->vol; spin_lock(&vol->ubi->volumes_lock); - ubi_assert(vol->readers == 0 && vol->writers == 0); + ubi_assert(vol->readers == 0 && vol->writers == 0 && vol->metaonly == 0); ubi_assert(vol->exclusive == 1 && desc->mode == UBI_EXCLUSIVE); vol->exclusive = 0; if (mode == UBI_READONLY) vol->readers = 1; else if (mode == UBI_READWRITE) vol->writers = 1; + else if (mode == UBI_METAONLY) + vol->metaonly = 1; else vol->exclusive = 1; spin_unlock(&vol->ubi->volumes_lock); @@ -134,7 +136,7 @@ vol->ubi->ubi_num, vol->vol_id, desc->mode); if (vol->updating) { - ubi_warn("update of volume %d not finished, volume is damaged", + ubi_warn(vol->ubi, "update of volume %d not finished, volume is damaged", vol->vol_id); ubi_assert(!vol->changing_leb); vol->updating = 0; @@ -155,38 +157,14 @@ { struct ubi_volume_desc *desc = file->private_data; struct ubi_volume *vol = desc->vol; - loff_t new_offset; if (vol->updating) { /* Update is in progress, seeking is prohibited */ - ubi_err("updating"); + ubi_err(vol->ubi, "updating"); return -EBUSY; } - switch (origin) { - case 0: /* SEEK_SET */ - new_offset = offset; - break; - case 1: /* SEEK_CUR */ - new_offset = file->f_pos + offset; - break; - case 2: /* SEEK_END */ - new_offset = vol->used_bytes + offset; - break; - default: - return -EINVAL; - } - - if (new_offset < 0 || new_offset > vol->used_bytes) { - ubi_err("bad seek %lld", new_offset); - return -EINVAL; - } - - dbg_gen("seek volume %d, offset %lld, origin %d, new offset %lld", - vol->vol_id, offset, origin, new_offset); - - file->f_pos = new_offset; - return new_offset; + return fixed_size_llseek(file, offset, origin, vol->used_bytes); } static int vol_cdev_fsync(struct file *file, loff_t start, loff_t end, @@ -217,11 +195,11 @@ count, *offp, vol->vol_id); if (vol->updating) { - ubi_err("updating"); + ubi_err(vol->ubi, "updating"); return -EBUSY; } if (vol->upd_marker) { - ubi_err("damaged volume, update marker is set"); + ubi_err(vol->ubi, "damaged volume, update marker is set"); return -EBADF; } if (*offp == vol->used_bytes || count == 0) @@ -301,7 +279,7 @@ lnum = div_u64_rem(*offp, vol->usable_leb_size, &off); if (off & (ubi->min_io_size - 1)) { - ubi_err("unaligned position"); + ubi_err(ubi, "unaligned position"); return -EINVAL; } @@ -310,7 +288,7 @@ /* We can write only in fractions of the minimum I/O unit */ if (count & (ubi->min_io_size - 1)) { - ubi_err("unaligned write length"); + ubi_err(ubi, "unaligned write length"); return -EINVAL; } @@ -372,7 +350,7 @@ err = ubi_more_leb_change_data(ubi, vol, buf, count); if (err < 0) { - ubi_err("cannot accept more %zd bytes of data, error %d", + ubi_err(ubi, "cannot accept more %zd bytes of data, error %d", count, err); return err; } @@ -394,7 +372,7 @@ return err; if (err) { - ubi_warn("volume %d on UBI device %d is corrupted", + ubi_warn(ubi, "volume %d on UBI device %d is corrupted", vol->vol_id, ubi->ubi_num); vol->corrupted = 1; } @@ -449,8 +427,10 @@ break; err = ubi_start_update(ubi, vol, bytes); - if (bytes == 0) + if (bytes == 0) { + ubi_volume_notify(ubi, vol, UBI_VOLUME_UPDATED); revoke_exclusive(desc, UBI_READWRITE); + } break; } @@ -585,6 +565,26 @@ break; } + /* Create a R/O block device on top of the UBI volume */ + case UBI_IOCVOLCRBLK: + { + struct ubi_volume_info vi; + + ubi_get_volume_info(desc, &vi); + err = ubiblock_create(&vi); + break; + } + + /* Remove the R/O block device */ + case UBI_IOCVOLRMBLK: + { + struct ubi_volume_info vi; + + ubi_get_volume_info(desc, &vi); + err = ubiblock_remove(&vi); + break; + } + default: err = -ENOTTY; break; @@ -644,7 +644,7 @@ return 0; bad: - ubi_err("bad volume creation request"); + ubi_err(ubi, "bad volume creation request"); ubi_dump_mkvol_req(req); return err; } @@ -703,19 +703,19 @@ req->ents[i].name[req->ents[i].name_len] = '\0'; n = strlen(req->ents[i].name); if (n != req->ents[i].name_len) - err = -EINVAL; + return -EINVAL; } /* Make sure volume IDs and names are unique */ for (i = 0; i < req->count - 1; i++) { for (n = i + 1; n < req->count; n++) { if (req->ents[i].vol_id == req->ents[n].vol_id) { - ubi_err("duplicated volume id %d", + ubi_err(ubi, "duplicated volume id %d", req->ents[i].vol_id); return -EINVAL; } if (!strcmp(req->ents[i].name, req->ents[n].name)) { - ubi_err("duplicated volume name \"%s\"", + ubi_err(ubi, "duplicated volume name \"%s\"", req->ents[i].name); return -EINVAL; } @@ -735,10 +735,11 @@ goto out_free; } - re->desc = ubi_open_volume(ubi->ubi_num, vol_id, UBI_EXCLUSIVE); + re->desc = ubi_open_volume(ubi->ubi_num, vol_id, UBI_METAONLY); if (IS_ERR(re->desc)) { err = PTR_ERR(re->desc); - ubi_err("cannot open volume %d, error %d", vol_id, err); + ubi_err(ubi, "cannot open volume %d, error %d", + vol_id, err); kfree(re); goto out_free; } @@ -797,7 +798,7 @@ continue; /* The volume exists but busy, or an error occurred */ - ubi_err("cannot open volume \"%s\", error %d", + ubi_err(ubi, "cannot open volume \"%s\", error %d", re->new_name, err); goto out_free; } @@ -948,7 +949,7 @@ if (!req) { err = -ENOMEM; break; - }; + } err = copy_from_user(req, argp, sizeof(struct ubi_rnvol_req)); if (err) { @@ -974,7 +975,7 @@ static long ctrl_cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - int err = 0; + int err = 0, force = 0; void __user *argp = (void __user *)arg; if (!capable(CAP_SYS_RESOURCE)) @@ -1024,6 +1025,10 @@ } /* Detach an MTD device command */ + case UBI_IOCFDET: + force = 1; + /* fallthrough */ + case UBI_IOCDET: { int ubi_num; @@ -1036,7 +1041,7 @@ } mutex_lock(&ubi_devices_mutex); - err = ubi_detach_mtd_dev(ubi_num, 0); + err = ubi_detach_mtd_dev(ubi_num, force); mutex_unlock(&ubi_devices_mutex); break; }