1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Special file handling for Lustre.
6 * Copyright (c) 2002, 2003 Cluster File Systems, Inc.
7 * Author: Wang Di <wangdi@clusterfs.com>
8 * Author: Andreas Dilger <adilger@clusterfs.com>
10 * This file is part of Lustre, http://www.lustre.org.
12 * Lustre is free software; you can redistribute it and/or
13 * modify it under the terms of version 2 of the GNU General Public
14 * License as published by the Free Software Foundation.
16 * Lustre is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with Lustre; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #define DEBUG_SUBSYSTEM S_LLITE
27 #include <linux/lustre_dlm.h>
28 #include <linux/lustre_lite.h>
29 #include <linux/pagemap.h>
30 #include <linux/file.h>
31 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
32 #include <linux/lustre_compat25.h>
35 #include "llite_internal.h"
40 static struct file_operations **get_save_fops(struct file* filp, int mode)
42 struct inode *inode = filp->f_dentry->d_inode;
43 struct ll_inode_info *lli = ll_i2info(inode);
45 if (mode == INODE_OPS) {
46 return &(lli->ll_save_ifop);
47 } else if (mode == FILE_OPS) {
48 if (S_ISFIFO(inode->i_mode)) {
49 switch (filp->f_mode) {
51 return &(lli->ll_save_ffop);
53 return &(lli->ll_save_wfop);
55 return &(lli->ll_save_wrfop);
60 return &(lli->ll_save_ffop);
62 CERROR("invalid special file ops %d\n", mode);
68 static void save_fops(struct file *filp, struct inode *inode,
69 struct file_operations *sfops)
71 if (sfops != filp->f_op) {
72 struct file_operations **pfop = get_save_fops(filp, FILE_OPS);
75 if (S_ISCHR(inode->i_mode))
76 filp->f_op = &ll_special_chr_file_fops;
77 else if (S_ISFIFO(inode->i_mode))
78 filp->f_op = &ll_special_fifo_file_fops;
80 CDEBUG(D_INFO,"saved %p, replaced with %p\n", *pfop,filp->f_op);
82 CDEBUG(D_INFO,"%p has owner %p\n",*pfop,(*pfop)->owner);
86 static ssize_t ll_special_file_read(struct file *filp, char *buf,
87 size_t count, loff_t *ppos)
89 struct file_operations **pfop = get_save_fops(filp, FILE_OPS);
92 if (pfop && *pfop && (*pfop)->read)
93 rc = (*pfop)->read(filp, buf, count, ppos);
98 static ssize_t ll_special_file_write(struct file *filp, const char *buf,
99 size_t count, loff_t *ppos)
101 struct file_operations **pfop = get_save_fops(filp, FILE_OPS);
104 if (pfop && *pfop && (*pfop)->write)
105 rc = (*pfop)->write(filp, buf, count, ppos);
110 static int ll_special_file_ioctl(struct inode *inode, struct file *filp,
111 unsigned int cmd, unsigned long arg)
113 struct file_operations **pfop = get_save_fops(filp, FILE_OPS);
116 if (pfop && *pfop && (*pfop)->ioctl) {
117 struct file_operations *sfops = filp->f_op;
119 rc = (*pfop)->ioctl(inode, filp, cmd, arg);
120 save_fops(filp, inode, sfops);
125 static loff_t ll_special_file_seek(struct file *filp, loff_t offset, int origin)
127 struct file_operations **pfop = get_save_fops(filp, FILE_OPS);
130 if (pfop && *pfop && (*pfop)->llseek)
131 rc = (*pfop)->llseek(filp, offset, origin);
133 rc = default_llseek(filp, offset, origin);
139 #define DEFAULT_POLLMASK (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)
141 static unsigned int ll_special_file_poll(struct file *filp,
142 struct poll_table_struct *poll_table)
144 struct file_operations **pfop = get_save_fops(filp, FILE_OPS);
145 int rc = DEFAULT_POLLMASK;
147 if (pfop && *pfop && (*pfop)->poll)
148 rc = (*pfop)->poll(filp, poll_table);
153 static int ll_special_file_open(struct inode *inode, struct file *filp)
155 struct file_operations **pfop = get_save_fops(filp, FILE_OPS);
162 rc = (*pfop)->open(inode, filp);
171 static ssize_t ll_special_read(struct file *filp, char *buf, size_t count,
174 struct file_operations **pfop = get_save_fops(filp, INODE_OPS);
177 if (pfop && *pfop && (*pfop)->read)
178 rc = (*pfop)->read(filp, buf, count, ppos);
183 static ssize_t ll_special_write(struct file *filp, const char *buf,
184 size_t count, loff_t *ppos)
186 struct file_operations **pfop = get_save_fops(filp, INODE_OPS);
189 if (pfop && *pfop && (*pfop)->write)
190 rc = (*pfop)->write(filp, buf, count, ppos);
195 static int ll_special_ioctl(struct inode *inode, struct file *filp,
196 unsigned int cmd, unsigned long arg)
198 struct file_operations **pfop = get_save_fops(filp, INODE_OPS);
201 if (pfop && *pfop && (*pfop)->ioctl) {
202 struct file_operations *sfops = filp->f_op;
204 rc = (*pfop)->ioctl(inode, filp, cmd, arg);
206 /* sometimes, file_operations will be changed in ioctl */
207 save_fops(filp, inode, sfops);
213 static int ll_special_mmap(struct file * filp, struct vm_area_struct * vma)
215 struct file_operations **pfop = get_save_fops(filp, INODE_OPS);
218 if (pfop && *pfop && (*pfop)->mmap)
219 rc = (*pfop)->mmap(filp, vma);
224 static loff_t ll_special_seek(struct file *filp, loff_t offset, int origin)
226 struct file_operations** pfop = get_save_fops (filp, INODE_OPS);
229 if (pfop && *pfop && (*pfop)->llseek)
230 rc = (*pfop)->llseek(filp, offset, origin);
232 rc = default_llseek(filp, offset, origin);
237 static int ll_special_fsync(struct file *filp, struct dentry *dentry, int data)
239 struct file_operations **pfop = get_save_fops(filp, INODE_OPS);
242 if (pfop && *pfop && (*pfop)->fsync)
243 rc = (*pfop)->fsync(filp, dentry, data);
248 static int ll_special_file_fasync(int fd, struct file *filp, int on)
250 struct file_operations **pfop = get_save_fops(filp, FILE_OPS);
253 if (pfop && *pfop && (*pfop)->fasync)
254 rc = (*pfop)->fasync(fd, filp, on);
259 static int ll_special_release_internal(struct inode *inode, struct file *filp,
262 struct file_operations **pfop = get_save_fops(filp, mode);
263 struct ll_sb_info *sbi = ll_i2sbi(inode);
268 if ((*pfop)->release)
269 rc = (*pfop)->release(inode, filp);
273 lprocfs_counter_incr(sbi->ll_stats, LPROC_LL_RELEASE);
274 err = ll_mdc_close(sbi->ll_mdc_exp, inode, filp);
282 static int ll_special_open(struct inode *inode, struct file *filp)
284 struct file_operations **pfop = get_save_fops(filp, INODE_OPS);
285 struct file_operations *sfops = filp->f_op;
286 struct ptlrpc_request *req;
287 struct lookup_intent *it;
288 int rc = -EINVAL, err;
292 /* mostly we will have @def_blk_fops here and it is not in a
293 * module but we do this just to be sure. */
297 rc = (*pfop)->open(inode, filp);
301 else /* sometimes ops will be changed in open */
302 save_fops(filp, inode, sfops);
306 lprocfs_counter_incr(ll_i2sbi(inode)->ll_stats, LPROC_LL_OPEN);
310 err = ll_local_open(filp, it);
312 CERROR("error opening special file: rc %d\n", rc);
313 ll_mdc_close(ll_i2sbi(inode)->ll_mdc_exp, inode, filp);
316 if ((*pfop)->release)
317 (*pfop)->release(inode, filp);
323 req = it->d.lustre.it_data;
325 ptlrpc_req_finished(req);
330 static int ll_special_release(struct inode *inode, struct file *filp)
332 return ll_special_release_internal(inode, filp, INODE_OPS);
335 static int ll_special_file_release(struct inode *inode, struct file *filp)
337 return ll_special_release_internal(inode, filp, FILE_OPS);
340 struct inode_operations ll_special_inode_operations = {
341 .setattr_raw = ll_setattr_raw,
342 .setattr = ll_setattr,
343 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
344 .getattr_it = ll_getattr,
346 .revalidate_it = ll_inode_revalidate_it,
350 struct file_operations ll_special_chr_inode_fops = {
351 //FIXME .owner = THIS_MODULE,
352 .open = ll_special_open,
355 struct file_operations ll_special_blk_inode_fops = {
356 //FIXME .owner = THIS_MODULE,
357 .read = ll_special_read,
358 .write = ll_special_write,
359 .ioctl = ll_special_ioctl,
360 .open = ll_special_open,
361 .release = ll_special_release,
362 .mmap = ll_special_mmap,
363 .llseek = ll_special_seek,
364 .fsync = ll_special_fsync,
367 struct file_operations ll_special_fifo_inode_fops = {
368 //FIXME .owner = THIS_MODULE,
369 .open = ll_special_open,
372 struct file_operations ll_special_sock_inode_fops = {
373 //FIXME .owner = THIS_MODULE,
374 .open = ll_special_open
377 struct file_operations ll_special_chr_file_fops = {
378 //FIXME .owner = THIS_MODULE,
379 .llseek = ll_special_file_seek,
380 .read = ll_special_file_read,
381 .write = ll_special_file_write,
382 .poll = ll_special_file_poll,
383 .ioctl = ll_special_file_ioctl,
384 .open = ll_special_file_open,
385 .release = ll_special_file_release,
386 .fasync = ll_special_file_fasync,
389 struct file_operations ll_special_fifo_file_fops = {
390 //FIXME .owner = THIS_MODULE,
391 .llseek = ll_special_file_seek,
392 .read = ll_special_file_read,
393 .write = ll_special_file_write,
394 .poll = ll_special_file_poll,
395 .ioctl = ll_special_file_ioctl,
396 .open = ll_special_file_open,
397 .release = ll_special_file_release,