Пример #1
0
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;
}
Пример #2
0
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;
}
Пример #3
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);
}
Пример #4
0
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;
}
Пример #5
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);
}
Пример #6
0
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;
};
Пример #7
0
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;
}
Пример #8
0
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;
}
Пример #9
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;

}
Пример #10
0
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);
}
Пример #11
0
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;
}
Пример #12
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;
}
Пример #13
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;
}
Пример #14
0
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;
}
Пример #15
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);
}
Пример #16
0
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;
}
Пример #17
0
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;
}
Пример #18
0
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;
}
Пример #19
0
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;
}
Пример #20
0
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;
}
Пример #21
0
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;
}
Пример #22
0
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;
}
Пример #23
0
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;
}
Пример #24
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 = 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);
}