Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 84241
b: refs/heads/master
c: e73f445
h: refs/heads/master
i:
  84239: 290f8d2
v: v3
  • Loading branch information
Artem Bityutskiy authored and Artem Bityutskiy committed Dec 26, 2007
1 parent 837ad7c commit 84ecd38
Show file tree
Hide file tree
Showing 8 changed files with 202 additions and 64 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 9f961b57568960a150cc9781c52824c9093a0514
refs/heads/master: e73f4459d969bb266f03dd4cbe21bdba8cb2732c
142 changes: 127 additions & 15 deletions trunk/drivers/mtd/ubi/build.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,6 @@ static int mtd_devs = 0;
/* MTD devices specification parameters */
static struct mtd_dev_param mtd_dev_param[UBI_MAX_DEVICES];

/* All UBI devices in system */
struct ubi_device *ubi_devices[UBI_MAX_DEVICES];

/* Root UBI "class" object (corresponds to '/<sysfs>/class/ubi/') */
struct class *ubi_class;

Expand All @@ -83,6 +80,12 @@ static struct miscdevice ubi_ctrl_cdev = {
.fops = &ubi_ctrl_cdev_operations,
};

/* All UBI devices in system */
static struct ubi_device *ubi_devices[UBI_MAX_DEVICES];

/* Protects @ubi_devices and @ubi->ref_count */
static DEFINE_SPINLOCK(ubi_devices_lock);

/* "Show" method for files in '/<sysfs>/class/ubi/' */
static ssize_t ubi_version_show(struct class *class, char *buf)
{
Expand Down Expand Up @@ -118,37 +121,145 @@ static struct device_attribute dev_min_io_size =
static struct device_attribute dev_bgt_enabled =
__ATTR(bgt_enabled, S_IRUGO, dev_attribute_show, NULL);

/**
* ubi_get_device - get UBI device.
* @ubi_num: UBI device number
*
* This function returns UBI device description object for UBI device number
* @ubi_num, or %NULL if the device does not exist. This function increases the
* device reference count to prevent removal of the device. In other words, the
* device cannot be removed if its reference count is not zero.
*/
struct ubi_device *ubi_get_device(int ubi_num)
{
struct ubi_device *ubi;

spin_lock(&ubi_devices_lock);
ubi = ubi_devices[ubi_num];
if (ubi) {
ubi_assert(ubi->ref_count >= 0);
ubi->ref_count += 1;
get_device(&ubi->dev);
}
spin_unlock(&ubi_devices_lock);

return ubi;
}

/**
* ubi_put_device - drop an UBI device reference.
* @ubi: UBI device description object
*/
void ubi_put_device(struct ubi_device *ubi)
{
spin_lock(&ubi_devices_lock);
ubi->ref_count -= 1;
put_device(&ubi->dev);
spin_unlock(&ubi_devices_lock);
}

/**
* ubi_get_by_major - get UBI device description object by character device
* major number.
* @major: major number
*
* This function is similar to 'ubi_get_device()', but it searches the device
* by its major number.
*/
struct ubi_device *ubi_get_by_major(int major)
{
int i;
struct ubi_device *ubi;

spin_lock(&ubi_devices_lock);
for (i = 0; i < UBI_MAX_DEVICES; i++) {
ubi = ubi_devices[i];
if (ubi && MAJOR(ubi->cdev.dev) == major) {
ubi_assert(ubi->ref_count >= 0);
ubi->ref_count += 1;
get_device(&ubi->dev);
spin_unlock(&ubi_devices_lock);
return ubi;
}
}
spin_unlock(&ubi_devices_lock);

return NULL;
}

/**
* ubi_major2num - get UBI device number by character device major number.
* @major: major number
*
* This function searches UBI device number object by its major number. If UBI
* device was not found, this function returns -ENODEV, othewise the UBI device
* number is returned.
*/
int ubi_major2num(int major)
{
int i, ubi_num = -ENODEV;

spin_lock(&ubi_devices_lock);
for (i = 0; i < UBI_MAX_DEVICES; i++) {
struct ubi_device *ubi = ubi_devices[i];

if (ubi && MAJOR(ubi->cdev.dev) == major) {
ubi_num = ubi->ubi_num;
break;
}
}
spin_unlock(&ubi_devices_lock);

return ubi_num;
}

/* "Show" method for files in '/<sysfs>/class/ubi/ubiX/' */
static ssize_t dev_attribute_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
const struct ubi_device *ubi;
ssize_t ret;
struct ubi_device *ubi;

/*
* The below code looks weird, but it actually makes sense. We get the
* UBI device reference from the contained 'struct ubi_device'. But it
* is unclear if the device was removed or not yet. Indeed, if the
* device was removed before we increased its reference count,
* 'ubi_get_device()' will return -ENODEV and we fail.
*
* Remember, 'struct ubi_device' is freed in the release function, so
* we still can use 'ubi->ubi_num'.
*/
ubi = container_of(dev, struct ubi_device, dev);
ubi = ubi_get_device(ubi->ubi_num);
if (!ubi)
return -ENODEV;

if (attr == &dev_eraseblock_size)
return sprintf(buf, "%d\n", ubi->leb_size);
ret = sprintf(buf, "%d\n", ubi->leb_size);
else if (attr == &dev_avail_eraseblocks)
return sprintf(buf, "%d\n", ubi->avail_pebs);
ret = sprintf(buf, "%d\n", ubi->avail_pebs);
else if (attr == &dev_total_eraseblocks)
return sprintf(buf, "%d\n", ubi->good_peb_count);
ret = sprintf(buf, "%d\n", ubi->good_peb_count);
else if (attr == &dev_volumes_count)
return sprintf(buf, "%d\n", ubi->vol_count);
ret = sprintf(buf, "%d\n", ubi->vol_count);
else if (attr == &dev_max_ec)
return sprintf(buf, "%d\n", ubi->max_ec);
ret = sprintf(buf, "%d\n", ubi->max_ec);
else if (attr == &dev_reserved_for_bad)
return sprintf(buf, "%d\n", ubi->beb_rsvd_pebs);
ret = sprintf(buf, "%d\n", ubi->beb_rsvd_pebs);
else if (attr == &dev_bad_peb_count)
return sprintf(buf, "%d\n", ubi->bad_peb_count);
ret = sprintf(buf, "%d\n", ubi->bad_peb_count);
else if (attr == &dev_max_vol_count)
return sprintf(buf, "%d\n", ubi->vtbl_slots);
ret = sprintf(buf, "%d\n", ubi->vtbl_slots);
else if (attr == &dev_min_io_size)
return sprintf(buf, "%d\n", ubi->min_io_size);
ret = sprintf(buf, "%d\n", ubi->min_io_size);
else if (attr == &dev_bgt_enabled)
return sprintf(buf, "%d\n", ubi->thread_enabled);
ret = sprintf(buf, "%d\n", ubi->thread_enabled);
else
BUG();

return 0;
ubi_put_device(ubi);
return ret;
}

/* Fake "release" method for UBI devices */
Expand Down Expand Up @@ -670,6 +781,7 @@ static void detach_mtd_dev(struct ubi_device *ubi)
int ubi_num = ubi->ubi_num, mtd_num = ubi->mtd->index;

dbg_msg("detaching mtd%d from ubi%d", ubi->mtd->index, ubi_num);
ubi_assert(ubi->ref_count == 0);
uif_close(ubi);
ubi_eba_close(ubi);
ubi_wl_close(ubi);
Expand Down
34 changes: 10 additions & 24 deletions trunk/drivers/mtd/ubi/cdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,23 +55,6 @@
#define VOL_CDEV_IOC_MAX_SEQ 2
#endif

/**
* major_to_device - get UBI device object by character device major number.
* @major: major number
*
* This function returns a pointer to the UBI device object.
*/
static struct ubi_device *major_to_device(int major)
{
int i;

for (i = 0; i < UBI_MAX_DEVICES; i++)
if (ubi_devices[i] && MAJOR(ubi_devices[i]->cdev.dev) == major)
return ubi_devices[i];
BUG();
return NULL;
}

/**
* get_exclusive - get exclusive access to an UBI volume.
* @desc: volume descriptor
Expand Down Expand Up @@ -129,9 +112,11 @@ static void revoke_exclusive(struct ubi_volume_desc *desc, int mode)
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;
int vol_id = iminor(inode) - 1, mode, ubi_num;

ubi_num = ubi_major2num(imajor(inode));
if (ubi_num < 0)
return ubi_num;

if (file->f_mode & FMODE_WRITE)
mode = UBI_READWRITE;
Expand All @@ -140,7 +125,7 @@ static int vol_cdev_open(struct inode *inode, struct file *file)

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

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

Expand Down Expand Up @@ -586,9 +571,9 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file,
if (!capable(CAP_SYS_RESOURCE))
return -EPERM;

ubi = major_to_device(imajor(inode));
if (IS_ERR(ubi))
return PTR_ERR(ubi);
ubi = ubi_get_by_major(imajor(inode));
if (!ubi)
return -ENODEV;

switch (cmd) {
/* Create volume command */
Expand Down Expand Up @@ -695,6 +680,7 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file,
break;
}

ubi_put_device(ubi);
return err;
}

Expand Down
5 changes: 5 additions & 0 deletions trunk/drivers/mtd/ubi/eba.c
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ int ubi_eba_unmap_leb(struct ubi_device *ubi, struct ubi_volume *vol,
{
int err, pnum, vol_id = vol->vol_id;

ubi_assert(ubi->ref_count > 0);
ubi_assert(vol->ref_count > 0);

if (ubi->ro_mode)
Expand Down Expand Up @@ -389,6 +390,7 @@ int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
struct ubi_vid_hdr *vid_hdr;
uint32_t uninitialized_var(crc);

ubi_assert(ubi->ref_count > 0);
ubi_assert(vol->ref_count > 0);

err = leb_read_lock(ubi, vol_id, lnum);
Expand Down Expand Up @@ -614,6 +616,7 @@ int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
int err, pnum, tries = 0, vol_id = vol->vol_id;
struct ubi_vid_hdr *vid_hdr;

ubi_assert(ubi->ref_count > 0);
ubi_assert(vol->ref_count > 0);

if (ubi->ro_mode)
Expand Down Expand Up @@ -749,6 +752,7 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol,
struct ubi_vid_hdr *vid_hdr;
uint32_t crc;

ubi_assert(ubi->ref_count > 0);
ubi_assert(vol->ref_count > 0);

if (ubi->ro_mode)
Expand Down Expand Up @@ -865,6 +869,7 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
struct ubi_vid_hdr *vid_hdr;
uint32_t crc;

ubi_assert(ubi->ref_count > 0);
ubi_assert(vol->ref_count > 0);

if (ubi->ro_mode)
Expand Down
Loading

0 comments on commit 84ecd38

Please sign in to comment.