diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2009-09-10 12:07:10 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2009-09-11 09:13:33 +0200 |
commit | f46010a1ab5182346e424af31fe8b654e8d700f4 (patch) | |
tree | fbd7a3bedb25f9ebceb11d16f082bfc05058fea3 /fs | |
parent | 2ee3e596c5dfc56baca440faed47bc641719d26b (diff) | |
download | barebox-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.c | 36 |
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); |