Esempio n. 1
0
/**
 * open_ubi - parse UBI device name string and open the UBI device.
 * @name: UBI volume name
 * @mode: UBI volume open mode
 *
 * There are several ways to specify UBI volumes when mounting UBIFS:
 * o ubiX_Y    - UBI device number X, volume Y;
 * o ubiY      - UBI device number 0, volume Y;
 * o ubiX:NAME - mount UBI device X, volume with name NAME;
 * o ubi:NAME  - mount UBI device 0, volume with name NAME.
 *
 * Alternative '!' separator may be used instead of ':' (because some shells
 * like busybox may interpret ':' as an NFS host name separator). This function
 * returns ubi volume object in case of success and a negative error code in
 * case of failure.
 */
static struct ubi_volume_desc *open_ubi(const char *name, int mode)
{
	int dev, vol;
	char *endptr;

	if (name[0] != 'u' || name[1] != 'b' || name[2] != 'i')
		return ERR_PTR(-EINVAL);

	/* ubi:NAME method */
	if ((name[3] == ':' || name[3] == '!') && name[4] != '\0')
		return ubi_open_volume_nm(0, name + 4, mode);

	if (!isdigit(name[3]))
		return ERR_PTR(-EINVAL);

	dev = simple_strtoul(name + 3, &endptr, 0);

	/* ubiY method */
	if (*endptr == '\0')
		return ubi_open_volume(0, dev, mode);

	/* ubiX_Y method */
	if (*endptr == '_' && isdigit(endptr[1])) {
		vol = simple_strtoul(endptr + 1, &endptr, 0);
		if (*endptr != '\0')
			return ERR_PTR(-EINVAL);
		return ubi_open_volume(dev, vol, mode);
	}

	/* ubiX:NAME method */
	if ((*endptr == ':' || *endptr == '!') && endptr[1] != '\0')
		return ubi_open_volume_nm(dev, ++endptr, mode);

	return ERR_PTR(-EINVAL);
}
Esempio n. 2
0
/**
 * ubi_open_volume_path - open UBI volume by its character device node path.
 * @pathname: volume character device node path
 * @mode: open mode
 *
 * This function is similar to 'ubi_open_volume()', but opens a volume the path
 * to its character device node.
 */
struct ubi_volume_desc *ubi_open_volume_path(const char *pathname, int mode)
{
	int error, ubi_num, vol_id, mod;
	struct inode *inode;
	struct path path;

	dbg_gen("open volume %s, mode %d", pathname, mode);

	if (!pathname || !*pathname)
		return ERR_PTR(-EINVAL);

	error = kern_path(pathname, LOOKUP_FOLLOW, &path);
	if (error)
		return ERR_PTR(error);

	inode = path.dentry->d_inode;
	mod = inode->i_mode;
	ubi_num = ubi_major2num(imajor(inode));
	vol_id = iminor(inode) - 1;
	path_put(&path);

	if (!S_ISCHR(mod))
		return ERR_PTR(-EINVAL);
	if (vol_id >= 0 && ubi_num >= 0)
		return ubi_open_volume(ubi_num, vol_id, mode);
	return ERR_PTR(-ENODEV);
}
Esempio n. 3
0
/**
 * gluebi_get_device - get MTD device reference.
 * @mtd: the MTD device description object
 *
 * This function is called every time the MTD device is being opened and
 * implements the MTD get_device() operation. Returns zero in case of success
 * and a negative error code in case of failure.
 */
static int gluebi_get_device(struct mtd_info *mtd)
{
	struct ubi_volume *vol;

	vol = container_of(mtd, struct ubi_volume, gluebi_mtd);

	/*
	 * We do not introduce locks for gluebi reference count because the
	 * get_device()/put_device() calls are already serialized at MTD.
	 */
	if (vol->gluebi_refcount > 0) {
		/*
		 * The MTD device is already referenced and this is just one
		 * more reference. MTD allows many users to open the same
		 * volume simultaneously and do not distinguish between
		 * readers/writers/exclusive openers as UBI does. So we do not
		 * open the UBI volume again - just increase the reference
		 * counter and return.
		 */
		vol->gluebi_refcount += 1;
		return 0;
	}

	/*
	 * This is the first reference to this UBI volume via the MTD device
	 * interface. Open the corresponding volume in read-write mode.
	 */
	vol->gluebi_desc = ubi_open_volume(vol->ubi->ubi_num, vol->vol_id,
					   UBI_READWRITE);
	if (IS_ERR(vol->gluebi_desc))
		return PTR_ERR(vol->gluebi_desc);
	vol->gluebi_refcount += 1;
	return 0;
}
Esempio n. 4
0
static int vol_cdev_open(struct inode *inode, struct file *file)
{
	struct ubi_volume_desc *desc;
	int vol_id = iminor(inode) - 1, mode, ubi_num;

	lock_kernel();
	ubi_num = ubi_major2num(imajor(inode));
	if (ubi_num < 0) {
		unlock_kernel();
		return ubi_num;
	}

	if (file->f_mode & FMODE_WRITE)
		mode = UBI_READWRITE;
	else
		mode = UBI_READONLY;

	dbg_msg("open volume %d, mode %d", vol_id, mode);

	desc = ubi_open_volume(ubi_num, vol_id, mode);
	unlock_kernel();
	if (IS_ERR(desc))
		return PTR_ERR(desc);

	file->private_data = desc;
	return 0;
}
Esempio n. 5
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;
}
Esempio n. 6
0
File: kapi.c Progetto: Lyude/linux
/**
 * ubi_open_volume_path - open UBI volume by its character device node path.
 * @pathname: volume character device node path
 * @mode: open mode
 *
 * This function is similar to 'ubi_open_volume()', but opens a volume the path
 * to its character device node.
 */
struct ubi_volume_desc *ubi_open_volume_path(const char *pathname, int mode)
{
	int error, ubi_num, vol_id;
	struct path path;
	struct kstat stat;

	dbg_gen("open volume %s, mode %d", pathname, mode);

	if (!pathname || !*pathname)
		return ERR_PTR(-EINVAL);

	error = kern_path(pathname, LOOKUP_FOLLOW, &path);
	if (error)
		return ERR_PTR(error);

	error = vfs_getattr(&path, &stat, STATX_TYPE, AT_STATX_SYNC_AS_STAT);
	path_put(&path);
	if (error)
		return ERR_PTR(error);

	if (!S_ISCHR(stat.mode))
		return ERR_PTR(-EINVAL);

	ubi_num = ubi_major2num(MAJOR(stat.rdev));
	vol_id = MINOR(stat.rdev) - 1;

	if (vol_id >= 0 && ubi_num >= 0)
		return ubi_open_volume(ubi_num, vol_id, mode);
	return ERR_PTR(-ENODEV);
}
Esempio n. 7
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;
}
Esempio n. 8
0
/**
 * ubi_open_volume_nm - open UBI volume by name.
 * @ubi_num: UBI device number
 * @name: volume name
 * @mode: open mode
 *
 * This function is similar to 'ubi_open_volume()', but opens a volume by name.
 */
struct ubi_volume_desc *ubi_open_volume_nm(int ubi_num, const char *name,
					   int mode)
{
	int i, vol_id = -1, len;
	struct ubi_device *ubi;
	struct ubi_volume_desc *ret;

	dbg_gen("open device %d, volume %s, mode %d", ubi_num, name, mode);

	if (!name)
		return ERR_PTR(-EINVAL);

	len = strnlen(name, UBI_VOL_NAME_MAX + 1);
	if (len > UBI_VOL_NAME_MAX)
		return ERR_PTR(-EINVAL);

	if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES)
		return ERR_PTR(-EINVAL);

	ubi = ubi_get_device(ubi_num);
	if (!ubi)
		return ERR_PTR(-ENODEV);

	spin_lock(&ubi->volumes_lock);
	/* Walk all volumes of this UBI device */
	for (i = 0; i < ubi->vtbl_slots; i++) {
		struct ubi_volume *vol = ubi->volumes[i];

		if (vol && len == vol->name_len && !strcmp(name, vol->name)) {
			vol_id = i;
			break;
		}
	}
	spin_unlock(&ubi->volumes_lock);

	if (vol_id >= 0)
		ret = ubi_open_volume(ubi_num, vol_id, mode);
	else
		ret = ERR_PTR(-ENODEV);

	/*
	 * We should put the UBI device even in case of success, because
	 * 'ubi_open_volume()' took a reference as well.
	 */
	ubi_put_device(ubi);
	return ret;
}
Esempio n. 9
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;
}
Esempio n. 10
0
File: kapi.c Progetto: cilynx/dd-wrt
/**
 * ubi_open_volume_nm - open UBI volume by name.
 * @ubi_num: UBI device number
 * @name: volume name
 * @mode: open mode
 *
 * This function is similar to 'ubi_open_volume()', but opens a volume by name.
 */
struct ubi_volume_desc *ubi_open_volume_nm(int ubi_num, const char *name,
					   int mode)
{
	int i, vol_id = -1, len;
	struct ubi_volume_desc *ret;
	struct ubi_device *ubi;

	dbg_msg("open volume %s, mode %d", name, mode);

	if (!name)
		return ERR_PTR(-EINVAL);

	len = strnlen(name, UBI_VOL_NAME_MAX + 1);
	if (len > UBI_VOL_NAME_MAX)
		return ERR_PTR(-EINVAL);

	ret = ERR_PTR(-ENODEV);
	if (!try_module_get(THIS_MODULE))
		return ret;

	if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES || !ubi_devices[ubi_num])
		goto out_put;

	ubi = ubi_devices[ubi_num];

	spin_lock(&ubi->volumes_lock);
	/* Walk all volumes of this UBI device */
	for (i = 0; i < ubi->vtbl_slots; i++) {
		struct ubi_volume *vol = ubi->volumes[i];

		if (vol && len == vol->name_len && !strcmp(name, vol->name)) {
			vol_id = i;
			break;
		}
	}
	spin_unlock(&ubi->volumes_lock);

	if (vol_id < 0)
		goto out_put;

	ret = ubi_open_volume(ubi_num, vol_id, mode);

out_put:
	module_put(THIS_MODULE);
	return ret;
}
Esempio n. 11
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;

}
Esempio n. 12
0
static int vol_cdev_open(struct inode *inode, struct file *file)
{
	struct ubi_volume_desc *desc;
	const struct ubi_device *ubi = major_to_device(imajor(inode));
	int vol_id = iminor(inode) - 1;
	int mode;

	if (file->f_mode & FMODE_WRITE)
		mode = UBI_READWRITE;
	else
		mode = UBI_READONLY;

	dbg_msg("open volume %d, mode %d", vol_id, mode);

	desc = ubi_open_volume(ubi->ubi_num, vol_id, mode);
	if (IS_ERR(desc))
		return PTR_ERR(desc);

	file->private_data = desc;
	return 0;
}
Esempio n. 13
0
/**
 * ubi_open_volume_path - open UBI volume by its character device node path.
 * @pathname: volume character device node path
 * @mode: open mode
 *
 * This function is similar to 'ubi_open_volume()', but opens a volume the path
 * to its character device node.
 */
struct ubi_volume_desc *ubi_open_volume_path(const char *pathname, int mode)
{
	int error, ubi_num, vol_id;
	struct kstat stat;

	dbg_gen("open volume %s, mode %d", pathname, mode);

	if (!pathname || !*pathname)
		return ERR_PTR(-EINVAL);

	error = vfs_stat(pathname, &stat);
	if (error)
		return ERR_PTR(error);

	if (!S_ISCHR(stat.mode))
		return ERR_PTR(-EINVAL);

	ubi_num = ubi_major2num(MAJOR(stat.rdev));
	vol_id = MINOR(stat.rdev) - 1;

	if (vol_id >= 0 && ubi_num >= 0)
		return ubi_open_volume(ubi_num, vol_id, mode);
	return ERR_PTR(-ENODEV);
}
Esempio n. 14
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;
}
Esempio n. 15
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;
}
Esempio n. 16
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;
}
Esempio n. 17
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;
}
Esempio n. 18
0
/*
 * Set up our internal device.
 */
static void setup_device(struct ubiblk_dev *dev, int which)
{
	memset (dev, 0, sizeof (struct ubiblk_dev));

	spin_lock_init(&dev->lock);

	/* get each ubi device that we're working with.  Each mtd device claimed
	 * by the ubi layer is a device.  Note that this can be a chip or a
	 * partition.
	 */
	if(ubi_get_device_info(which, &dev->ubi_dev)) {
		printk("ubiblk: Failed to get device info for ubi%d\n", which);
		goto out_vfree;
	}

	/* each ubi device is either empty, corrupted, or contains some number
	 * of volumes.  For now, I'm assuming that there's exactly one volume,
	 * and it's volume id is 0.  This is a bit inapproriate, because ubi
	 * volumes are supposed to be like partitions.  The proper solution
	 * would be to allow the ubi userspace tools to create partitions much
	 * like fdisk would.
	 */

	dev->ubi_vol = ubi_open_volume(which, 0, UBI_READWRITE);
	if(IS_ERR(dev->ubi_vol)) {
		printk("Failed to open ubi volume 0 on device %d\n", which);
		dev->ubi_vol = 0;
		goto out_vfree;
	}

	dev->hardsect_size = dev->ubi_dev.min_io_size;
	dev->size = nsectors*dev->hardsect_size;

	/* setup blk dev queuing */
	dev->queue = blk_init_queue(ubiblk_request, &dev->lock);
	if (dev->queue == NULL)
		goto out_vfree;

	blk_queue_hardsect_size(dev->queue, dev->hardsect_size);
	dev->queue->queuedata = dev;

	/* setup gendisk structure */
	dev->gd = alloc_disk(UBIBLK_MINORS);
	if (! dev->gd) {
		printk (KERN_NOTICE "alloc_disk failure\n");
		goto out_vfree;
	}
	dev->gd->major = ubiblk_major;
	dev->gd->first_minor = which*UBIBLK_MINORS;
	dev->gd->fops = &ubiblk_ops;
	dev->gd->queue = dev->queue;
	dev->gd->private_data = dev;
	snprintf (dev->gd->disk_name, 32, "ubiblk%c", which + 'a');
	set_capacity(dev->gd, nsectors*(dev->hardsect_size/KERNEL_SECTOR_SIZE));
	add_disk(dev->gd);
	return;

  out_vfree:
	if (dev->queue)
		blk_cleanup_queue(dev->queue);
}
Esempio n. 19
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;
}
Esempio n. 20
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;
}
Esempio n. 21
0
/**
 * ubi_open_volume_nm - open UBI volume by name.
 * @ubi_num: UBI device number
 * @name: volume name
 * @mode: open mode
 *
 * This function is similar to 'ubi_open_volume()', but opens a volume by name.
 */
struct ubi_volume_desc *ubi_open_volume_nm(int ubi_num, const char *name,
					   int mode)
{
	int i, vol_id = -1, len;
	struct ubi_device *ubi;
	struct ubi_volume_desc *ret;
	int k;

	dbg_msg("open volume %s, mode %d", name, mode);

	if (!name)
		return ERR_PTR(-EINVAL);

	len = strnlen(name, UBI_VOL_NAME_MAX + 1);

	if (len > UBI_VOL_NAME_MAX)
		return ERR_PTR(-EINVAL);

	if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES)
		return ERR_PTR(-EINVAL);

	ubi = ubi_get_device(ubi_num);
	if (!ubi)
		return ERR_PTR(-ENODEV);

	for( k=0; k<(UBI_MAX_VOLUMES+UBI_INT_VOL_COUNT); k++)
	{
		if (ubi->volumes[i]) {
			printf("ubi volume name = %s\n", ubi->volumes[i]->name);
		}
	}

	
	spin_lock(&ubi->volumes_lock);
	/* Walk all volumes of this UBI device */
	for (i = 0; i < (ubi->vtbl_slots+UBI_INT_VOL_COUNT); i++) {
		struct ubi_volume *vol = ubi->volumes[i];

		if (vol) {
//		   printf("ubi_open_volume_nm found i=%d\n", i);
//		   printf("ubi_open_volume_nm found volume vol->name=%s\n", vol->name);
//		   printf("ubi_open_volume_nm found volume name=%s\n", name);
//		   printf("ubi_open_volume_nm found len=%d\n", len);
//		   printf("ubi_open_volume_nm found vol->name_len=%d\n", vol->name_len);
		   k = strcmp(name, vol->name);
		   if (0==k) {
			   vol_id=i;
//			   printf("ubi_open_volume_nm found strings are compared\n");
		   }
		   break;
		}
	}
	spin_unlock(&ubi->volumes_lock);

	if (vol_id >= 0)
		ret = ubi_open_volume(ubi_num, vol_id, mode);
	else
		ret = ERR_PTR(-ENODEV);

//	printf("ubi_open_volume_nm  volume =%d!\n", i);


	/*
	 * We should put the UBI device even in case of success, because
	 * 'ubi_open_volume()' took a reference as well.
	 */
	ubi_put_device(ubi);
	return ret;
}
Esempio n. 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;
}