/*************************************************************************** * * Copyright (C) 2001 International Business Machines * All rights reserved. * * This file is part of the GPFS mmfslinux kernel module. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *************************************************************************** */ /* @(#)90 1.28 src/avs/fs/mmfs/ts/kernext/gpl-linux/block.c, mmfs, avs_rgpfs24, rgpfs240610b 8/4/04 23:12:51 */ #if LINUX_KERNEL_VERSION < 2050000 #define __NO_VERSION__ #ifndef __KERNEL__ #define __KERNEL__ #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* Major number for GPFS filesystem /dev entries. Note that FS_MAJOR is just our first choice for a number. Since we don't have a reserved number (see linux/major.h) we have to be prepared to receive EBUSY when we register. If FS_MAJOR is already taken, we allow devfs_register_blkdev to assign us any available number. After we've registered, our major number will be stored in GPFSFileSysMajorNumber. */ #define FS_MAJOR 239 static unsigned int GPFSFileSysMajorNumber = 0; /* just return a zero'd buffer */ ssize_t gpfs_fb_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos) { ssize_t written = 0; int toWrite; int rc = 0; ENTER(0); TRACE3(TRACE_BOPS, 2, TRCID_FBREAD_ENTER, "gpfs_fb_read: enter file 0x%X buf 0x%X nbytes %d\n", file, buf, nbytes); while (nbytes) { toWrite = (nbytes >= PAGE_SIZE) ? PAGE_SIZE : nbytes; rc = clear_user(buf, toWrite); if (rc) goto xerror; nbytes -= toWrite; buf += toWrite; written += toWrite; } xerror: TRACE1(TRACE_BOPS, 2, TRCID_FBREAD_EXIT, "gpfs_fb_read: exit written %d\n", written); EXIT(0); return (rc ? -ENOSYS : written); } ssize_t gpfs_fb_write(struct file *file, const char *buf, size_t nbytes, loff_t *ppos) { ENTER(0); TRACE3(TRACE_BOPS, 2, TRCID_FBWRITE_ENTER, "gpfs_fb_write: enter file 0x%X buf 0x%X nbytes %d\n", file, buf, nbytes); EXIT(0); return nbytes; } int gpfs_fb_open(struct inode *inode, struct file *file) { struct block_device *bdP; int openers; int count; ENTER(0); TRACE2(TRACE_BOPS, 2, TRCID_FBOPEN_ENTER, "gpfs_fb_open: inode 0x%X file 0x%X\n", inode, file); if (inode->i_bdev) { bdP = inode->i_bdev; # if LINUX_KERNEL_VERSION >= 2041300 openers = bdP->bd_openers; count = atomic_read(&bdP->bd_count); #else openers = atomic_read(&bdP->bd_openers); count = atomic_read(&bdP->bd_count); #endif TRACE3(TRACE_BOPS, 2, TRCID_FBOPEN_EXIT, "gpfs_fb_open: exit bdP 0x%lX openers %d count %d\n", bdP, openers, count); } EXIT(0); return 0; } int gpfs_fb_release(struct inode *inode, struct file *file) { struct block_device *bdP; int openers; int count; ENTER(0); TRACE2(TRACE_BOPS, 2, TRCID_FBRELEASE_ENTER, "gpfs_fb_release: inode 0x%X file 0x%X\n", inode, file); if (inode->i_bdev) { bdP = inode->i_bdev; # if LINUX_KERNEL_VERSION >= 2041300 openers = bdP->bd_openers; count = atomic_read(&bdP->bd_count); #else openers = atomic_read(&bdP->bd_openers); count = atomic_read(&bdP->bd_count); #endif /* We're responsible for calling this to lower the openers * count as we have a specific release routine. We're using * BDEV_RAW since that doesn't incur any operations in * blkdev_put() */ blkdev_put(bdP, BDEV_RAW); TRACE3(TRACE_BOPS, 2, TRCID_FBRELEASE_EXIT, "gpfs_fb_release: exit bdP 0x%lX openers %d count %d\n", bdP, openers, count); } EXIT(0); return 0; } int gpfs_fb_ioctl(struct inode *inode, struct file *file, unsigned p1, unsigned long p2) { ENTER(0); TRACE4(TRACE_BOPS, 2, TRCID_FBIOCTL_ENTER, "gpfs_fb_ioctl: inode 0x%X file 0x%X p1 %d p2 %d\n", inode, file, p1, p2); EXIT(0); return 0; } int gpfs_b_open(struct inode *inode, struct file *file) { struct block_device *bdP; int openers; int count; ENTER(0); TRACE2(TRACE_BOPS, 2, TRCID_BOPEN_ENTER, "gpfs_b_open: inode 0x%X file 0x%X\n", inode, file); if (!inode) return -EINVAL; if (inode->i_bdev) { bdP = inode->i_bdev; # if LINUX_KERNEL_VERSION >= 2041300 openers = bdP->bd_openers; count = atomic_read(&bdP->bd_count); #else openers = atomic_read(&bdP->bd_openers); count = atomic_read(&bdP->bd_count); #endif TRACE3(TRACE_BOPS, 2, TRCID_BOPEN_EXIT, "gpfs_b_open: exit bdP 0x%lX openers %d count %d\n", bdP, openers, count); } file->f_op = &gpfs_fbps; EXIT(0); return 0; /* success */ } int gpfs_b_release(struct inode *inode, struct file *file) { struct block_device *bdP; int openers; int count; ENTER(0); TRACE2(TRACE_BOPS, 2, TRCID_BRELEASE_ENTER, "gpfs_b_release: inode 0x%X file 0x%X\n", inode, file); if (inode->i_bdev) { bdP = inode->i_bdev; # if LINUX_KERNEL_VERSION >= 2041300 openers = bdP->bd_openers; count = atomic_read(&bdP->bd_count); #else openers = atomic_read(&bdP->bd_openers); count = atomic_read(&bdP->bd_count); #endif TRACE3(TRACE_BOPS, 2, TRCID_BRELEASE_EXIT, "gpfs_b_release: exit bdP 0x%lX openers %d count %d\n", bdP, openers, count); } EXIT(0); return 0; /* success */ } int gpfs_b_ioctl(struct inode *inode, struct file *file, unsigned p1, unsigned long p2) { ENTER(0); TRACE4(TRACE_BOPS, 2, TRCID_BIOCTL_ENTER, "gpfs_fb_ioctl: inode 0x%X file 0x%X p1 %d p2 %d\n", inode, file, p1, p2); EXIT(0); return 0; } int gpfs_make_request(request_queue_t *rq, int rw, struct buffer_head *bh) { ENTER(0); BUFHEAD_ERROR_IODONE(bh); EXIT(0); return 0; } int gpfs_block_init() { int rc; ENTER(0); GPFSFileSysMajorNumber = FS_MAJOR; retry: rc = register_blkdev(GPFSFileSysMajorNumber, "gpfs", &gpfs_bops); if (rc < 0) { TRACE2(TRACE_BOPS, 2, TRCID_BLOCK_011, "gpfs_block_init: unable to get major %d rc %d\n", GPFSFileSysMajorNumber, rc); /* If FS_MAJOR was already taken, register without specifying a major number (allow devfs_register_blkdev to choose an available one). */ if ((rc == -EBUSY) && (GPFSFileSysMajorNumber == FS_MAJOR)) { GPFSFileSysMajorNumber = 0; goto retry; } GPFSFileSysMajorNumber = 0; EXIT(0); return -1; } /* If devfs_register_blkdev chose the number, save it so we can properly unregister later. */ if (GPFSFileSysMajorNumber == 0) GPFSFileSysMajorNumber = rc; /* set up a null strategy routine */ blk_queue_make_request(BLK_DEFAULT_QUEUE(GPFSFileSysMajorNumber), gpfs_make_request); TRACE2(TRACE_BOPS, 2, TRCID_BLOCK_013, "gpfs_block_init: register_blkdev %d rc %d\n", GPFSFileSysMajorNumber, rc); EXIT(0); return 0; } void gpfs_block_clean() { int rc; ENTER(0); rc = unregister_blkdev(GPFSFileSysMajorNumber, "gpfs"); TRACE2(TRACE_BOPS, 2, TRCID_BLOCK_015, "gpfs_block_clean: unregister_blkdev %d rc %d\n", GPFSFileSysMajorNumber, rc); GPFSFileSysMajorNumber = 0; EXIT(0); } #endif /* LINUX_KERNEL_VERSION < 2050000 */