From 70d59aaece7c40430dc4eab5fe231f56bd0d7648 Mon Sep 17 00:00:00 2001 From: wangdi Date: Fri, 21 Nov 2003 18:20:14 +0000 Subject: [PATCH] add special device inode lustre handler --- lustre/llite/llite_internal.h | 14 +- lustre/llite/special.c | 365 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 378 insertions(+), 1 deletion(-) create mode 100644 lustre/llite/special.c diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h index 49ef45a..a57bcb6 100644 --- a/lustre/llite/llite_internal.h +++ b/lustre/llite/llite_internal.h @@ -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 index 0000000..aeb281b --- /dev/null +++ b/lustre/llite/special.c @@ -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 + * Author: Phil Schwan + * Author: Andreas Dilger + * + * 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 +#include +#include +#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, +}; + -- 1.8.3.1