summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2009-09-10 12:07:10 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2009-09-11 09:13:33 +0200
commitf46010a1ab5182346e424af31fe8b654e8d700f4 (patch)
treefbd7a3bedb25f9ebceb11d16f082bfc05058fea3 /fs
parent2ee3e596c5dfc56baca440faed47bc641719d26b (diff)
downloadbarebox-f46010a1ab5182346e424af31fe8b654e8d700f4.tar.gz
barebox-f46010a1ab5182346e424af31fe8b654e8d700f4.tar.xz
devfs: add open counter
Add an open counter for device files so that we cannot accidently remove an opened device. This happened with bb devices. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'fs')
-rw-r--r--fs/devfs.c36
1 files changed, 29 insertions, 7 deletions
diff --git a/fs/devfs.c b/fs/devfs.c
index 865b9ccb79..ae8eaa8039 100644
--- a/fs/devfs.c
+++ b/fs/devfs.c
@@ -130,6 +130,7 @@ static int devfs_memmap(struct device_d *_dev, FILE *f, void **map, int flags)
static int devfs_open(struct device_d *_dev, FILE *f, const char *filename)
{
struct cdev *cdev;
+ int ret;
cdev = cdev_by_name(filename + 1);
@@ -139,8 +140,13 @@ static int devfs_open(struct device_d *_dev, FILE *f, const char *filename)
f->size = cdev->size;
f->inode = cdev;
- if (cdev->ops->open)
- return cdev->ops->open(cdev, f);
+ if (cdev->ops->open) {
+ ret = cdev->ops->open(cdev, f);
+ if (ret)
+ return ret;
+ }
+
+ cdev->open++;
return 0;
}
@@ -148,9 +154,16 @@ static int devfs_open(struct device_d *_dev, FILE *f, const char *filename)
static int devfs_close(struct device_d *_dev, FILE *f)
{
struct cdev *cdev = f->inode;
+ int ret;
+
+ if (cdev->ops->close) {
+ ret = cdev->ops->close(cdev, f);
+ if (ret)
+ return ret;
+ }
+
+ cdev->open--;
- if (cdev->ops->close)
- return cdev->ops->close(cdev, f);
return 0;
}
@@ -301,11 +314,16 @@ int devfs_create(struct cdev *new)
return 0;
}
-void devfs_remove(struct cdev *cdev)
+int devfs_remove(struct cdev *cdev)
{
+ if (cdev->open)
+ return -EBUSY;
+
list_del(&cdev->list);
if (cdev->dev)
list_del(&cdev->devices_list);
+
+ return 0;
}
int devfs_add_partition(const char *devname, unsigned long offset, size_t size,
@@ -333,7 +351,7 @@ int devfs_add_partition(const char *devname, unsigned long offset, size_t size,
new->dev = cdev->dev;
new->flags = flags | DEVFS_IS_PARTITION;
- list_add_tail(&new->list, &cdev_list);
+ devfs_create(new);
return 0;
}
@@ -341,6 +359,7 @@ int devfs_add_partition(const char *devname, unsigned long offset, size_t size,
int devfs_del_partition(const char *name)
{
struct cdev *cdev;
+ int ret;
cdev = cdev_by_name(name);
if (!cdev)
@@ -351,7 +370,10 @@ int devfs_del_partition(const char *name)
if (cdev->flags & DEVFS_PARTITION_FIXED)
return -EPERM;
- devfs_remove(cdev);
+ ret = devfs_remove(cdev);
+ if (ret)
+ return ret;
+
free(cdev->name);
free(cdev);