#include <linux/kmemleak.h>
#include <asm/uaccess.h>
#include "internal.h"
+#include <linux/mtd/blktrans.h>
+#include <linux/mtd/mtd.h>
struct bdev_inode {
struct block_device bdev;
if (!sb)
goto out;
if (sb->s_flags & MS_RDONLY) {
- deactivate_locked_super(sb);
+ sb->s_frozen = SB_FREEZE_TRANS;
+ up_write(&sb->s_umount);
mutex_unlock(&bdev->bd_fsfreeze_mutex);
return sb;
}
BUG_ON(sb->s_bdev != bdev);
down_write(&sb->s_umount);
if (sb->s_flags & MS_RDONLY)
- goto out_deactivate;
+ goto out_unfrozen;
if (sb->s_op->unfreeze_fs) {
error = sb->s_op->unfreeze_fs(sb);
}
}
+out_unfrozen:
sb->s_frozen = SB_UNFROZEN;
smp_wmb();
wake_up(&sb->s_wait_unfrozen);
-out_deactivate:
if (sb)
deactivate_locked_super(sb);
out_unlock:
* NULL first argument is nfsd_sync_dir() and that's not a directory.
*/
-static int block_fsync(struct file *filp, struct dentry *dentry, int datasync)
+int block_fsync(struct file *filp, struct dentry *dentry, int datasync)
{
return sync_blockdev(I_BDEV(filp->f_mapping->host));
}
return NULL;
return &ei->vfs_inode;
}
+EXPORT_SYMBOL(block_fsync);
static void bdev_destroy_inode(struct inode *inode)
{
/*
* hooks: /n/, see "layering violations".
*/
- ret = devcgroup_inode_permission(bdev->bd_inode, perm);
- if (ret != 0) {
- bdput(bdev);
- return ret;
+ if (!for_part) {
+ ret = devcgroup_inode_permission(bdev->bd_inode, perm);
+ if (ret != 0) {
+ bdput(bdev);
+ return ret;
+ }
}
lock_kernel();
if (!bdev->bd_part)
goto out_clear;
+ ret = 0;
if (disk->fops->open) {
ret = disk->fops->open(bdev, mode);
if (ret == -ERESTARTSYS) {
mutex_unlock(&bdev->bd_mutex);
goto restart;
}
- if (ret)
- goto out_clear;
}
+ /*
+ * If the device is invalidated, rescan partition
+ * if open succeeded or failed with -ENOMEDIUM.
+ * The latter is necessary to prevent ghost
+ * partitions on a removed medium.
+ */
+ if (bdev->bd_invalidated && (!ret || ret == -ENOMEDIUM))
+ rescan_partitions(disk, bdev);
+ if (ret)
+ goto out_clear;
+
if (!bdev->bd_openers) {
bd_set_size(bdev,(loff_t)get_capacity(disk)<<9);
bdi = blk_get_backing_dev_info(bdev);
bdi = &default_backing_dev_info;
bdev->bd_inode->i_data.backing_dev_info = bdi;
}
- if (bdev->bd_invalidated)
- rescan_partitions(disk, bdev);
} else {
struct block_device *whole;
whole = bdget_disk(disk, 0);
bd_set_size(bdev, (loff_t)bdev->bd_part->nr_sects << 9);
}
} else {
- put_disk(disk);
module_put(disk->fops->owner);
+ put_disk(disk);
disk = NULL;
if (bdev->bd_contains == bdev) {
- if (bdev->bd_disk->fops->open) {
+ ret = 0;
+ if (bdev->bd_disk->fops->open)
ret = bdev->bd_disk->fops->open(bdev, mode);
- if (ret)
- goto out_unlock_bdev;
- }
- if (bdev->bd_invalidated)
+ /* the same as first opener case, read comment there */
+ if (bdev->bd_invalidated && (!ret || ret == -ENOMEDIUM))
rescan_partitions(bdev->bd_disk, bdev);
+ if (ret)
+ goto out_unlock_bdev;
}
}
bdev->bd_openers++;
.direct_IO = blkdev_direct_IO,
};
+
+ssize_t mydo_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
+{
+ unsigned long buf_addr = (unsigned long)buf;
+ if((memcmp(filp->f_mapping->host->i_bdev->bd_disk->disk_name, "mtdblock", 8) == 0) &&(buf_addr >= 0xc0000000))// kernel mem is usb tran &&(buf_addr >= 0xc0000000)
+ {
+ struct mtd_blktrans_dev *dev;
+ struct mtd_blktrans_ops *tr;
+ struct mtd_info *mtd;
+
+ dev = (filp->f_mapping->host->i_bdev->bd_disk->private_data);
+ mtd = dev->mtd;
+ /*if((buf_addr < 0xc0000000)&&(mtd->name[0]=='u' &&mtd->name[3]=='r' && mtd->name[4]==0)) // user part
+ {
+ return(do_sync_read(filp, buf,len,ppos));
+ }*/
+ tr = dev->tr;
+ if (!tr->readsect)
+ {
+ return(do_sync_read(filp, buf,len,ppos));
+ }
+ //printk("mydo_sync_read buf = 0x%lx LBA = 0x%lx len = 0x%x \n",buf, (unsigned long)(*ppos>>9),len);
+ if(tr->readsect(dev, (unsigned long)(*ppos>>9), len>>9, buf))
+ {
+ return 0 ;
+ }
+ *ppos += len;
+ return len;
+ }
+
+ else
+ {
+ return(do_sync_read(filp, buf,len,ppos));
+ }
+}
+
+ssize_t mydo_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)
+{
+ unsigned long buf_addr = (unsigned long)buf;
+ if((memcmp(filp->f_mapping->host->i_bdev->bd_disk->disk_name, "mtdblock", 8) == 0) &&(buf_addr >= 0xc0000000))// kernel mem is usb tran &&(buf_addr >= 0xc0000000)
+ {
+ struct mtd_blktrans_dev *dev;
+ struct mtd_blktrans_ops *tr;
+ struct mtd_info *mtd;
+
+ dev = (filp->f_mapping->host->i_bdev->bd_disk->private_data);
+
+ mtd = dev->mtd;
+ /*if((buf_addr < 0xc0000000)&&(mtd->name[0]=='u' &&mtd->name[3]=='r' && mtd->name[4]==0))
+ {
+ return(do_sync_write(filp, buf,len,ppos));
+ }*/
+
+ tr = dev->tr;
+
+ if (!tr->writesect)
+ return 0;
+ //printk("mydo_sync_write buf = 0x%lx LBA = 0x%lx len = 0x%x \n",buf, (unsigned long)(*ppos>>9),len);
+ if(tr->writesect(dev, (unsigned long)(*ppos>>9), len>>9, buf))
+ {
+ return 0 ;
+ }
+ *ppos += len;
+ return len;
+ }
+
+ else
+ {
+ return(do_sync_write(filp, buf,len,ppos));
+ }
+}
+
+
const struct file_operations def_blk_fops = {
.open = blkdev_open,
.release = blkdev_close,
.llseek = block_llseek,
- .read = do_sync_read,
- .write = do_sync_write,
+ .read = mydo_sync_read,
+ .write = mydo_sync_write,
.aio_read = generic_file_aio_read,
.aio_write = blkdev_aio_write,
.mmap = generic_file_mmap,