Home | History | Annotate | Download | only in ltpfs
      1 
      2 #include <linux/kernel.h>
      3 #include <linux/module.h>
      4 #include <linux/init.h>
      5 #include <linux/types.h>
      6 #include <linux/fs.h>
      7 #include <linux/ioctl.h>
      8 #include <linux/pm.h>
      9 #include <linux/genhd.h>
     10 #include <linux/bio.h>
     11 #include <linux/mm.h>
     12 #include <linux/swap.h>
     13 #include <linux/bio.h>
     14 #include <linux/blk.h>
     15 #include <linux/slab.h>
     16 #include <linux/mempool.h>
     17 #include <linux/workqueue.h>
     18 #include <linux/namei.h>
     19 #include <linux/mount.h>
     20 #include <linux/quotaops.h>
     21 #include <linux/pagemap.h>
     22 #include <linux/dnotify.h>
     23 #include <linux/smp_lock.h>
     24 #include <linux/personality.h>
     25 #include <linux/security.h>
     26 #include <linux/buffer_head.h>
     27 #include <asm/namei.h>
     28 #include <asm/uaccess.h>
     29 
     30 #define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
     31 #define IS_POSIX(fl)	(fl->fl_flags & FL_POSIX)
     32 #define TEST_MEM_SIZE  4096
     33 #define FALSE          0
     34 #include "Ltpfs.h"
     35 
     36 static int ltpdev_open(struct inode *inode, struct file *pfile);
     37 static int ltpdev_release(struct inode *inode, struct file *pfile);
     38 static int ltpdev_ioctl(struct inode *pinode, struct file *pfile,
     39 			unsigned int cmd, unsigned long arg);
     40 static int do_buffer_c_tests(void);
     41 
     42 static struct block_device_operations blkops = {
     43 open:	ltpdev_open,
     44 release:ltpdev_release,
     45 ioctl:	ltpdev_ioctl,
     46 };
     47 
     48 int ltp_fs_major = LTPMAJOR;
     49 int test_iteration = 0;
     50 
     51 static char genhd_flags = 0;
     52 static struct gendisk *gd_ptr;
     53 static spinlock_t bdev_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
     54 
     55 MODULE_AUTHOR("Martin Ridgeway <mridge (at) us.ibm.com>");
     56 MODULE_DESCRIPTION(FS_LTP_TEST_DRIVER_NAME);
     57 MODULE_LICENSE("GPL");
     58 
     59 /*
     60  * Device operations for the virtual FS devices
     61  */
     62 
     63 static struct pm_dev *ltp_pm_dev = NULL;
     64 struct block_device *ltplookup_bdev(const char *path);
     65 int path_lookup(const char *name, unsigned int flags, struct nameidata *nd);
     66 //static int __emul_lookup_dentry(const char *name, struct nameidata *nd);
     67 void path_release(struct nameidata *nd);
     68 
     69 static int ltpdev_open(struct inode *pinode, struct file *pfile)
     70 {
     71 	printk(KERN_ALERT "ltpdev_open \n");
     72 	return 0;
     73 }
     74 
     75 static int ltpdev_release(struct inode *pinode, struct file *pfile)
     76 {
     77 
     78 	printk(KERN_ALERT "ltpdev_release \n");
     79 	return 0;
     80 }
     81 
     82 static int ltpdev_ioctl(struct inode *pinode, struct file *pfile,
     83 			unsigned int cmd, unsigned long arg)
     84 {
     85 
     86 	struct bio *my_bio = NULL;
     87 	struct bio *my_bio_copy = NULL;
     88 	request_queue_t *q = NULL;
     89 	struct block_device *bdev = NULL;
     90 	unsigned long uaddr;
     91 
     92 	unsigned int bytes_done = 100;
     93 
     94 	int error = 0;
     95 	int rc = 0;
     96 
     97     /*****************************************************************************/
     98 
     99 	printk(KERN_ALERT "ltpdev_ioctl fs tests\n");
    100 
    101 	switch (cmd) {
    102 
    103 	case LTPAIODEV_CMD:
    104 		printk(KERN_ALERT "Running AIO FS tests \n");
    105 		printk(KERN_ALERT "AIO FS tests complete\n");
    106 		break;
    107 
    108 	case LTPBIODEV_CMD:
    109 
    110 		printk(KERN_ALERT "Running BIO FS tests \n");
    111 
    112 		my_bio = bio_alloc(GFP_KERNEL, 0);
    113 		if (!my_bio) {
    114 			printk(KERN_ALERT
    115 			       "Error getting kernel slab memory !!\n");
    116 		} else {
    117 			printk(KERN_ALERT "kernel slab memory alloc OK\n");
    118 		}
    119 
    120 		bio_endio(my_bio, bytes_done, error);
    121 
    122 		printk(KERN_ALERT "Return from bio_endio = %d \n", error);
    123 
    124 		my_bio_copy = bio_clone(my_bio, GFP_ATOMIC);
    125 
    126 		if (!my_bio_copy) {
    127 			printk(KERN_ALERT
    128 			       "Error getting kernel bio clone !!\n");
    129 		} else {
    130 			printk(KERN_ALERT "kernel bio clone OK\n");
    131 		}
    132 
    133 		my_bio_copy = bio_clone(my_bio, GFP_NOIO);
    134 
    135 		if (!my_bio_copy) {
    136 			printk(KERN_ALERT
    137 			       "Error getting kernel bio clone !!\n");
    138 		} else {
    139 			printk(KERN_ALERT "kernel bio clone OK\n");
    140 		}
    141 
    142 //        q = bdev_get_queue(my_bio->bi_bdev);
    143 
    144 //        rc = bio_phys_segments(q, my_bio);
    145 
    146 //        rc = bio_hw_segments(q, my_bio);
    147 
    148 		bdev = lookup_bdev(LTP_FS_DEVICE_NAME);
    149 
    150 		printk(KERN_ALERT "return from bdev size %d\n",
    151 		       bdev->bd_block_size);
    152 
    153 		printk(KERN_ALERT "Return from phys_segments = %d \n", rc);
    154 
    155 //        Don't use this API, causes system to hang and corrupts FS
    156 //        bio_put(my_bio);
    157 
    158 		(char *)uaddr = kmalloc(TEST_MEM_SIZE, GFP_KERNEL);
    159 
    160 		my_bio_copy = bio_map_user(bdev, uaddr, TEST_MEM_SIZE, FALSE);
    161 
    162 		printk(KERN_ALERT "Return from bio_map_user %p\n", my_bio_copy);
    163 
    164 		do_buffer_c_tests();
    165 
    166 		printk(KERN_ALERT "BIO FS tests complete\n");
    167 
    168 		break;
    169 	}
    170 
    171 	return 0;
    172 }
    173 
    174 static int ltp_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data)
    175 {
    176 	return 0;
    177 }
    178 
    179 int init_module(void)
    180 {
    181 	int result;
    182 
    183 	printk(KERN_ALERT "ltpdev_init_module \n");
    184 
    185 	ltp_pm_dev = pm_register(PM_UNKNOWN_DEV, 0, ltp_pm_callback);
    186 
    187 	result = register_blkdev(ltp_fs_major, LTP_FS_DEV_NAME);
    188 
    189 	printk(KERN_ALERT "LTP FS: register_blkdev result=%d major %d\n",
    190 	       result, ltp_fs_major);
    191 
    192 	if (result < 0) {
    193 		printk(KERN_ALERT "LTP FS: can't get major %d\n", ltp_fs_major);
    194 		return result;
    195 	}
    196 
    197 	gd_ptr = kmalloc(sizeof(struct gendisk *), GFP_KERNEL);
    198 
    199 	if (!gd_ptr) {
    200 		printk(KERN_ALERT "ERROR getting memory !!!\n");
    201 		return 0;
    202 	}
    203 
    204 	gd_ptr = alloc_disk(1);
    205 
    206 	printk(KERN_ALERT "gd_ptr after alloc = %p \n", gd_ptr);
    207 
    208 	gd_ptr->major = ltp_fs_major;
    209 	gd_ptr->first_minor = 0;
    210 	gd_ptr->fops = &blkops;
    211 	gd_ptr->driverfs_dev = NULL;
    212 	gd_ptr->capacity = MAX_NUM_DISKS;
    213 	gd_ptr->flags = genhd_flags;
    214 
    215 	sprintf(gd_ptr->disk_name, LTP_FS_DEV_NAME);
    216 
    217 	add_disk(gd_ptr);
    218 
    219 	return 0;
    220 }
    221 
    222 void cleanup_module(void)
    223 {
    224 
    225 	printk(KERN_ALERT "Exiting module and cleaning up \n");
    226 
    227 	pm_unregister(ltp_pm_dev);
    228 
    229 	put_disk(gd_ptr);
    230 
    231 	del_gendisk(gd_ptr);
    232 
    233 	unregister_blkdev(ltp_fs_major, LTP_FS_DEV_NAME);
    234 
    235 }
    236 
    237 static int do_buffer_c_tests()
    238 {
    239 	int line_no = 0;
    240 
    241 	printk(KERN_ALERT "Starting buffer.c coverage tests... \n");
    242 
    243 	__buffer_error("Test file", line_no);
    244 
    245 	printk(KERN_ALERT "buffer.c coverage tests complete...\n");
    246 
    247 	return 0;
    248 }
    249 
    250 /**
    251  * lookup_bdev  - lookup a struct block_device by name
    252  *
    253  * @path:	special file representing the block device
    254  *
    255  * Get a reference to the blockdevice at @path in the current
    256  * namespace if possible and return it.  Return ERR_PTR(error)
    257  * otherwise.
    258  */
    259 struct block_device *lookup_bdev(const char *path)
    260 {
    261 	struct block_device *bdev;
    262 	struct inode *inode;
    263 	struct nameidata nd;
    264 	int error;
    265 
    266 	if (!path || !*path)
    267 		return ERR_PTR(-EINVAL);
    268 
    269 	error = path_lookup(path, LOOKUP_FOLLOW, &nd);
    270 	if (error)
    271 		return ERR_PTR(error);
    272 
    273 	inode = nd.dentry->d_inode;
    274 	error = -ENOTBLK;
    275 	if (!S_ISBLK(inode->i_mode))
    276 		goto fail;
    277 	error = -EACCES;
    278 	if (nd.mnt->mnt_flags & MNT_NODEV)
    279 		goto fail;
    280 	error = bd_acquire(inode);
    281 	if (error)
    282 		goto fail;
    283 	bdev = inode->i_bdev;
    284 
    285 out:
    286 	path_release(&nd);
    287 	return bdev;
    288 fail:
    289 	bdev = ERR_PTR(error);
    290 	goto out;
    291 }
    292 
    293 int bd_acquire(struct inode *inode)
    294 {
    295 	struct block_device *bdev;
    296 	spin_lock(&bdev_lock);
    297 	if (inode->i_bdev) {
    298 		atomic_inc(&inode->i_bdev->bd_count);
    299 		spin_unlock(&bdev_lock);
    300 		return 0;
    301 	}
    302 	spin_unlock(&bdev_lock);
    303 	bdev = bdget(kdev_t_to_nr(inode->i_rdev));
    304 	if (!bdev)
    305 		return -ENOMEM;
    306 	spin_lock(&bdev_lock);
    307 	if (!inode->i_bdev) {
    308 		inode->i_bdev = bdev;
    309 		inode->i_mapping = bdev->bd_inode->i_mapping;
    310 		list_add(&inode->i_devices, &bdev->bd_inodes);
    311 	} else if (inode->i_bdev != bdev)
    312 		BUG();
    313 	spin_unlock(&bdev_lock);
    314 	return 0;
    315 }
    316