int ubifs_size(const char *filename, loff_t *size) { struct ubifs_info *c = ubifs_sb->s_fs_info; unsigned long inum; struct inode *inode; int err = 0; c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY); inum = ubifs_findfile(ubifs_sb, (char *)filename); if (!inum) { err = -1; goto out; } inode = ubifs_iget(ubifs_sb, inum); if (IS_ERR(inode)) { printf("%s: Error reading inode %ld!\n", __func__, inum); err = PTR_ERR(inode); goto out; } *size = inode->i_size; ubifs_iput(inode); out: ubi_close_volume(c->ubi); return err; }
int ubifs_mount(char *name) { int flags; void *data; struct vfsmount *mnt; int ret; struct ubifs_info *c; /* * First unmount if allready mounted */ if (ubifs_sb) ubifs_umount(ubifs_sb->s_fs_info); INIT_LIST_HEAD(&ubifs_infos); INIT_LIST_HEAD(&ubifs_fs_type.fs_supers); /* * Mount in read-only mode */ flags = MS_RDONLY; data = NULL; mnt = NULL; ret = ubifs_get_sb(&ubifs_fs_type, flags, name, data, mnt); if (ret) { ubifs_err("Error reading superblock on volume '%s' errno=%d!\n", name, ret); return -1; } c = ubifs_sb->s_fs_info; ubi_close_volume(c->ubi); return 0; }
/** * gluebi_put_device - put MTD device reference. * @mtd: the MTD device description object * * This function is called every time the MTD device is being put. Returns * zero in case of success and a negative error code in case of failure. */ static void gluebi_put_device(struct mtd_info *mtd) { struct ubi_volume *vol; vol = container_of(mtd, struct ubi_volume, gluebi_mtd); vol->gluebi_refcount -= 1; ubi_assert(vol->gluebi_refcount >= 0); if (vol->gluebi_refcount == 0) ubi_close_volume(vol->gluebi_desc); }
int ubifs_exists(const char *filename) { struct ubifs_info *c = ubifs_sb->s_fs_info; unsigned long inum; c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY); inum = ubifs_findfile(ubifs_sb, (char *)filename); ubi_close_volume(c->ubi); return inum != 0; }
static void ubifs_remove(struct device_d *dev) { struct ubifs_priv *priv = dev->priv; struct super_block *sb = priv->sb; struct ubifs_info *c = sb->s_fs_info; ubifs_umount(c); ubi_close_volume(priv->ubi); free(c); free(priv); }
BAREBOX_CMD_END static int get_vol_id(u32 ubi_num, const char *name) { struct ubi_volume_desc *desc; struct ubi_volume_info vi; desc = ubi_open_volume_nm(ubi_num, name, UBI_READONLY); if(IS_ERR(desc)) return PTR_ERR(desc); ubi_get_volume_info(desc, &vi); ubi_close_volume(desc); return vi.vol_id; };
int ubifs_ls(char *filename) { struct ubifs_info *c = ubifs_sb->s_fs_info; struct file *file; struct dentry *dentry; struct inode *dir; void *dirent = NULL; unsigned long inum; int ret = 0; c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY); inum = ubifs_findfile(ubifs_sb, filename); if (!inum) { ret = -1; goto out; } file = kzalloc(sizeof(struct file), 0); dentry = kzalloc(sizeof(struct dentry), 0); dir = kzalloc(sizeof(struct inode), 0); if (!file || !dentry || !dir) { printf("%s: Error, no memory for malloc!\n", __func__); ret = -ENOMEM; goto out_mem; } dir->i_sb = ubifs_sb; file->f_path.dentry = dentry; file->f_path.dentry->d_parent = dentry; file->f_path.dentry->d_inode = dir; file->f_path.dentry->d_inode->i_ino = inum; file->f_pos = 1; file->private_data = NULL; ubifs_printdir(file, dirent); out_mem: if (file) free(file); if (dentry) free(dentry); if (dir) free(dir); out: ubi_close_volume(c->ubi); return ret; }
static int vol_cdev_release(struct inode *inode, struct file *file) { struct ubi_volume_desc *desc = file->private_data; struct ubi_volume *vol = desc->vol; dbg_msg("release volume %d, mode %d", vol->vol_id, desc->mode); if (vol->updating) { ubi_warn("update of volume %d not finished, volume is damaged", vol->vol_id); vol->updating = 0; kfree(vol->upd_buf); } ubi_close_volume(desc); return 0; }
int ubifs_filesize(char *filename, u32* size) { struct ubifs_info *c = ubifs_sb->s_fs_info; unsigned long inum=0; struct inode *inode=NULL; int err = 0; c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY); if (IS_ERR(c->ubi)) { err = PTR_ERR(c->ubi); goto out_no_close; } inum = ubifs_findfile(ubifs_sb, filename); if (!inum) { err = -1; goto out; } /* * Read file inode */ inode = ubifs_iget(ubifs_sb, inum); if (IS_ERR(inode)) { printf("%s: Error reading inode %ld!\n", __func__, inum); err = PTR_ERR(inode); goto out; } /* * If no size was specified or if size bigger than filesize * set size to filesize */ //if ((size == 0) || (size > inode->i_size)) *size = inode->i_size; printf("ubifs_filesize %08x \n", *size); //return 0; out: ubi_close_volume(c->ubi); out_no_close: return err; }
static void ubiblk_exit(void) { int i; for (i = 0; i < ndevices; i++) { struct ubiblk_dev *dev = Devices + i; if (dev->gd) { del_gendisk(dev->gd); put_disk(dev->gd); } if (dev->queue) { blk_cleanup_queue(dev->queue); } if (dev->ubi_vol) { ubi_close_volume(dev->ubi_vol); } } unregister_blkdev(ubiblk_major, "ubiblk"); kfree(Devices); }
BAREBOX_CMD_END static int do_ubirmvol(int argc, char *argv[]) { struct ubi_volume_desc *desc; uint32_t ubinum; int fd, ret; if (argc != 3) return COMMAND_ERROR_USAGE; fd = open(argv[1], O_WRONLY); if (fd < 0) { perror("open"); return 1; } ret = ioctl(fd, UBI_IOCGETUBINUM, &ubinum); if (ret) { printf("failed to get ubinum: %s\n", strerror(-ret)); goto err; } desc = ubi_open_volume_nm(ubinum, argv[2], UBI_EXCLUSIVE); if (IS_ERR(desc)) { ret = PTR_ERR(desc); printf("failed to open volume %s: %s\n", argv[2], strerror(-ret)); goto err; } ret = ubi_api_remove_volume(desc, 0); if (ret) printf("failed to remove volume %s: %s\n", argv[2], strerror(-ret)); ubi_close_volume(desc); err: close(fd); return ret ? 1 : 0; }
static int ubi_cdev_ioctl(struct cdev *cdev, int cmd, void *buf) { struct ubi_volume_desc *desc; struct ubi_device *ubi = cdev->priv; struct ubi_mkvol_req *req = buf; switch (cmd) { case UBI_IOCRMVOL: desc = ubi_open_volume_nm(ubi->ubi_num, req->name, UBI_EXCLUSIVE); if (IS_ERR(desc)) return PTR_ERR(desc); ubi_remove_volume(desc, 0); ubi_close_volume(desc); break; case UBI_IOCMKVOL: if (!req->bytes) req->bytes = (__s64)ubi->avail_pebs * ubi->leb_size; return ubi_create_volume(ubi, req); }; return 0; }
static int ubifs_probe(struct device_d *dev) { struct fs_device_d *fsdev = dev_to_fs_device(dev); struct ubifs_priv *priv = xzalloc(sizeof(struct ubifs_priv)); int ret; dev->priv = priv; ret = fsdev_open_cdev(fsdev); if (ret) goto err_free; priv->cdev = fsdev->cdev; priv->ubi = ubi_open_volume_cdev(priv->cdev, UBI_READONLY); if (IS_ERR(priv->ubi)) { dev_err(dev, "failed to open ubi volume: %s\n", strerrorp(priv->ubi)); ret = PTR_ERR(priv->ubi); goto err_free; } ret = ubifs_get_super(dev, priv->ubi, 0); if (ret) goto err; priv->sb = &fsdev->sb; ubifs_set_rootarg(priv, fsdev); return 0; err: ubi_close_volume(priv->ubi); err_free: free(priv); return ret; }
static int vol_cdev_release(struct inode *inode, struct file *file) { struct ubi_volume_desc *desc = file->private_data; struct ubi_volume *vol = desc->vol; dbg_msg("release volume %d, mode %d", vol->vol_id, desc->mode); if (vol->updating) { ubi_warn("update of volume %d not finished, volume is damaged", vol->vol_id); ubi_assert(!vol->changing_leb); vol->updating = 0; vfree(vol->upd_buf); } else if (vol->changing_leb) { dbg_msg("only %lld of %lld bytes received for atomic LEB change" " for volume %d:%d, cancel", vol->upd_received, vol->upd_bytes, vol->ubi->ubi_num, vol->vol_id); vol->changing_leb = 0; vfree(vol->upd_buf); } ubi_close_volume(desc); return 0; }
/** * ubi_open_volume - open UBI volume. * @ubi_num: UBI device number * @vol_id: volume ID * @mode: open mode * * The @mode parameter specifies if the volume should be opened in read-only * mode, read-write mode, or exclusive mode. The exclusive mode guarantees that * nobody else will be able to open this volume. UBI allows to have many volume * readers and one writer at a time. * * If a static volume is being opened for the first time since boot, it will be * checked by this function, which means it will be fully read and the CRC * checksum of each logical eraseblock will be checked. * * This function returns volume descriptor in case of success and a negative * error code in case of failure. */ struct ubi_volume_desc *ubi_open_volume(int ubi_num, int vol_id, int mode) { int err; struct ubi_volume_desc *desc; struct ubi_device *ubi; struct ubi_volume *vol; dbg_gen("open device %d, volume %d, mode %d", ubi_num, vol_id, mode); if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES) return ERR_PTR(-EINVAL); if (mode != UBI_READONLY && mode != UBI_READWRITE && mode != UBI_EXCLUSIVE) return ERR_PTR(-EINVAL); /* * First of all, we have to get the UBI device to prevent its removal. */ ubi = ubi_get_device(ubi_num); if (!ubi) return ERR_PTR(-ENODEV); if (vol_id < 0 || vol_id >= ubi->vtbl_slots) { err = -EINVAL; goto out_put_ubi; } desc = kmalloc(sizeof(struct ubi_volume_desc), GFP_KERNEL); if (!desc) { err = -ENOMEM; goto out_put_ubi; } err = -ENODEV; if (!try_module_get(THIS_MODULE)) goto out_free; spin_lock(&ubi->volumes_lock); vol = ubi->volumes[vol_id]; if (!vol) goto out_unlock; err = -EBUSY; switch (mode) { case UBI_READONLY: if (vol->exclusive) goto out_unlock; vol->readers += 1; break; case UBI_READWRITE: if (vol->exclusive || vol->writers > 0) goto out_unlock; vol->writers += 1; break; case UBI_EXCLUSIVE: if (vol->exclusive || vol->writers || vol->readers) goto out_unlock; vol->exclusive = 1; break; } get_device(&vol->dev); vol->ref_count += 1; spin_unlock(&ubi->volumes_lock); desc->vol = vol; desc->mode = mode; mutex_lock(&ubi->ckvol_mutex); if (!vol->checked) { /* This is the first open - check the volume */ err = ubi_check_volume(ubi, vol_id); if (err < 0) { mutex_unlock(&ubi->ckvol_mutex); ubi_close_volume(desc); return ERR_PTR(err); } if (err == 1) { ubi_warn("volume %d on UBI device %d is corrupted", vol_id, ubi->ubi_num); vol->corrupted = 1; } vol->checked = 1; } mutex_unlock(&ubi->ckvol_mutex); return desc; out_unlock: spin_unlock(&ubi->volumes_lock); module_put(THIS_MODULE); out_free: kfree(desc); out_put_ubi: ubi_put_device(ubi); dbg_err("cannot open device %d, volume %d, error %d", ubi_num, vol_id, err); return ERR_PTR(err); }
int ubifs_read(const char *filename, void *buf, loff_t offset, loff_t size, loff_t *actread) { struct ubifs_info *c = ubifs_sb->s_fs_info; unsigned long inum; struct inode *inode; struct page page; int err = 0; int i; int count; int last_block_size = 0; *actread = 0; if (offset & (PAGE_SIZE - 1)) { printf("ubifs: Error offset must be a multple of %d\n", PAGE_SIZE); return -1; } c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY); /* ubifs_findfile will resolve symlinks, so we know that we get * the real file here */ inum = ubifs_findfile(ubifs_sb, (char *)filename); if (!inum) { err = -1; goto out; } /* * Read file inode */ inode = ubifs_iget(ubifs_sb, inum); if (IS_ERR(inode)) { printf("%s: Error reading inode %ld!\n", __func__, inum); err = PTR_ERR(inode); goto out; } if (offset > inode->i_size) { printf("ubifs: Error offset (%lld) > file-size (%lld)\n", offset, size); err = -1; goto put_inode; } /* * If no size was specified or if size bigger than filesize * set size to filesize */ if ((size == 0) || (size > (inode->i_size - offset))) size = inode->i_size - offset; count = (size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT; page.addr = buf; page.index = offset / PAGE_SIZE; page.inode = inode; for (i = 0; i < count; i++) { /* * Make sure to not read beyond the requested size */ if (((i + 1) == count) && (size < inode->i_size)) last_block_size = size - (i * PAGE_SIZE); err = do_readpage(c, inode, &page, last_block_size); if (err) break; page.addr += PAGE_SIZE; page.index++; } if (err) { printf("Error reading file '%s'\n", filename); *actread = i * PAGE_SIZE; } else { *actread = size; } put_inode: ubifs_iput(inode); out: ubi_close_volume(c->ubi); return err; }
int ubifs_load(char *filename, u32 addr, u32 size) { struct ubifs_info *c = ubifs_sb->s_fs_info; unsigned long inum; struct inode *inode; struct page page; int err = 0; int i; int count; int last_block_size = 0; c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY); /* ubifs_findfile will resolve symlinks, so we know that we get * the real file here */ inum = ubifs_findfile(ubifs_sb, filename); if (!inum) { err = -1; goto out; } /* * Read file inode */ inode = ubifs_iget(ubifs_sb, inum); if (IS_ERR(inode)) { printf("%s: Error reading inode %ld!\n", __func__, inum); err = PTR_ERR(inode); goto out; } /* * If no size was specified or if size bigger than filesize * set size to filesize */ if ((size == 0) || (size > inode->i_size)) size = inode->i_size; count = (size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT; printf("Loading file '%s' to addr 0x%08x with size %d (0x%08x)...\n", filename, addr, size, size); page.addr = (void *)addr; page.index = 0; page.inode = inode; for (i = 0; i < count; i++) { /* * Make sure to not read beyond the requested size */ if ((i + 1) == count) last_block_size = size - (i * PAGE_SIZE); err = do_readpage(c, inode, &page, last_block_size); if (err) break; page.addr += PAGE_SIZE; page.index++; } if (err) printf("Error reading file '%s'\n", filename); else printf("Done\n"); ubifs_iput(inode); out: ubi_close_volume(c->ubi); return err; }
static int ubi_cdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { int err = 0; struct ubi_device *ubi; struct ubi_volume_desc *desc; void __user *argp = (void __user *)arg; if (_IOC_NR(cmd) > UBI_CDEV_IOC_MAX_SEQ || _IOC_TYPE(cmd) != UBI_IOC_MAGIC) return -ENOTTY; if (_IOC_DIR(cmd) && _IOC_READ) err = !access_ok(VERIFY_WRITE, argp, _IOC_SIZE(cmd)); else if (_IOC_DIR(cmd) && _IOC_WRITE) err = !access_ok(VERIFY_READ, argp, _IOC_SIZE(cmd)); if (err) return -EFAULT; if (!capable(CAP_SYS_RESOURCE)) return -EPERM; ubi = major_to_device(imajor(inode)); if (IS_ERR(ubi)) return PTR_ERR(ubi); switch (cmd) { /* Create volume command */ case UBI_IOCMKVOL: { struct ubi_mkvol_req req; dbg_msg("create volume"); err = __copy_from_user(&req, argp, sizeof(struct ubi_mkvol_req)); if (err) { err = -EFAULT; break; } err = verify_mkvol_req(ubi, &req); if (err) break; req.name[req.name_len] = '\0'; err = ubi_create_volume(ubi, &req); if (err) break; err = __put_user(req.vol_id, (__user int32_t *)argp); if (err) err = -EFAULT; break; } /* Remove volume command */ case UBI_IOCRMVOL: { int vol_id; dbg_msg("remove volume"); err = __get_user(vol_id, (__user int32_t *)argp); if (err) { err = -EFAULT; break; } desc = ubi_open_volume(ubi->ubi_num, vol_id, UBI_EXCLUSIVE); if (IS_ERR(desc)) { err = PTR_ERR(desc); break; } err = ubi_remove_volume(desc); if (err) ubi_close_volume(desc); break; } /* Re-size volume command */ case UBI_IOCRSVOL: { int pebs; uint64_t tmp; struct ubi_rsvol_req req; dbg_msg("re-size volume"); err = __copy_from_user(&req, argp, sizeof(struct ubi_rsvol_req)); if (err) { err = -EFAULT; break; } err = verify_rsvol_req(ubi, &req); if (err) break; desc = ubi_open_volume(ubi->ubi_num, req.vol_id, UBI_EXCLUSIVE); if (IS_ERR(desc)) { err = PTR_ERR(desc); break; } tmp = req.bytes; pebs = !!do_div(tmp, desc->vol->usable_leb_size); pebs += tmp; err = ubi_resize_volume(desc, pebs); ubi_close_volume(desc); break; } default: err = -ENOTTY; break; } return err; }
static int ubi_cdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { int err = 0; struct ubi_device *ubi; struct ubi_volume_desc *desc; void __user *argp = (void __user *)arg; if (!capable(CAP_SYS_RESOURCE)) return -EPERM; ubi = ubi_get_by_major(imajor(inode)); if (!ubi) return -ENODEV; switch (cmd) { /* Create volume command */ case UBI_IOCMKVOL: { struct ubi_mkvol_req req; dbg_msg("create volume"); err = copy_from_user(&req, argp, sizeof(struct ubi_mkvol_req)); if (err) { err = -EFAULT; break; } err = verify_mkvol_req(ubi, &req); if (err) break; req.name[req.name_len] = '\0'; mutex_lock(&ubi->volumes_mutex); err = ubi_create_volume(ubi, &req); mutex_unlock(&ubi->volumes_mutex); if (err) break; err = put_user(req.vol_id, (__user int32_t *)argp); if (err) err = -EFAULT; break; } /* Remove volume command */ case UBI_IOCRMVOL: { int vol_id; dbg_msg("remove volume"); err = get_user(vol_id, (__user int32_t *)argp); if (err) { err = -EFAULT; break; } desc = ubi_open_volume(ubi->ubi_num, vol_id, UBI_EXCLUSIVE); if (IS_ERR(desc)) { err = PTR_ERR(desc); break; } mutex_lock(&ubi->volumes_mutex); err = ubi_remove_volume(desc); mutex_unlock(&ubi->volumes_mutex); /* * The volume is deleted (unless an error occurred), and the * 'struct ubi_volume' object will be freed when * 'ubi_close_volume()' will call 'put_device()'. */ ubi_close_volume(desc); break; } /* Re-size volume command */ case UBI_IOCRSVOL: { int pebs; uint64_t tmp; struct ubi_rsvol_req req; dbg_msg("re-size volume"); err = copy_from_user(&req, argp, sizeof(struct ubi_rsvol_req)); if (err) { err = -EFAULT; break; } err = verify_rsvol_req(ubi, &req); if (err) break; desc = ubi_open_volume(ubi->ubi_num, req.vol_id, UBI_EXCLUSIVE); if (IS_ERR(desc)) { err = PTR_ERR(desc); break; } tmp = req.bytes; pebs = !!do_div(tmp, desc->vol->usable_leb_size); pebs += tmp; mutex_lock(&ubi->volumes_mutex); err = ubi_resize_volume(desc, pebs); mutex_unlock(&ubi->volumes_mutex); ubi_close_volume(desc); break; } default: err = -ENOTTY; break; } ubi_put_device(ubi); return err; }
int ubifs_load(char *filename, u32 addr, u32 size) { struct ubifs_info *c = ubifs_sb->s_fs_info; unsigned long inum; struct inode *inode; struct page page; int err = 0; int i; int count; char link_name[64]; struct ubifs_inode *ui; c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY); inum = ubifs_findfile(ubifs_sb, filename); if (!inum) { err = -1; goto out; } /* * Read file inode */ inode = ubifs_iget(ubifs_sb, inum); if (IS_ERR(inode)) { printf("%s: Error reading inode %ld!\n", __func__, inum); err = PTR_ERR(inode); goto out; } /* * Check for symbolic link */ ui = ubifs_inode(inode); if (((inode->i_mode & S_IFMT) == S_IFLNK) && ui->data_len) { memcpy(link_name, ui->data, ui->data_len); printf("%s is linked to %s!\n", filename, link_name); ubifs_iput(inode); /* * Now we have the "real" filename, call ubifs_load() * again (recursive call) to load this file instead */ return ubifs_load(link_name, addr, size); } /* * If no size was specified or if size bigger than filesize * set size to filesize */ if ((size == 0) || (size > inode->i_size)) size = inode->i_size; count = (size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT; printf("Loading file '%s' to addr 0x%08x with size %d (0x%08x)...\n", filename, addr, size, size); page.addr = (void *)addr; page.index = 0; page.inode = inode; for (i = 0; i < count; i++) { err = do_readpage(c, inode, &page); if (err) break; page.addr += PAGE_SIZE; page.index++; } if (err) printf("Error reading file '%s'\n", filename); else printf("Done\n"); ubifs_iput(inode); out: ubi_close_volume(c->ubi); return err; }
static int ubifs_fill_super(struct super_block *sb, void *data, int silent) { struct ubi_volume_desc *ubi = sb->s_fs_info; struct ubifs_info *c; struct inode *root; int err; c = kzalloc(sizeof(struct ubifs_info), GFP_KERNEL); if (!c) return -ENOMEM; spin_lock_init(&c->cnt_lock); spin_lock_init(&c->cs_lock); spin_lock_init(&c->buds_lock); spin_lock_init(&c->space_lock); spin_lock_init(&c->orphan_lock); init_rwsem(&c->commit_sem); mutex_init(&c->lp_mutex); mutex_init(&c->tnc_mutex); mutex_init(&c->log_mutex); mutex_init(&c->mst_mutex); mutex_init(&c->umount_mutex); init_waitqueue_head(&c->cmt_wq); c->buds = RB_ROOT; c->old_idx = RB_ROOT; c->size_tree = RB_ROOT; c->orph_tree = RB_ROOT; INIT_LIST_HEAD(&c->infos_list); INIT_LIST_HEAD(&c->idx_gc); INIT_LIST_HEAD(&c->replay_list); INIT_LIST_HEAD(&c->replay_buds); INIT_LIST_HEAD(&c->uncat_list); INIT_LIST_HEAD(&c->empty_list); INIT_LIST_HEAD(&c->freeable_list); INIT_LIST_HEAD(&c->frdi_idx_list); INIT_LIST_HEAD(&c->unclean_leb_list); INIT_LIST_HEAD(&c->old_buds); INIT_LIST_HEAD(&c->orph_list); INIT_LIST_HEAD(&c->orph_new); c->highest_inum = UBIFS_FIRST_INO; c->lhead_lnum = c->ltail_lnum = UBIFS_LOG_LNUM; ubi_get_volume_info(ubi, &c->vi); ubi_get_device_info(c->vi.ubi_num, &c->di); /* Re-open the UBI device in read-write mode */ c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY); if (IS_ERR(c->ubi)) { err = PTR_ERR(c->ubi); goto out_free; } c->vfs_sb = sb; sb->s_fs_info = c; sb->s_magic = UBIFS_SUPER_MAGIC; sb->s_blocksize = UBIFS_BLOCK_SIZE; sb->s_blocksize_bits = UBIFS_BLOCK_SHIFT; sb->s_dev = c->vi.cdev; sb->s_maxbytes = c->max_inode_sz = key_max_inode_size(c); if (c->max_inode_sz > MAX_LFS_FILESIZE) sb->s_maxbytes = c->max_inode_sz = MAX_LFS_FILESIZE; if (c->rw_incompat) { ubifs_err("the file-system is not R/W-compatible"); ubifs_msg("on-flash format version is w%d/r%d, but software " "only supports up to version w%d/r%d", c->fmt_version, c->ro_compat_version, UBIFS_FORMAT_VERSION, UBIFS_RO_COMPAT_VERSION); return -EROFS; } mutex_lock(&c->umount_mutex); err = mount_ubifs(c); if (err) { ubifs_assert(err < 0); goto out_unlock; } /* Read the root inode */ root = ubifs_iget(sb, UBIFS_ROOT_INO); if (IS_ERR(root)) { err = PTR_ERR(root); goto out_umount; } sb->s_root = NULL; mutex_unlock(&c->umount_mutex); return 0; out_umount: ubifs_umount(c); out_unlock: mutex_unlock(&c->umount_mutex); ubi_close_volume(c->ubi); out_free: kfree(c); return err; }
int ubifs_part_load(char *filename, u32 addr, u32 offset, u32 size) { struct ubifs_info *c = ubifs_sb->s_fs_info; unsigned long inum=0; struct inode *inode=NULL; struct page page; int err = 0; int i=0; int count=0; int last_block_size = 0; char link_name[64]; struct ubifs_inode *ui=NULL; if(offset % PAGE_SIZE != 0) { printf("%s: offset(0x%x) should align to page size(0x%x), at %d\n", __func__, offset, PAGE_SIZE, __LINE__); return 1; } c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY); if (IS_ERR(c->ubi)) { err = PTR_ERR(c->ubi); goto out_no_close; } inum = ubifs_findfile(ubifs_sb, filename); if (!inum) { err = -1; goto out; } /* * Read file inode */ inode = ubifs_iget(ubifs_sb, inum); if (IS_ERR(inode)) { printf("%s: Error reading inode %ld!\n", __func__, inum); err = PTR_ERR(inode); goto out; } /* * Check for symbolic link */ ui = ubifs_inode(inode); if (((inode->i_mode & S_IFMT) == S_IFLNK) && ui->data_len) { memcpy(link_name, ui->data, ui->data_len); link_name[ui->data_len] = '\0'; printf("%s is linked to %s!\n", filename, link_name); ubifs_iput(inode); /* * Now we have the "real" filename, call ubifs_load() * again (recursive call) to load this file instead */ return ubifs_part_load(link_name, addr, offset, size); } /* * If no size was specified or if size bigger than filesize * set size to filesize */ if ((size == 0) || (size > inode->i_size)) size = inode->i_size; count = (size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT; printf("Loading file '%s' to addr 0x%08x with size %d (0x%08x)...\n", filename, addr, size, size); page.addr = (void *)addr; page.index = (offset / PAGE_SIZE); page.inode = inode; //offset for (i = 0; i < count; i++) { /* * Make sure to not read beyond the requested size */ if (((i + 1) == count) && (size < inode->i_size)) last_block_size = size - (i * PAGE_SIZE); err = do_readpage(c, inode, &page, last_block_size); if (err) break; page.addr += PAGE_SIZE; page.index++; } if (err) printf("Error reading file '%s'\n", filename); else printf("Done\n"); ubifs_iput(inode); out: ubi_close_volume(c->ubi); out_no_close: return err; }
static int ubifs_get_sb(struct file_system_type *fs_type, int flags, const char *name, void *data, struct vfsmount *mnt) { struct ubi_volume_desc *ubi; struct ubi_volume_info vi; struct super_block *sb; int err; dbg_gen("name %s, flags %#x", name, flags); /* * Get UBI device number and volume ID. Mount it read-only so far * because this might be a new mount point, and UBI allows only one * read-write user at a time. */ ubi = open_ubi(name, UBI_READONLY); if (IS_ERR(ubi)) { ubifs_err("cannot open \"%s\", error %d", name, (int)PTR_ERR(ubi)); return PTR_ERR(ubi); } ubi_get_volume_info(ubi, &vi); dbg_gen("opened ubi%d_%d", vi.ubi_num, vi.vol_id); sb = sget(fs_type, &sb_test, &sb_set, &vi.cdev); if (IS_ERR(sb)) { err = PTR_ERR(sb); goto out_close; } if (sb->s_root) { /* A new mount point for already mounted UBIFS */ dbg_gen("this ubi volume is already mounted"); if ((flags ^ sb->s_flags) & MS_RDONLY) { err = -EBUSY; goto out_deact; } } else { sb->s_flags = flags; /* * Pass 'ubi' to 'fill_super()' in sb->s_fs_info where it is * replaced by 'c'. */ sb->s_fs_info = ubi; err = ubifs_fill_super(sb, data, flags & MS_SILENT ? 1 : 0); if (err) goto out_deact; /* We do not support atime */ sb->s_flags |= MS_ACTIVE | MS_NOATIME; } /* 'fill_super()' opens ubi again so we must close it here */ ubi_close_volume(ubi); ubifs_sb = sb; return 0; out_deact: up_write(&sb->s_umount); out_close: ubi_close_volume(ubi); return err; }
/** * ubi_open_volume - open UBI volume. * @ubi_num: UBI device number * @vol_id: volume ID * @mode: open mode * * The @mode parameter specifies if the volume should be opened in read-only * mode, read-write mode, or exclusive mode. The exclusive mode guarantees that * nobody else will be able to open this volume. UBI allows to have many volume * readers and one writer at a time. * * If a static volume is being opened for the first time since boot, it will be * checked by this function, which means it will be fully read and the CRC * checksum of each logical eraseblock will be checked. * * This function returns volume descriptor in case of success and a negative * error code in case of failure. */ struct ubi_volume_desc *ubi_open_volume(int ubi_num, int vol_id, int mode) { int err; struct ubi_volume_desc *desc; struct ubi_device *ubi = ubi_devices[ubi_num]; struct ubi_volume *vol; dbg_msg("open device %d volume %d, mode %d", ubi_num, vol_id, mode); err = -ENODEV; if (!try_module_get(THIS_MODULE)) return ERR_PTR(err); if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES || !ubi) goto out_put; err = -EINVAL; if (vol_id < 0 || vol_id >= ubi->vtbl_slots) goto out_put; if (mode != UBI_READONLY && mode != UBI_READWRITE && mode != UBI_EXCLUSIVE) goto out_put; desc = kmalloc(sizeof(struct ubi_volume_desc), GFP_KERNEL); if (!desc) { err = -ENOMEM; goto out_put; } spin_lock(&ubi->volumes_lock); vol = ubi->volumes[vol_id]; if (!vol) { err = -ENODEV; goto out_unlock; } err = -EBUSY; switch (mode) { case UBI_READONLY: if (vol->exclusive) goto out_unlock; vol->readers += 1; break; case UBI_READWRITE: if (vol->exclusive || vol->writers > 0) goto out_unlock; vol->writers += 1; break; case UBI_EXCLUSIVE: if (vol->exclusive || vol->writers || vol->readers) goto out_unlock; vol->exclusive = 1; break; } spin_unlock(&ubi->volumes_lock); desc->vol = vol; desc->mode = mode; /* * To prevent simultaneous checks of the same volume we use @vtbl_mutex, * although it is not the purpose it was introduced for. */ mutex_lock(&ubi->vtbl_mutex); if (!vol->checked) { /* This is the first open - check the volume */ err = ubi_check_volume(ubi, vol_id); if (err < 0) { mutex_unlock(&ubi->vtbl_mutex); ubi_close_volume(desc); return ERR_PTR(err); } if (err == 1) { ubi_warn("volume %d on UBI device %d is corrupted", vol_id, ubi->ubi_num); vol->corrupted = 1; } vol->checked = 1; } mutex_unlock(&ubi->vtbl_mutex); return desc; out_unlock: spin_unlock(&ubi->volumes_lock); kfree(desc); out_put: module_put(THIS_MODULE); return ERR_PTR(err); }