mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH v2] Symlink support for devfs
@ 2015-12-16  9:47 Sascha Hauer
  2015-12-16  9:47 ` [PATCH 1/2] devfs: Add symlink support Sascha Hauer
  2015-12-16  9:47 ` [PATCH 2/2] partition: Create links with partition names Sascha Hauer
  0 siblings, 2 replies; 4+ messages in thread
From: Sascha Hauer @ 2015-12-16  9:47 UTC (permalink / raw)
  To: Barebox List

This adds symlink support for devfs and uses it to create named
partition aliases.

Changes since v1:

- Put links to a cdev onto a list on that cdev to be able to show them
  in devinfo output

----------------------------------------------------------------
Sascha Hauer (2):
      devfs: Add symlink support
      partition: Create links with partition names

 commands/devinfo.c  |  7 +++--
 common/partitions.c | 20 +++++---------
 fs/devfs-core.c     | 76 ++++++++++++++++++++++++++++++++++++++++++++---------
 fs/devfs.c          | 27 ++++++++++++++++++-
 include/driver.h    |  5 ++++
 5 files changed, 106 insertions(+), 29 deletions(-)

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/2] devfs: Add symlink support
  2015-12-16  9:47 [PATCH v2] Symlink support for devfs Sascha Hauer
@ 2015-12-16  9:47 ` Sascha Hauer
  2015-12-16  9:47 ` [PATCH 2/2] partition: Create links with partition names Sascha Hauer
  1 sibling, 0 replies; 4+ messages in thread
From: Sascha Hauer @ 2015-12-16  9:47 UTC (permalink / raw)
  To: Barebox List

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 commands/devinfo.c |  7 +++--
 fs/devfs-core.c    | 76 ++++++++++++++++++++++++++++++++++++++++++++----------
 fs/devfs.c         | 27 ++++++++++++++++++-
 include/driver.h   |  5 ++++
 4 files changed, 99 insertions(+), 16 deletions(-)

diff --git a/commands/devinfo.c b/commands/devinfo.c
index 3c9d6a6..c78efcb 100644
--- a/commands/devinfo.c
+++ b/commands/devinfo.c
@@ -21,7 +21,7 @@
 static int do_devinfo_subtree(struct device_d *dev, int depth)
 {
 	struct device_d *child;
-	struct cdev *cdev;
+	struct cdev *cdev, *cdevl;
 	int i;
 
 	for (i = 0; i < depth; i++)
@@ -33,11 +33,14 @@ static int do_devinfo_subtree(struct device_d *dev, int depth)
 		list_for_each_entry(cdev, &dev->cdevs, devices_list) {
 			for (i = 0; i < depth + 1; i++)
 				printf("   ");
-			printf("`-- 0x%08llx-0x%08llx (%10s): /dev/%s\n",
+			printf("`-- 0x%08llx-0x%08llx (%10s): /dev/%s",
 					cdev->offset,
 					cdev->offset + cdev->size - 1,
 					size_human_readable(cdev->size),
 					cdev->name);
+			list_for_each_entry(cdevl, &cdev->links, link_entry)
+				printf(", %s", cdevl->name);
+			printf("\n");
 		}
 	} else {
 		printf("\n");
diff --git a/fs/devfs-core.c b/fs/devfs-core.c
index 2541ea3..640a134 100644
--- a/fs/devfs-core.c
+++ b/fs/devfs-core.c
@@ -46,7 +46,18 @@ int devfs_partition_complete(struct string_list *sl, char *instr)
 }
 #endif
 
-struct cdev *cdev_by_name(const char *filename)
+struct cdev *cdev_readlink(struct cdev *cdev)
+{
+	if (cdev->link)
+		cdev = cdev->link;
+
+	/* links to links are not allowed */
+	BUG_ON(cdev->link);
+
+	return cdev;
+}
+
+struct cdev *lcdev_by_name(const char *filename)
 {
 	struct cdev *cdev;
 
@@ -57,6 +68,17 @@ struct cdev *cdev_by_name(const char *filename)
 	return NULL;
 }
 
+struct cdev *cdev_by_name(const char *filename)
+{
+	struct cdev *cdev;
+
+	cdev = lcdev_by_name(filename);
+	if (!cdev)
+		return NULL;
+
+	return cdev_readlink(cdev);
+}
+
 struct cdev *cdev_by_device_node(struct device_node *node)
 {
 	struct cdev *cdev;
@@ -65,7 +87,7 @@ struct cdev *cdev_by_device_node(struct device_node *node)
 		if (!cdev->device_node)
 			continue;
 		if (cdev->device_node == node)
-			return cdev;
+			return cdev_readlink(cdev);
 	}
 	return NULL;
 }
@@ -111,14 +133,6 @@ int cdev_find_free_index(const char *basename)
 	return -EBUSY;	/* all indexes are used */
 }
 
-int cdev_do_open(struct cdev *cdev, unsigned long flags)
-{
-	if (cdev->ops->open)
-		return cdev->ops->open(cdev, flags);
-
-	return 0;
-}
-
 struct cdev *cdev_open(const char *name, unsigned long flags)
 {
 	struct cdev *cdev;
@@ -131,9 +145,11 @@ struct cdev *cdev_open(const char *name, unsigned long flags)
 	if (!cdev)
 		return NULL;
 
-	ret = cdev_do_open(cdev, flags);
-	if (ret)
-		return NULL;
+	if (cdev->ops->open) {
+		ret = cdev->ops->open(cdev, flags);
+		if (ret)
+			return NULL;
+	}
 
 	return cdev;
 }
@@ -259,6 +275,8 @@ int devfs_create(struct cdev *new)
 	if (cdev)
 		return -EEXIST;
 
+	INIT_LIST_HEAD(&new->links);
+
 	list_add_tail(&new->list, &cdev_list);
 	if (new->dev)
 		list_add_tail(&new->devices_list, &new->dev->cdevs);
@@ -266,15 +284,47 @@ int devfs_create(struct cdev *new)
 	return 0;
 }
 
+int devfs_create_link(struct cdev *cdev, const char *name)
+{
+	struct cdev *new;
+
+	if (cdev_by_name(name))
+		return -EEXIST;
+
+	/*
+	 * Create a link to the real cdev instead of creating
+	 * a link to a link.
+	 */
+	cdev = cdev_readlink(cdev);
+
+	new = xzalloc(sizeof(*new));
+	new->name = xstrdup(name);
+	new->link = cdev;
+	INIT_LIST_HEAD(&new->links);
+	list_add_tail(&new->list, &cdev_list);
+	list_add_tail(&new->link_entry, &cdev->links);
+
+	return 0;
+}
+
 int devfs_remove(struct cdev *cdev)
 {
+	struct cdev *c, *tmp;
+
 	if (cdev->open)
 		return -EBUSY;
 
 	list_del(&cdev->list);
+
 	if (cdev->dev)
 		list_del(&cdev->devices_list);
 
+	list_for_each_entry_safe(c, tmp, &cdev->links, link_entry)
+		devfs_remove(c);
+
+	if (cdev->link)
+		free(cdev);
+
 	return 0;
 }
 
diff --git a/fs/devfs.c b/fs/devfs.c
index 5c96682..0b8d4fd 100644
--- a/fs/devfs.c
+++ b/fs/devfs.c
@@ -212,12 +212,18 @@ static int devfs_stat(struct device_d *_dev, const char *filename, struct stat *
 {
 	struct cdev *cdev;
 
-	cdev = cdev_by_name(filename + 1);
+	cdev = lcdev_by_name(filename + 1);
 	if (!cdev)
 		return -ENOENT;
 
 	s->st_mode = S_IFCHR;
 	s->st_size = cdev->size;
+
+	if (cdev->link)
+		s->st_mode |= S_IFLNK;
+
+	cdev = cdev_readlink(cdev);
+
 	if (cdev->ops->write)
 		s->st_mode |= S_IWUSR;
 	if (cdev->ops->read)
@@ -242,6 +248,24 @@ static void devfs_delete(struct device_d *dev)
 {
 }
 
+static int devfs_readlink(struct device_d *dev, const char *pathname,
+			  char *buf, size_t bufsz)
+{
+	struct cdev *cdev;
+
+	cdev = cdev_by_name(pathname + 1);
+	if (!cdev)
+		return -ENOENT;
+
+	while (cdev->link)
+		cdev = cdev->link;
+
+	bufsz = min(bufsz, strlen(cdev->name));
+	memcpy(buf, cdev->name, bufsz);
+
+	return 0;
+}
+
 static struct fs_driver_d devfs_driver = {
 	.read      = devfs_read,
 	.write     = devfs_write,
@@ -258,6 +282,7 @@ static struct fs_driver_d devfs_driver = {
 	.erase     = devfs_erase,
 	.protect   = devfs_protect,
 	.memmap    = devfs_memmap,
+	.readlink  = devfs_readlink,
 	.flags     = FS_DRIVER_NO_DEV,
 	.drv = {
 		.probe  = devfs_probe,
diff --git a/include/driver.h b/include/driver.h
index 046dd90..31c6734 100644
--- a/include/driver.h
+++ b/include/driver.h
@@ -450,13 +450,18 @@ struct cdev {
 	int open;
 	struct mtd_info *mtd;
 	u8 dos_partition_type;
+	struct cdev *link;
+	struct list_head link_entry, links;
 };
 
 int devfs_create(struct cdev *);
+int devfs_create_link(struct cdev *, const char *name);
 int devfs_remove(struct cdev *);
 int cdev_find_free_index(const char *);
 struct cdev *device_find_partition(struct device_d *dev, const char *name);
 struct cdev *cdev_by_name(const char *filename);
+struct cdev *lcdev_by_name(const char *filename);
+struct cdev *cdev_readlink(struct cdev *cdev);
 struct cdev *cdev_by_device_node(struct device_node *node);
 struct cdev *cdev_open(const char *name, unsigned long flags);
 int cdev_do_open(struct cdev *, unsigned long flags);
-- 
2.6.2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 2/2] partition: Create links with partition names
  2015-12-16  9:47 [PATCH v2] Symlink support for devfs Sascha Hauer
  2015-12-16  9:47 ` [PATCH 1/2] devfs: Add symlink support Sascha Hauer
@ 2015-12-16  9:47 ` Sascha Hauer
  1 sibling, 0 replies; 4+ messages in thread
From: Sascha Hauer @ 2015-12-16  9:47 UTC (permalink / raw)
  To: Barebox List

When a partition has a name create a link to the original partition
rather than registering a second cdev.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 common/partitions.c | 20 +++++++-------------
 1 file changed, 7 insertions(+), 13 deletions(-)

diff --git a/common/partitions.c b/common/partitions.c
index 4f50bfe..82ec508 100644
--- a/common/partitions.c
+++ b/common/partitions.c
@@ -71,20 +71,14 @@ static int register_one_partition(struct block_device *blk,
 	if (!part->name[0])
 		return 0;
 
-	partition_name = asprintf("%s.%s", blk->cdev.name, part->name);
-	if (!partition_name)
-		return -ENOMEM;
-
-	dev_dbg(blk->dev, "Registering partition %s on drive %s\n",
-				partition_name, blk->cdev.name);
-	cdev = devfs_add_partition(blk->cdev.name,
-				start, size, 0, partition_name);
-
-	if (IS_ERR(cdev))
-		dev_warn(blk->dev, "Registering partition %s on drive %s failed\n",
-				partition_name, blk->cdev.name);
+	partition_name = xasprintf("%s.%s", blk->cdev.name, part->name);
+	ret = devfs_create_link(cdev, partition_name);
+	if (ret)
+		dev_warn(blk->dev, "Failed to create link from %s to %s\n",
+			 partition_name, blk->cdev.name);
+	free(partition_name);
 
-	ret = 0;
+	return 0;
 out:
 	free(partition_name);
 	return ret;
-- 
2.6.2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/2] devfs: Add symlink support
@ 2015-12-11 10:40 Sascha Hauer
  0 siblings, 0 replies; 4+ messages in thread
From: Sascha Hauer @ 2015-12-11 10:40 UTC (permalink / raw)
  To: Barebox List

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 fs/devfs-core.c  | 72 ++++++++++++++++++++++++++++++++++++++++++++++----------
 fs/devfs.c       | 27 ++++++++++++++++++++-
 include/driver.h |  4 ++++
 3 files changed, 89 insertions(+), 14 deletions(-)

diff --git a/fs/devfs-core.c b/fs/devfs-core.c
index 2541ea3..1e899a1 100644
--- a/fs/devfs-core.c
+++ b/fs/devfs-core.c
@@ -46,7 +46,18 @@ int devfs_partition_complete(struct string_list *sl, char *instr)
 }
 #endif
 
-struct cdev *cdev_by_name(const char *filename)
+struct cdev *cdev_readlink(struct cdev *cdev)
+{
+	if (cdev->link)
+		cdev = cdev->link;
+
+	/* links to links are not allowed */
+	BUG_ON(cdev->link);
+
+	return cdev;
+}
+
+struct cdev *lcdev_by_name(const char *filename)
 {
 	struct cdev *cdev;
 
@@ -57,6 +68,17 @@ struct cdev *cdev_by_name(const char *filename)
 	return NULL;
 }
 
+struct cdev *cdev_by_name(const char *filename)
+{
+	struct cdev *cdev;
+
+	cdev = lcdev_by_name(filename);
+	if (!cdev)
+		return NULL;
+
+	return cdev_readlink(cdev);
+}
+
 struct cdev *cdev_by_device_node(struct device_node *node)
 {
 	struct cdev *cdev;
@@ -65,7 +87,7 @@ struct cdev *cdev_by_device_node(struct device_node *node)
 		if (!cdev->device_node)
 			continue;
 		if (cdev->device_node == node)
-			return cdev;
+			return cdev_readlink(cdev);
 	}
 	return NULL;
 }
@@ -111,14 +133,6 @@ int cdev_find_free_index(const char *basename)
 	return -EBUSY;	/* all indexes are used */
 }
 
-int cdev_do_open(struct cdev *cdev, unsigned long flags)
-{
-	if (cdev->ops->open)
-		return cdev->ops->open(cdev, flags);
-
-	return 0;
-}
-
 struct cdev *cdev_open(const char *name, unsigned long flags)
 {
 	struct cdev *cdev;
@@ -131,9 +145,11 @@ struct cdev *cdev_open(const char *name, unsigned long flags)
 	if (!cdev)
 		return NULL;
 
-	ret = cdev_do_open(cdev, flags);
-	if (ret)
-		return NULL;
+	if (cdev->ops->open) {
+		ret = cdev->ops->open(cdev, flags);
+		if (ret)
+			return NULL;
+	}
 
 	return cdev;
 }
@@ -266,8 +282,31 @@ int devfs_create(struct cdev *new)
 	return 0;
 }
 
+int devfs_create_link(struct cdev *cdev, const char *name)
+{
+	struct cdev *new;
+
+	if (cdev_by_name(name))
+		return -EEXIST;
+
+	/*
+	 * Create a link to the real cdev instead of creating
+	 * a link to a link.
+	 */
+	cdev = cdev_readlink(cdev);
+
+	new = xzalloc(sizeof(*new));
+	new->name = xstrdup(name);
+	new->link = cdev;
+	list_add_tail(&new->list, &cdev_list);
+
+	return 0;
+}
+
 int devfs_remove(struct cdev *cdev)
 {
+	struct cdev *c, *tmp;
+
 	if (cdev->open)
 		return -EBUSY;
 
@@ -275,6 +314,13 @@ int devfs_remove(struct cdev *cdev)
 	if (cdev->dev)
 		list_del(&cdev->devices_list);
 
+	list_for_each_entry_safe(c, tmp, &cdev_list, list)
+		if (c->link == cdev)
+			devfs_remove(c);
+
+	if (cdev->link)
+		free(cdev);
+
 	return 0;
 }
 
diff --git a/fs/devfs.c b/fs/devfs.c
index 5c96682..0b8d4fd 100644
--- a/fs/devfs.c
+++ b/fs/devfs.c
@@ -212,12 +212,18 @@ static int devfs_stat(struct device_d *_dev, const char *filename, struct stat *
 {
 	struct cdev *cdev;
 
-	cdev = cdev_by_name(filename + 1);
+	cdev = lcdev_by_name(filename + 1);
 	if (!cdev)
 		return -ENOENT;
 
 	s->st_mode = S_IFCHR;
 	s->st_size = cdev->size;
+
+	if (cdev->link)
+		s->st_mode |= S_IFLNK;
+
+	cdev = cdev_readlink(cdev);
+
 	if (cdev->ops->write)
 		s->st_mode |= S_IWUSR;
 	if (cdev->ops->read)
@@ -242,6 +248,24 @@ static void devfs_delete(struct device_d *dev)
 {
 }
 
+static int devfs_readlink(struct device_d *dev, const char *pathname,
+			  char *buf, size_t bufsz)
+{
+	struct cdev *cdev;
+
+	cdev = cdev_by_name(pathname + 1);
+	if (!cdev)
+		return -ENOENT;
+
+	while (cdev->link)
+		cdev = cdev->link;
+
+	bufsz = min(bufsz, strlen(cdev->name));
+	memcpy(buf, cdev->name, bufsz);
+
+	return 0;
+}
+
 static struct fs_driver_d devfs_driver = {
 	.read      = devfs_read,
 	.write     = devfs_write,
@@ -258,6 +282,7 @@ static struct fs_driver_d devfs_driver = {
 	.erase     = devfs_erase,
 	.protect   = devfs_protect,
 	.memmap    = devfs_memmap,
+	.readlink  = devfs_readlink,
 	.flags     = FS_DRIVER_NO_DEV,
 	.drv = {
 		.probe  = devfs_probe,
diff --git a/include/driver.h b/include/driver.h
index 046dd90..29686f5 100644
--- a/include/driver.h
+++ b/include/driver.h
@@ -450,13 +450,17 @@ struct cdev {
 	int open;
 	struct mtd_info *mtd;
 	u8 dos_partition_type;
+	struct cdev *link;
 };
 
 int devfs_create(struct cdev *);
+int devfs_create_link(struct cdev *, const char *name);
 int devfs_remove(struct cdev *);
 int cdev_find_free_index(const char *);
 struct cdev *device_find_partition(struct device_d *dev, const char *name);
 struct cdev *cdev_by_name(const char *filename);
+struct cdev *lcdev_by_name(const char *filename);
+struct cdev *cdev_readlink(struct cdev *cdev);
 struct cdev *cdev_by_device_node(struct device_node *node);
 struct cdev *cdev_open(const char *name, unsigned long flags);
 int cdev_do_open(struct cdev *, unsigned long flags);
-- 
2.6.2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2015-12-16  9:47 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-12-16  9:47 [PATCH v2] Symlink support for devfs Sascha Hauer
2015-12-16  9:47 ` [PATCH 1/2] devfs: Add symlink support Sascha Hauer
2015-12-16  9:47 ` [PATCH 2/2] partition: Create links with partition names Sascha Hauer
  -- strict thread matches above, loose matches on Subject: below --
2015-12-11 10:40 [PATCH 1/2] devfs: Add symlink support Sascha Hauer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox