X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fllite%2Fspecial.c;h=46f2ab914daccde8744311c4d11a8b65d37e3d54;hb=f94cd862288805adfdd31c95ef788c7020c250e4;hp=35d60824ddaed7ee53ebd76a444947ecbbdc1e0e;hpb=dbebe02c53b039f384a2858edf009ed70b0fbde0;p=fs%2Flustre-release.git diff --git a/lustre/llite/special.c b/lustre/llite/special.c index 35d6082..46f2ab9 100644 --- a/lustre/llite/special.c +++ b/lustre/llite/special.c @@ -1,9 +1,10 @@ /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- * vim:expandtab:shiftwidth=8:tabstop=8: * + * Special file handling for Lustre. + * * Copyright (c) 2002, 2003 Cluster File Systems, Inc. - * Author: Peter Braam - * Author: Phil Schwan + * Author: Wang Di * Author: Andreas Dilger * * This file is part of Lustre, http://www.lustre.org. @@ -23,21 +24,28 @@ */ #define DEBUG_SUBSYSTEM S_LLITE +#include #include +#include #include +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) +#include +#endif #include #include "llite_internal.h" -#define FILE_OPS 0 -#define INODE_OPS 1 +#define INODE_OPS 1 +#define FILE_OPS 2 -static inline struct file_operations** -get_save_fops(struct file* filp, int mode) +static 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)){ + + if (mode == INODE_OPS) { + return &(lli->ll_save_ifop); + } else if (mode == FILE_OPS) { + if (S_ISFIFO(inode->i_mode)) { switch (filp->f_mode) { case 1: /*O_RDONLY*/ return &(lli->ll_save_ffop); @@ -50,64 +58,64 @@ get_save_fops(struct file* filp, int mode) } } return &(lli->ll_save_ffop); - } else - return &(lli->ll_save_ifop); - + } else { + CERROR("invalid special file ops %d\n", mode); + LBUG(); + return NULL; + } } - -static inline void save_fops(struct file *filp, struct inode *inode, - struct file_operations *sfops) +static 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); - struct module *save_module = NULL; + struct file_operations **pfop = get_save_fops(filp, FILE_OPS); - save_module = filp->f_op->owner; *pfop = filp->f_op; - if (S_ISCHR(inode->i_mode)) { + if (S_ISCHR(inode->i_mode)) filp->f_op = &ll_special_chr_file_fops; - }else if (S_ISFIFO(inode->i_mode)){ + else if (S_ISFIFO(inode->i_mode)) filp->f_op = &ll_special_fifo_file_fops; - } - filp->f_op->owner = save_module; + + CDEBUG(D_INFO,"saved %p, replaced with %p\n", *pfop,filp->f_op); + if ((*pfop)->owner) + CDEBUG(D_INFO,"%p has owner %p\n",*pfop,(*pfop)->owner); } } -static ssize_t ll_special_file_read(struct file *filp, char *buf, +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; + struct file_operations **pfop = get_save_fops(filp, FILE_OPS); + int rc = -EINVAL; - if (pfop && *pfop && (*pfop)->read) + 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, +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) + 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, + +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; + struct file_operations **pfop = get_save_fops(filp, FILE_OPS); + int rc = -ENOTTY; - if (pfop && *pfop && (*pfop)->ioctl) { + if (pfop && *pfop && (*pfop)->ioctl) { struct file_operations *sfops = filp->f_op; - + rc = (*pfop)->ioctl(inode, filp, cmd, arg); save_fops(filp, inode, sfops); } @@ -116,27 +124,27 @@ static int ll_special_file_ioctl(struct inode *inode, struct file *filp, 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; + struct file_operations **pfop = get_save_fops(filp, FILE_OPS); + int rc = 0; - if (pfop && *pfop && (*pfop)->llseek) + 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) +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; + struct file_operations **pfop = get_save_fops(filp, FILE_OPS); + int rc = DEFAULT_POLLMASK; - if (pfop && *pfop && (*pfop)->poll) + if (pfop && *pfop && (*pfop)->poll) rc = (*pfop)->poll(filp, poll_table); RETURN(rc); @@ -144,49 +152,57 @@ ll_special_file_poll(struct file *filp, struct poll_table_struct *poll_table) static int ll_special_file_open(struct inode *inode, struct file *filp) { - struct file_operations** pfop = get_save_fops (filp, FILE_OPS); + struct file_operations **pfop = get_save_fops(filp, FILE_OPS); int rc = -EINVAL; - if (pfop && *pfop && (*pfop)->open) - rc = (*pfop)->open(inode, filp); - + if (pfop && *pfop) { + fops_get(*pfop); + + if ((*pfop)->open) + rc = (*pfop)->open(inode, filp); + + if (rc) + fops_put(*pfop); + } + RETURN(rc); } -static ssize_t ll_special_read(struct file *filp, char *buf, - size_t count, loff_t *ppos) +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; + struct file_operations **pfop = get_save_fops(filp, INODE_OPS); + int rc = -EINVAL; - if (pfop && *pfop && (*pfop)->read) + 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, +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; + struct file_operations **pfop = get_save_fops(filp, INODE_OPS); + int rc = -EINVAL; - if (pfop && *pfop && (*pfop)->write) + 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, +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; + struct file_operations **pfop = get_save_fops(filp, INODE_OPS); + int rc = -ENOTTY; - if (pfop && *pfop && (*pfop)->ioctl) { + 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); } @@ -196,12 +212,12 @@ static int ll_special_ioctl(struct inode *inode, struct file *filp, 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; + struct file_operations **pfop = get_save_fops(filp, INODE_OPS); + int rc = -ENODEV; - if (pfop && *pfop && (*pfop)->mmap) + if (pfop && *pfop && (*pfop)->mmap) rc = (*pfop)->mmap(filp, vma); - + RETURN(rc); } @@ -210,20 +226,20 @@ 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) + 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; + struct file_operations **pfop = get_save_fops(filp, INODE_OPS); + int rc = -EINVAL; - if (pfop && *pfop && (*pfop)->fsync) + if (pfop && *pfop && (*pfop)->fsync) rc = (*pfop)->fsync(filp, dentry, data); RETURN(rc); @@ -231,137 +247,212 @@ static int ll_special_fsync(struct file *filp, struct dentry *dentry, int data) 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; + struct file_operations **pfop = get_save_fops(filp, FILE_OPS); + int rc = -EINVAL; - if (pfop && *pfop && (*pfop)->fasync) + if (pfop && *pfop && (*pfop)->fasync) rc = (*pfop)->fasync(fd, filp, on); RETURN(rc); } +static int ll_special_release_internal(struct inode *inode, struct file *filp, + int mode) +{ + struct file_operations **pfop = get_save_fops(filp, mode); + struct ll_sb_info *sbi = ll_i2sbi(inode); + int rc = 0, err; + ENTRY; + + if (pfop && *pfop) { + if ((*pfop)->release) + rc = (*pfop)->release(inode, filp); + fops_put(*pfop); + } + + lprocfs_counter_incr(sbi->ll_stats, LPROC_LL_RELEASE); + err = ll_md_close(sbi->ll_md_exp, inode, filp); + + if (err && rc == 0) + rc = err; + + RETURN(rc); +} + static int ll_special_open(struct inode *inode, struct file *filp) { + struct file_operations **pfop = get_save_fops(filp, INODE_OPS); + struct file_operations *sfops = filp->f_op; + struct ll_inode_info *lli = ll_i2info(inode); struct ptlrpc_request *req; - struct file_operations** pfop = get_save_fops (filp, INODE_OPS); struct lookup_intent *it; - int rc = -EINVAL; + int rc = -EINVAL, err; + struct obd_client_handle **och_p; + __u64 *och_usecount; 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); + + it = filp->f_it; + + if (LUSTRE_IT(it)->it_disposition) { + err = it_open_error(DISP_OPEN_OPEN, it); + if (err) + RETURN(err); } - + + if (pfop && *pfop) { + /* mostly we will have @def_blk_fops here and it is not in a + * module but we do this just to be sure. */ + fops_get(*pfop); + + if ((*pfop)->open) { + rc = (*pfop)->open(inode, filp); + + if (rc) + fops_put(*pfop); + else /* sometimes ops will be changed in open */ + save_fops(filp, inode, sfops); + } + } + + /* Let's see if we have file open on MDS already. */ + if (it->it_flags & FMODE_WRITE) { + och_p = &lli->lli_mds_write_och; + och_usecount = &lli->lli_open_fd_write_count; + } else if (it->it_flags & FMODE_EXEC) { + och_p = &lli->lli_mds_exec_och; + och_usecount = &lli->lli_open_fd_exec_count; + } else { + och_p = &lli->lli_mds_read_och; + och_usecount = &lli->lli_open_fd_read_count; + } + 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; + + down(&lli->lli_och_sem); + if (*och_p) { /* Open handle is present */ + if (LUSTRE_IT(it)->it_disposition) { + struct obd_client_handle *och; + /* Well, there's extra open request that we do not need, + let's close it somehow*/ + OBD_ALLOC(och, sizeof (struct obd_client_handle)); + if (!och) { + /* XXX We leak open fd and open OPEN connectioni + to server here */ + up(&lli->lli_och_sem); + RETURN(-ENOMEM); + } + ll_och_fill(inode, it, och); + /* ll_md_och_close() will free och */ + ll_md_och_close(ll_i2mdexp(inode), inode, och, 0, 0); + } + (*och_usecount)++; + + err = ll_local_open(filp, it, NULL); + } else { + LASSERT(*och_usecount == 0); + OBD_ALLOC(*och_p, sizeof (struct obd_client_handle)); + if (!*och_p) { + // XXX Same as above + up(&lli->lli_och_sem); + RETURN(-ENOMEM); + } + (*och_usecount)++; + + err = ll_local_open(filp, it, *och_p); + } + up(&lli->lli_och_sem); + + if (rc != 0) { + CERROR("error opening special file: rc %d\n", rc); + ll_md_close(ll_i2sbi(inode)->ll_md_exp, inode, filp); + } else if (err) { + if (pfop && *pfop) { + if ((*pfop)->release) + (*pfop)->release(inode, filp); + fops_put(*pfop); + } + rc = err; + } + + req = LUSTRE_IT(it)->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); + return ll_special_release_internal(inode, filp, INODE_OPS); } 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); - + return ll_special_release_internal(inode, filp, FILE_OPS); } struct inode_operations ll_special_inode_operations = { - setattr_raw: ll_setattr_raw, - setattr: ll_setattr, + .setattr = ll_setattr, #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) - getattr_it: ll_getattr, + .getattr = ll_getattr, #else - revalidate_it: ll_inode_revalidate_it, + .revalidate_it = ll_inode_revalidate_it, #endif + .setxattr = ll_setxattr, + .getxattr = ll_getxattr, + .listxattr = ll_listxattr, + .removexattr = ll_removexattr, + .permission = ll_inode_permission, + }; struct file_operations ll_special_chr_inode_fops = { - open: ll_special_open, + //FIXME .owner = THIS_MODULE, + .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, + //FIXME .owner = THIS_MODULE, + .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, + //FIXME .owner = THIS_MODULE, + .open = ll_special_open, }; struct file_operations ll_special_sock_inode_fops = { - open: ll_special_open + //FIXME .owner = THIS_MODULE, + .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, + //FIXME .owner = THIS_MODULE, + .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, + //FIXME .owner = THIS_MODULE, + .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, };