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