diff options
author | Philipp Zabel <p.zabel@pengutronix.de> | 2017-06-01 12:37:29 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2017-06-06 09:16:23 +0200 |
commit | f3cd5b1bbcb27108496eb572ae2ff7cd526ddc55 (patch) | |
tree | 4a0e5586df03dd50f6190525c5cb71db34128113 /fs/devfs-core.c | |
parent | 7bcbc91a5eb2c3fbb3a6d67103ca0ff8fc8e4412 (diff) | |
download | barebox-f3cd5b1bbcb27108496eb572ae2ff7cd526ddc55.tar.gz barebox-f3cd5b1bbcb27108496eb572ae2ff7cd526ddc55.tar.xz |
fs: add cdev_create_loop and cdev_remove_loop for loop mount option
Allow to create a loopback cdev from a file.
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Fixed up with:
fs: Makefile: Add parseopt to all builds
parseopt.h was included to fs.c with commit 9248b, but parseopt.o has a
dependency to CONFIG_FS_NFS.
Moved parseopt.o to the default build to eliminate build failures.
Signed-off-by: Daniel Schultz <d.schultz@phytec.de>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'fs/devfs-core.c')
-rw-r--r-- | fs/devfs-core.c | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/fs/devfs-core.c b/fs/devfs-core.c index 26fffbb6c2..3368d3ed68 100644 --- a/fs/devfs-core.c +++ b/fs/devfs-core.c @@ -20,11 +20,14 @@ #include <complete.h> #include <driver.h> #include <errno.h> +#include <fcntl.h> #include <malloc.h> #include <ioctl.h> #include <nand.h> #include <linux/err.h> +#include <linux/fs.h> #include <linux/mtd/mtd.h> +#include <unistd.h> LIST_HEAD(cdev_list); @@ -409,3 +412,90 @@ int devfs_create_partitions(const char *devname, return 0; } + +struct loop_priv { + int fd; +}; + +static ssize_t loop_read(struct cdev *cdev, void *buf, size_t count, + loff_t offset, ulong flags) +{ + struct loop_priv *priv = cdev->priv; + loff_t ofs; + + ofs = lseek(priv->fd, offset, SEEK_SET); + if (ofs < 0) + return ofs; + + return read(priv->fd, buf, count); +} + +static ssize_t loop_write(struct cdev *cdev, const void *buf, size_t count, + loff_t offset, ulong flags) +{ + struct loop_priv *priv = cdev->priv; + loff_t ofs; + + ofs = lseek(priv->fd, offset, SEEK_SET); + if (ofs < 0) + return ofs; + + return write(priv->fd, buf, count); +} + +static const struct file_operations loop_ops = { + .read = loop_read, + .write = loop_write, + .memmap = generic_memmap_rw, + .lseek = dev_lseek_default, +}; + +struct cdev *cdev_create_loop(const char *path, ulong flags) +{ + struct cdev *new; + struct loop_priv *priv; + static int loopno; + loff_t ofs; + + priv = xzalloc(sizeof(*priv)); + + priv->fd = open(path, flags); + if (priv->fd < 0) { + free(priv); + return NULL; + } + + new = xzalloc(sizeof(*new)); + + new->ops = &loop_ops; + new->name = basprintf("loop%u", loopno++); + new->priv = priv; + + ofs = lseek(priv->fd, 0, SEEK_END); + if (ofs < 0) { + free(new); + free(priv); + return NULL; + } + lseek(priv->fd, 0, SEEK_SET); + + new->size = ofs; + new->offset = 0; + new->dev = NULL; + new->flags = 0; + + devfs_create(new); + + return new; +} + +void cdev_remove_loop(struct cdev *cdev) +{ + struct loop_priv *priv = cdev->priv; + + devfs_remove(cdev); + close(priv->fd); + free(priv); + free(cdev->name); + free(cdev); +} |