Whamcloud - gitweb
add special device inode lustre handler
authorwangdi <wangdi>
Fri, 21 Nov 2003 18:20:14 +0000 (18:20 +0000)
committerwangdi <wangdi>
Fri, 21 Nov 2003 18:20:14 +0000 (18:20 +0000)
lustre/llite/llite_internal.h
lustre/llite/special.c [new file with mode: 0644]

index 49ef45a..a57bcb6 100644 (file)
@@ -146,7 +146,6 @@ void ll_truncate(struct inode *inode);
 /* llite/file.c */
 extern struct file_operations ll_file_operations;
 extern struct inode_operations ll_file_inode_operations;
-extern struct inode_operations ll_special_inode_operations;
 extern int ll_inode_revalidate_it(struct dentry *, struct lookup_intent *);
 int ll_extent_lock(struct ll_file_data *, struct inode *,
                    struct lov_stripe_md *, int mode, struct ldlm_extent *,
@@ -159,11 +158,24 @@ int ll_extent_lock_no_validate(struct ll_file_data *, struct inode *,
                                struct lov_stripe_md *, int mode,
                                struct ldlm_extent *, struct lustre_handle *,
                                int ast_flags);
+
+int ll_local_open(struct file *file, struct lookup_intent *it);
+int ll_mdc_close(struct obd_export *mdc_exp, struct inode *inode, 
+                 struct file *file);
 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
 int ll_getattr(struct vfsmount *mnt, struct dentry *de,
                struct lookup_intent *it, struct kstat *stat);
 #endif
 
+/* llite/special.c */
+extern struct inode_operations ll_special_inode_operations;
+extern struct file_operations ll_special_chr_inode_fops;
+extern struct file_operations ll_special_chr_file_fops;
+extern struct file_operations ll_special_blk_inode_fops;
+extern struct file_operations ll_special_fifo_inode_fops;
+extern struct file_operations ll_special_fifo_file_fops;
+extern struct file_operations ll_special_sock_inode_fops;
+
 /* llite/dcache.c */
 void ll_intent_release(struct lookup_intent *);
 extern void ll_set_dd(struct dentry *de);
diff --git a/lustre/llite/special.c b/lustre/llite/special.c
new file mode 100644 (file)
index 0000000..aeb281b
--- /dev/null
@@ -0,0 +1,365 @@
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ *  Copyright (c) 2002, 2003 Cluster File Systems, Inc.
+ *   Author: Peter Braam <braam@clusterfs.com>
+ *   Author: Phil Schwan <phil@clusterfs.com>
+ *   Author: Andreas Dilger <adilger@clusterfs.com>
+ *
+ *   This file is part of Lustre, http://www.lustre.org.
+ *
+ *   Lustre is free software; you can redistribute it and/or
+ *   modify it under the terms of version 2 of the GNU General Public
+ *   License as published by the Free Software Foundation.
+ *
+ *   Lustre is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with Lustre; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define DEBUG_SUBSYSTEM S_LLITE
+#include <linux/lustre_lite.h>
+#include <linux/file.h>
+#include <asm/poll.h>
+#include "llite_internal.h"
+
+#define FILE_OPS 0 
+#define INODE_OPS 1 
+
+static inline struct file_operations** 
+get_save_fops(struct file* filp, int mode)
+{
+        struct inode *inode = filp->f_dentry->d_inode;
+        struct ll_inode_info *lli = ll_i2info(inode);
+        if (mode == FILE_OPS){
+                if (S_ISFIFO(inode->i_mode)){
+                        switch (filp->f_mode) {
+                        case 1: /*O_RDONLY*/
+                                return &(lli->ll_save_ffop);
+                        case 2: /*O_WRONLY*/
+                                return &(lli->ll_save_wfop);
+                        case 3: /* O_RDWR */
+                                return &(lli->ll_save_wrfop);
+                        default:
+                                return NULL;
+                        }
+                }
+                return &(lli->ll_save_ffop);
+        } else
+                return &(lli->ll_save_ifop);
+
+}
+                                          
+
+static inline void save_fops(struct file *filp, struct inode *inode,
+                             struct file_operations *sfops) 
+{
+        struct ll_inode_info *lli = ll_i2info(inode);
+        
+        if (sfops != filp->f_op) {
+                struct file_operations** pfop = get_save_fops (filp, FILE_OPS);
+                
+                *pfop = filp->f_op;
+                if (S_ISCHR(inode->i_mode)) {
+                        filp->f_op = &ll_special_chr_file_fops;
+                }else if (S_ISFIFO(inode->i_mode)){
+                        filp->f_op = &ll_special_fifo_file_fops;
+                }
+                filp->f_op->owner = lli->ll_save_ffop->owner; 
+        }
+}
+
+static ssize_t ll_special_file_read(struct file *filp, char *buf, 
+                                    size_t count, loff_t *ppos)
+{
+        struct file_operations** pfop = get_save_fops (filp, FILE_OPS);
+        int    rc = -EINVAL;
+
+        if (pfop && *pfop && (*pfop)->read) 
+                rc = (*pfop)->read(filp, buf, count, ppos);
+        
+        RETURN(rc);
+}
+
+static ssize_t ll_special_file_write(struct file *filp, const char *buf, 
+                                     size_t count, loff_t *ppos)
+{
+        struct file_operations** pfop = get_save_fops (filp, FILE_OPS);
+        int    rc = -EINVAL;
+        
+        if (pfop && *pfop && (*pfop)->write) 
+                rc = (*pfop)->write(filp, buf, count, ppos);
+        
+        RETURN(rc);
+}
+static int ll_special_file_ioctl(struct inode *inode, struct file *filp, 
+                                 unsigned int cmd, unsigned long arg)
+{
+        struct file_operations** pfop = get_save_fops (filp, FILE_OPS);
+        int    rc = -ENOTTY;
+
+        if (pfop && *pfop && (*pfop)->ioctl) { 
+                struct file_operations *sfops = filp->f_op;
+                
+                rc = (*pfop)->ioctl(inode, filp, cmd, arg);
+                save_fops(filp, inode, sfops);
+        }
+        RETURN(rc);
+}
+
+static loff_t ll_special_file_seek(struct file *filp, loff_t offset, int origin)
+{
+        struct file_operations** pfop = get_save_fops (filp, FILE_OPS);
+        int    rc = 0;
+
+        if (pfop && *pfop && (*pfop)->llseek)  
+                rc = (*pfop)->llseek(filp, offset, origin);
+        else
+                rc = default_llseek(filp, offset, origin);
+       
+        RETURN(rc);
+}
+
+
+#define DEFAULT_POLLMASK (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)
+
+static unsigned int
+ll_special_file_poll(struct file *filp, struct poll_table_struct *poll_table) 
+{
+        struct file_operations** pfop = get_save_fops (filp, FILE_OPS);
+        int    rc = DEFAULT_POLLMASK;
+
+        if (pfop && *pfop && (*pfop)->poll)  
+                rc = (*pfop)->poll(filp, poll_table);
+
+        RETURN(rc);
+}
+
+static int ll_special_file_open(struct inode *inode, struct file *filp)
+{
+        struct file_operations** pfop = get_save_fops (filp, FILE_OPS);
+        int rc = -EINVAL;
+
+        if (pfop && *pfop && (*pfop)->open)  
+                rc = (*pfop)->open(inode, filp);
+        
+        RETURN(rc);
+}
+
+static ssize_t ll_special_read(struct file *filp, char *buf, 
+                               size_t count, loff_t *ppos)
+{
+        struct file_operations** pfop = get_save_fops (filp, INODE_OPS);
+        int    rc = -EINVAL;
+
+        if (pfop && *pfop && (*pfop)->read)  
+                rc = (*pfop)->read(filp, buf, count, ppos);
+        
+        RETURN(rc);
+}
+
+static ssize_t ll_special_write(struct file *filp, const char *buf, 
+                                size_t count, loff_t *ppos)
+{
+        struct file_operations** pfop = get_save_fops (filp, INODE_OPS);
+        int    rc = -EINVAL;
+
+        if (pfop && *pfop && (*pfop)->write)  
+                rc = (*pfop)->write(filp, buf, count, ppos);
+        
+        RETURN(rc);
+}
+
+static int ll_special_ioctl(struct inode *inode, struct file *filp, 
+                            unsigned int cmd, unsigned long arg)
+{
+        struct file_operations** pfop = get_save_fops (filp, INODE_OPS);
+        int    rc = -ENOTTY;
+
+        if (pfop && *pfop && (*pfop)->ioctl) { 
+                struct file_operations *sfops = filp->f_op;
+                
+                rc = (*pfop)->ioctl(inode, filp, cmd, arg);
+                /* sometimes, file_operations will be changed in ioctl */
+                save_fops(filp, inode, sfops);
+        }
+
+        RETURN(rc);
+}
+
+static int ll_special_mmap(struct file * filp, struct vm_area_struct * vma)
+{
+        struct file_operations** pfop = get_save_fops (filp, INODE_OPS);
+        int    rc = -ENODEV;
+
+        if (pfop && *pfop && (*pfop)->mmap)  
+                rc = (*pfop)->mmap(filp, vma);
+        
+        RETURN(rc);
+}
+
+static loff_t ll_special_seek(struct file *filp, loff_t offset, int origin)
+{
+        struct file_operations** pfop = get_save_fops (filp, INODE_OPS);
+        int    rc = 0;
+
+        if (pfop && *pfop && (*pfop)->llseek)  
+                rc = (*pfop)->llseek(filp, offset, origin);
+        else
+                rc = default_llseek(filp, offset, origin);
+       
+        RETURN(rc);
+}
+
+static int ll_special_fsync(struct file *filp, struct dentry *dentry, int data)
+{
+        struct file_operations** pfop = get_save_fops (filp, INODE_OPS);
+        int    rc = -EINVAL;
+
+        if (pfop && *pfop && (*pfop)->fsync)  
+                rc = (*pfop)->fsync(filp, dentry, data);
+
+        RETURN(rc);
+}
+
+static int ll_special_file_fasync(int fd, struct file *filp, int on)
+{
+        struct file_operations** pfop = get_save_fops (filp, FILE_OPS);
+        int    rc = -EINVAL;
+
+        if (pfop && *pfop && (*pfop)->fasync)  
+                rc = (*pfop)->fasync(fd, filp, on);
+
+        RETURN(rc);
+}
+
+static int ll_special_open(struct inode *inode, struct file *filp)
+{
+        struct ptlrpc_request *req;
+        struct file_operations** pfop = get_save_fops (filp, INODE_OPS);
+        struct lookup_intent *it;
+        int rc = -EINVAL;
+        ENTRY;
+        
+        if (pfop && *pfop && (*pfop)->open) { 
+                struct file_operations *sfops = filp->f_op;
+                
+                rc = (*pfop)->open(inode, filp);
+                 /* sometimes the file_operations will be changed in open */
+                save_fops(filp, inode, sfops);
+        }
+        
+        lprocfs_counter_incr(ll_i2sbi(inode)->ll_stats, LPROC_LL_OPEN);
+        
+        it = filp->f_it;
+        
+        rc = ll_local_open(filp, it);
+        if (rc)
+                RETURN(rc);
+        req = it->d.lustre.it_data;
+        if (req)
+                ptlrpc_req_finished(req);
+        
+        RETURN(rc);
+}
+
+static int ll_special_release(struct inode *inode, struct file *filp)
+{
+       struct ll_sb_info *sbi = ll_i2sbi(inode);
+       struct file_operations** pfop = get_save_fops (filp, INODE_OPS);
+       int rc = 0, rc2 = 0;
+       ENTRY;
+
+        if (pfop && *pfop && (*pfop)->release) { 
+                rc = (*pfop)->release(inode, filp);
+        }
+        lprocfs_counter_incr(sbi->ll_stats, LPROC_LL_RELEASE);
+                
+        rc2 = ll_mdc_close(sbi->ll_mdc_exp, inode, filp);
+                
+        if (rc2 && !rc)
+                rc = rc2;
+        
+        RETURN(rc);
+}
+
+static int ll_special_file_release(struct inode *inode, struct file *filp)
+{
+        struct ll_sb_info *sbi = ll_i2sbi(inode);
+        struct file_operations** pfop = get_save_fops (filp, FILE_OPS);
+        int rc = 0, rc2 = 0;
+        ENTRY;
+
+        if (pfop && *pfop && (*pfop)->release) { 
+                rc = (*pfop)->release(inode, filp);
+        }
+        lprocfs_counter_incr(sbi->ll_stats, LPROC_LL_RELEASE);
+                
+        rc2 = ll_mdc_close(sbi->ll_mdc_exp, inode, filp);
+                
+        if (rc2 && !rc)
+               rc = rc2;
+
+        RETURN(rc);
+
+}
+
+struct inode_operations ll_special_inode_operations = {
+        setattr_raw:    ll_setattr_raw,
+        setattr:        ll_setattr,
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
+        getattr_it:     ll_getattr,
+#else
+        revalidate_it:  ll_inode_revalidate_it,
+#endif
+};
+
+struct file_operations ll_special_chr_inode_fops = {
+       open:           ll_special_open,
+};
+
+struct file_operations ll_special_blk_inode_fops = {
+        read:           ll_special_read,
+        write:          ll_special_write,
+        ioctl:          ll_special_ioctl,
+        open:           ll_special_open,
+        release:        ll_special_release,
+        mmap:           ll_special_mmap,
+        llseek:         ll_special_seek,
+        fsync:          ll_special_fsync,
+};
+
+struct file_operations ll_special_fifo_inode_fops = {
+        open:           ll_special_open,      
+};
+
+struct file_operations ll_special_sock_inode_fops = {
+        open:           ll_special_open
+};
+
+struct file_operations ll_special_chr_file_fops = {
+       llseek:         ll_special_file_seek,
+       read:           ll_special_file_read,
+       write:          ll_special_file_write,
+       poll:           ll_special_file_poll,
+       ioctl:          ll_special_file_ioctl,
+       open:           ll_special_file_open,
+       release:        ll_special_file_release,
+       fasync:         ll_special_file_fasync,
+};
+
+struct file_operations ll_special_fifo_file_fops = {
+       llseek:         ll_special_file_seek,
+       read:           ll_special_file_read,
+       write:          ll_special_file_write,
+       poll:           ll_special_file_poll,
+       ioctl:          ll_special_file_ioctl,
+       open:           ll_special_file_open,
+       release:        ll_special_file_release,
+};
+