diff options
author | Felix Fietkau <nbd@openwrt.org> | 2011-04-16 18:31:21 +0000 |
---|---|---|
committer | Felix Fietkau <nbd@openwrt.org> | 2011-04-16 18:31:21 +0000 |
commit | a1624421aeb492791e696230bc337daa3a836406 (patch) | |
tree | 7915ad510b30c21d3038ae4583f084915d57a1d9 /target/linux/generic/patches-2.6.37/441-block2mtd_refresh.patch | |
parent | 3fa43f54a267f45e42be641945573450a0a419b8 (diff) | |
download | mtk-20170518-a1624421aeb492791e696230bc337daa3a836406.zip mtk-20170518-a1624421aeb492791e696230bc337daa3a836406.tar.gz mtk-20170518-a1624421aeb492791e696230bc337daa3a836406.tar.bz2 |
kernel: reorganize 2.6.37 patches
SVN-Revision: 26692
Diffstat (limited to 'target/linux/generic/patches-2.6.37/441-block2mtd_refresh.patch')
-rw-r--r-- | target/linux/generic/patches-2.6.37/441-block2mtd_refresh.patch | 292 |
1 files changed, 292 insertions, 0 deletions
diff --git a/target/linux/generic/patches-2.6.37/441-block2mtd_refresh.patch b/target/linux/generic/patches-2.6.37/441-block2mtd_refresh.patch new file mode 100644 index 0000000..a1a8463 --- /dev/null +++ b/target/linux/generic/patches-2.6.37/441-block2mtd_refresh.patch @@ -0,0 +1,292 @@ +--- a/drivers/mtd/devices/block2mtd.c ++++ b/drivers/mtd/devices/block2mtd.c +@@ -30,6 +30,8 @@ struct block2mtd_dev { + struct block_device *blkdev; + struct mtd_info mtd; + struct mutex write_mutex; ++ rwlock_t bdev_mutex; ++ char devname[0]; + }; + + +@@ -82,6 +84,12 @@ static int block2mtd_erase(struct mtd_in + size_t len = instr->len; + int err; + ++ read_lock(&dev->bdev_mutex); ++ if (!dev->blkdev) { ++ err = -EINVAL; ++ goto done; ++ } ++ + instr->state = MTD_ERASING; + mutex_lock(&dev->write_mutex); + err = _block2mtd_erase(dev, from, len); +@@ -93,6 +101,10 @@ static int block2mtd_erase(struct mtd_in + instr->state = MTD_ERASE_DONE; + + mtd_erase_callback(instr); ++ ++done: ++ read_unlock(&dev->bdev_mutex); ++ + return err; + } + +@@ -104,10 +116,14 @@ static int block2mtd_read(struct mtd_inf + struct page *page; + int index = from >> PAGE_SHIFT; + int offset = from & (PAGE_SIZE-1); +- int cpylen; ++ int cpylen, err = 0; ++ ++ read_lock(&dev->bdev_mutex); ++ if (!dev->blkdev || (from > mtd->size)) { ++ err = -EINVAL; ++ goto done; ++ } + +- if (from > mtd->size) +- return -EINVAL; + if (from + len > mtd->size) + len = mtd->size - from; + +@@ -122,10 +138,14 @@ static int block2mtd_read(struct mtd_inf + len = len - cpylen; + + page = page_read(dev->blkdev->bd_inode->i_mapping, index); +- if (!page) +- return -ENOMEM; +- if (IS_ERR(page)) +- return PTR_ERR(page); ++ if (!page) { ++ err = -ENOMEM; ++ goto done; ++ } ++ if (IS_ERR(page)) { ++ err = PTR_ERR(page); ++ goto done; ++ } + + memcpy(buf, page_address(page) + offset, cpylen); + page_cache_release(page); +@@ -136,7 +156,10 @@ static int block2mtd_read(struct mtd_inf + offset = 0; + index++; + } +- return 0; ++ ++done: ++ read_unlock(&dev->bdev_mutex); ++ return err; + } + + +@@ -188,12 +211,22 @@ static int block2mtd_write(struct mtd_in + size_t *retlen, const u_char *buf) + { + struct block2mtd_dev *dev = mtd->priv; +- int err; ++ int err = 0; ++ ++ read_lock(&dev->bdev_mutex); ++ if (!dev->blkdev) { ++ err = -EINVAL; ++ goto done; ++ } + + if (!len) +- return 0; +- if (to >= mtd->size) +- return -ENOSPC; ++ goto done; ++ ++ if (to >= mtd->size) { ++ err = -ENOSPC; ++ goto done; ++ } ++ + if (to + len > mtd->size) + len = mtd->size - to; + +@@ -202,6 +235,9 @@ static int block2mtd_write(struct mtd_in + mutex_unlock(&dev->write_mutex); + if (err > 0) + err = 0; ++ ++done: ++ read_unlock(&dev->bdev_mutex); + return err; + } + +@@ -210,52 +246,29 @@ static int block2mtd_write(struct mtd_in + static void block2mtd_sync(struct mtd_info *mtd) + { + struct block2mtd_dev *dev = mtd->priv; +- sync_blockdev(dev->blkdev); +- return; +-} +- +- +-static void block2mtd_free_device(struct block2mtd_dev *dev) +-{ +- if (!dev) +- return; +- +- kfree(dev->mtd.name); + +- if (dev->blkdev) { +- invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping, +- 0, -1); +- close_bdev_exclusive(dev->blkdev, FMODE_READ|FMODE_WRITE); +- } ++ read_lock(&dev->bdev_mutex); ++ if (dev->blkdev) ++ sync_blockdev(dev->blkdev); ++ read_unlock(&dev->bdev_mutex); + +- kfree(dev); ++ return; + } + + +-/* FIXME: ensure that mtd->size % erase_size == 0 */ +-static struct block2mtd_dev *add_device(char *devname, int erase_size, const char *mtdname) ++static int _open_bdev(struct block2mtd_dev *dev) + { + struct block_device *bdev; +- struct block2mtd_dev *dev; +- struct mtd_partition *part; +- char *name; +- +- if (!devname) +- return NULL; +- +- dev = kzalloc(sizeof(struct block2mtd_dev), GFP_KERNEL); +- if (!dev) +- return NULL; + + /* Get a handle on the device */ +- bdev = open_bdev_exclusive(devname, FMODE_READ|FMODE_WRITE, NULL); ++ bdev = open_bdev_exclusive(dev->devname, FMODE_READ|FMODE_WRITE, NULL); + #ifndef MODULE + if (IS_ERR(bdev)) { + + /* We might not have rootfs mounted at this point. Try + to resolve the device name by other means. */ + +- dev_t devt = name_to_dev_t(devname); ++ dev_t devt = name_to_dev_t(dev->devname); + if (devt) { + bdev = open_by_devnum(devt, FMODE_WRITE | FMODE_READ); + } +@@ -263,17 +276,98 @@ static struct block2mtd_dev *add_device( + #endif + + if (IS_ERR(bdev)) { +- ERROR("error: cannot open device %s", devname); +- goto devinit_err; ++ ERROR("error: cannot open device %s", dev->devname); ++ return 1; + } + dev->blkdev = bdev; + + if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) { + ERROR("attempting to use an MTD device as a block device"); +- goto devinit_err; ++ return 1; + } + ++ return 0; ++} ++ ++static void _close_bdev(struct block2mtd_dev *dev) ++{ ++ struct block_device *bdev; ++ ++ if (!dev->blkdev) ++ return; ++ ++ bdev = dev->blkdev; ++ invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping, 0, -1); ++ close_bdev_exclusive(dev->blkdev, FMODE_READ|FMODE_WRITE); ++ dev->blkdev = NULL; ++} ++ ++static void block2mtd_free_device(struct block2mtd_dev *dev) ++{ ++ if (!dev) ++ return; ++ ++ kfree(dev->mtd.name); ++ _close_bdev(dev); ++ kfree(dev); ++} ++ ++ ++static int block2mtd_refresh(struct mtd_info *mtd) ++{ ++ struct block2mtd_dev *dev = mtd->priv; ++ struct block_device *bdev; ++ dev_t devt; ++ int err = 0; ++ ++ /* no other mtd function can run at this point */ ++ write_lock(&dev->bdev_mutex); ++ ++ /* get the device number for the whole disk */ ++ devt = MKDEV(MAJOR(dev->blkdev->bd_dev), 0); ++ ++ /* close the old block device */ ++ _close_bdev(dev); ++ ++ /* open the whole disk, issue a partition rescan, then */ ++ bdev = open_by_devnum(devt, FMODE_WRITE | FMODE_READ); ++ if (!bdev || !bdev->bd_disk) ++ err = -EINVAL; ++#ifndef CONFIG_MTD_BLOCK2MTD_MODULE ++ else ++ err = rescan_partitions(bdev->bd_disk, bdev); ++#endif ++ if (bdev) ++ close_bdev_exclusive(bdev, FMODE_READ|FMODE_WRITE); ++ ++ /* try to open the partition block device again */ ++ _open_bdev(dev); ++ write_unlock(&dev->bdev_mutex); ++ ++ return err; ++} ++ ++/* FIXME: ensure that mtd->size % erase_size == 0 */ ++static struct block2mtd_dev *add_device(char *devname, int erase_size, char *mtdname) ++{ ++ struct block2mtd_dev *dev; ++ struct mtd_partition *part; ++ char *name; ++ ++ if (!devname) ++ return NULL; ++ ++ dev = kzalloc(sizeof(struct block2mtd_dev) + strlen(devname) + 1, GFP_KERNEL); ++ if (!dev) ++ return NULL; ++ ++ strcpy(dev->devname, devname); ++ ++ if (_open_bdev(dev)) ++ goto devinit_err; ++ + mutex_init(&dev->write_mutex); ++ rwlock_init(&dev->bdev_mutex); + + /* Setup the MTD structure */ + /* make the name contain the block device in */ +@@ -298,6 +392,7 @@ static struct block2mtd_dev *add_device( + dev->mtd.read = block2mtd_read; + dev->mtd.priv = dev; + dev->mtd.owner = THIS_MODULE; ++ dev->mtd.refresh_device = block2mtd_refresh; + + part = kzalloc(sizeof(struct mtd_partition), GFP_KERNEL); + part->name = dev->mtd.name; |