Whamcloud - gitweb
b:2316 Save the owner of f_op before replace it with llite special file operation
[fs/lustre-release.git] / lustre / llite / special.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Copyright (c) 2002, 2003 Cluster File Systems, Inc.
5  *   Author: Peter Braam <braam@clusterfs.com>
6  *   Author: Phil Schwan <phil@clusterfs.com>
7  *   Author: Andreas Dilger <adilger@clusterfs.com>
8  *
9  *   This file is part of Lustre, http://www.lustre.org.
10  *
11  *   Lustre is free software; you can redistribute it and/or
12  *   modify it under the terms of version 2 of the GNU General Public
13  *   License as published by the Free Software Foundation.
14  *
15  *   Lustre is distributed in the hope that it will be useful,
16  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *   GNU General Public License for more details.
19  *
20  *   You should have received a copy of the GNU General Public License
21  *   along with Lustre; if not, write to the Free Software
22  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  */
24
25 #define DEBUG_SUBSYSTEM S_LLITE
26 #include <linux/lustre_lite.h>
27 #include <linux/file.h>
28 #include <asm/poll.h>
29 #include "llite_internal.h"
30
31 #define FILE_OPS 0 
32 #define INODE_OPS 1 
33
34 static inline struct file_operations** 
35 get_save_fops(struct file* filp, int mode)
36 {
37         struct inode *inode = filp->f_dentry->d_inode;
38         struct ll_inode_info *lli = ll_i2info(inode);
39         if (mode == FILE_OPS){
40                 if (S_ISFIFO(inode->i_mode)){
41                         switch (filp->f_mode) {
42                         case 1: /*O_RDONLY*/
43                                 return &(lli->ll_save_ffop);
44                         case 2: /*O_WRONLY*/
45                                 return &(lli->ll_save_wfop);
46                         case 3: /* O_RDWR */
47                                 return &(lli->ll_save_wrfop);
48                         default:
49                                 return NULL;
50                         }
51                 }
52                 return &(lli->ll_save_ffop);
53         } else
54                 return &(lli->ll_save_ifop);
55
56 }
57                                           
58
59 static inline void save_fops(struct file *filp, struct inode *inode,
60                              struct file_operations *sfops) 
61 {
62         struct ll_inode_info *lli = ll_i2info(inode);
63         
64         if (sfops != filp->f_op) {
65                 struct file_operations** pfop = get_save_fops (filp, FILE_OPS);
66                 struct module   *save_module = NULL;
67
68                 save_module = filp->f_op->owner;
69                 *pfop = filp->f_op;
70                 if (S_ISCHR(inode->i_mode)) {
71                         filp->f_op = &ll_special_chr_file_fops;
72                 }else if (S_ISFIFO(inode->i_mode)){
73                         filp->f_op = &ll_special_fifo_file_fops;
74                 }
75                 filp->f_op->owner = save_module;
76         }
77 }
78
79 static ssize_t ll_special_file_read(struct file *filp, char *buf, 
80                                     size_t count, loff_t *ppos)
81 {
82         struct file_operations** pfop = get_save_fops (filp, FILE_OPS);
83         int    rc = -EINVAL;
84
85         if (pfop && *pfop && (*pfop)->read) 
86                 rc = (*pfop)->read(filp, buf, count, ppos);
87         
88         RETURN(rc);
89 }
90
91 static ssize_t ll_special_file_write(struct file *filp, const char *buf, 
92                                      size_t count, loff_t *ppos)
93 {
94         struct file_operations** pfop = get_save_fops (filp, FILE_OPS);
95         int    rc = -EINVAL;
96         
97         if (pfop && *pfop && (*pfop)->write) 
98                 rc = (*pfop)->write(filp, buf, count, ppos);
99         
100         RETURN(rc);
101 }
102 static int ll_special_file_ioctl(struct inode *inode, struct file *filp, 
103                                  unsigned int cmd, unsigned long arg)
104 {
105         struct file_operations** pfop = get_save_fops (filp, FILE_OPS);
106         int    rc = -ENOTTY;
107
108         if (pfop && *pfop && (*pfop)->ioctl) { 
109                 struct file_operations *sfops = filp->f_op;
110                 
111                 rc = (*pfop)->ioctl(inode, filp, cmd, arg);
112                 save_fops(filp, inode, sfops);
113         }
114         RETURN(rc);
115 }
116
117 static loff_t ll_special_file_seek(struct file *filp, loff_t offset, int origin)
118 {
119         struct file_operations** pfop = get_save_fops (filp, FILE_OPS);
120         int    rc = 0;
121
122         if (pfop && *pfop && (*pfop)->llseek)  
123                 rc = (*pfop)->llseek(filp, offset, origin);
124         else
125                 rc = default_llseek(filp, offset, origin);
126        
127         RETURN(rc);
128 }
129
130
131 #define DEFAULT_POLLMASK (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)
132
133 static unsigned int
134 ll_special_file_poll(struct file *filp, struct poll_table_struct *poll_table) 
135 {
136         struct file_operations** pfop = get_save_fops (filp, FILE_OPS);
137         int    rc = DEFAULT_POLLMASK;
138
139         if (pfop && *pfop && (*pfop)->poll)  
140                 rc = (*pfop)->poll(filp, poll_table);
141
142         RETURN(rc);
143 }
144
145 static int ll_special_file_open(struct inode *inode, struct file *filp)
146 {
147         struct file_operations** pfop = get_save_fops (filp, FILE_OPS);
148         int rc = -EINVAL;
149
150         if (pfop && *pfop && (*pfop)->open)  
151                 rc = (*pfop)->open(inode, filp);
152         
153         RETURN(rc);
154 }
155
156 static ssize_t ll_special_read(struct file *filp, char *buf, 
157                                size_t count, loff_t *ppos)
158 {
159         struct file_operations** pfop = get_save_fops (filp, INODE_OPS);
160         int    rc = -EINVAL;
161
162         if (pfop && *pfop && (*pfop)->read)  
163                 rc = (*pfop)->read(filp, buf, count, ppos);
164         
165         RETURN(rc);
166 }
167
168 static ssize_t ll_special_write(struct file *filp, const char *buf, 
169                                 size_t count, loff_t *ppos)
170 {
171         struct file_operations** pfop = get_save_fops (filp, INODE_OPS);
172         int    rc = -EINVAL;
173
174         if (pfop && *pfop && (*pfop)->write)  
175                 rc = (*pfop)->write(filp, buf, count, ppos);
176         
177         RETURN(rc);
178 }
179
180 static int ll_special_ioctl(struct inode *inode, struct file *filp, 
181                             unsigned int cmd, unsigned long arg)
182 {
183         struct file_operations** pfop = get_save_fops (filp, INODE_OPS);
184         int    rc = -ENOTTY;
185
186         if (pfop && *pfop && (*pfop)->ioctl) { 
187                 struct file_operations *sfops = filp->f_op;
188                 
189                 rc = (*pfop)->ioctl(inode, filp, cmd, arg);
190                 /* sometimes, file_operations will be changed in ioctl */
191                 save_fops(filp, inode, sfops);
192         }
193
194         RETURN(rc);
195 }
196
197 static int ll_special_mmap(struct file * filp, struct vm_area_struct * vma)
198 {
199         struct file_operations** pfop = get_save_fops (filp, INODE_OPS);
200         int    rc = -ENODEV;
201
202         if (pfop && *pfop && (*pfop)->mmap)  
203                 rc = (*pfop)->mmap(filp, vma);
204         
205         RETURN(rc);
206 }
207
208 static loff_t ll_special_seek(struct file *filp, loff_t offset, int origin)
209 {
210         struct file_operations** pfop = get_save_fops (filp, INODE_OPS);
211         int    rc = 0;
212
213         if (pfop && *pfop && (*pfop)->llseek)  
214                 rc = (*pfop)->llseek(filp, offset, origin);
215         else
216                 rc = default_llseek(filp, offset, origin);
217        
218         RETURN(rc);
219 }
220
221 static int ll_special_fsync(struct file *filp, struct dentry *dentry, int data)
222 {
223         struct file_operations** pfop = get_save_fops (filp, INODE_OPS);
224         int    rc = -EINVAL;
225
226         if (pfop && *pfop && (*pfop)->fsync)  
227                 rc = (*pfop)->fsync(filp, dentry, data);
228
229         RETURN(rc);
230 }
231
232 static int ll_special_file_fasync(int fd, struct file *filp, int on)
233 {
234         struct file_operations** pfop = get_save_fops (filp, FILE_OPS);
235         int    rc = -EINVAL;
236
237         if (pfop && *pfop && (*pfop)->fasync)  
238                 rc = (*pfop)->fasync(fd, filp, on);
239
240         RETURN(rc);
241 }
242
243 static int ll_special_open(struct inode *inode, struct file *filp)
244 {
245         struct ptlrpc_request *req;
246         struct file_operations** pfop = get_save_fops (filp, INODE_OPS);
247         struct lookup_intent *it;
248         int rc = -EINVAL;
249         ENTRY;
250         
251         if (pfop && *pfop && (*pfop)->open) { 
252                 struct file_operations *sfops = filp->f_op;
253                 
254                 rc = (*pfop)->open(inode, filp);
255                  /* sometimes the file_operations will be changed in open */
256                 save_fops(filp, inode, sfops);
257         }
258         
259         lprocfs_counter_incr(ll_i2sbi(inode)->ll_stats, LPROC_LL_OPEN);
260         
261         it = filp->f_it;
262         
263         rc = ll_local_open(filp, it);
264         if (rc)
265                 RETURN(rc);
266         req = it->d.lustre.it_data;
267         if (req)
268                 ptlrpc_req_finished(req);
269         
270         RETURN(rc);
271 }
272
273 static int ll_special_release(struct inode *inode, struct file *filp)
274 {
275        struct ll_sb_info *sbi = ll_i2sbi(inode);
276        struct file_operations** pfop = get_save_fops (filp, INODE_OPS);
277        int rc = 0, rc2 = 0;
278        ENTRY;
279
280         if (pfop && *pfop && (*pfop)->release) { 
281                 rc = (*pfop)->release(inode, filp);
282         }
283         lprocfs_counter_incr(sbi->ll_stats, LPROC_LL_RELEASE);
284                 
285         rc2 = ll_mdc_close(sbi->ll_mdc_exp, inode, filp);
286                 
287         if (rc2 && !rc)
288                 rc = rc2;
289         
290         RETURN(rc);
291 }
292
293 static int ll_special_file_release(struct inode *inode, struct file *filp)
294 {
295         struct ll_sb_info *sbi = ll_i2sbi(inode);
296         struct file_operations** pfop = get_save_fops (filp, FILE_OPS);
297         int rc = 0, rc2 = 0;
298         ENTRY;
299
300         if (pfop && *pfop && (*pfop)->release) { 
301                 rc = (*pfop)->release(inode, filp);
302         }
303         lprocfs_counter_incr(sbi->ll_stats, LPROC_LL_RELEASE);
304                 
305         rc2 = ll_mdc_close(sbi->ll_mdc_exp, inode, filp);
306                 
307         if (rc2 && !rc)
308                rc = rc2;
309
310         RETURN(rc);
311
312 }
313
314 struct inode_operations ll_special_inode_operations = {
315         setattr_raw:    ll_setattr_raw,
316         setattr:        ll_setattr,
317 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
318         getattr_it:     ll_getattr,
319 #else
320         revalidate_it:  ll_inode_revalidate_it,
321 #endif
322 };
323
324 struct file_operations ll_special_chr_inode_fops = {
325        open:           ll_special_open,
326 };
327
328 struct file_operations ll_special_blk_inode_fops = {
329         read:           ll_special_read,
330         write:          ll_special_write,
331         ioctl:          ll_special_ioctl,
332         open:           ll_special_open,
333         release:        ll_special_release,
334         mmap:           ll_special_mmap,
335         llseek:         ll_special_seek,
336         fsync:          ll_special_fsync,
337 };
338
339 struct file_operations ll_special_fifo_inode_fops = {
340         open:           ll_special_open,      
341 };
342
343 struct file_operations ll_special_sock_inode_fops = {
344         open:           ll_special_open
345 };
346
347 struct file_operations ll_special_chr_file_fops = {
348         llseek:         ll_special_file_seek,
349         read:           ll_special_file_read,
350         write:          ll_special_file_write,
351         poll:           ll_special_file_poll,
352         ioctl:          ll_special_file_ioctl,
353         open:           ll_special_file_open,
354         release:        ll_special_file_release,
355         fasync:         ll_special_file_fasync,
356 };
357
358 struct file_operations ll_special_fifo_file_fops = {
359         llseek:         ll_special_file_seek,
360         read:           ll_special_file_read,
361         write:          ll_special_file_write,
362         poll:           ll_special_file_poll,
363         ioctl:          ll_special_file_ioctl,
364         open:           ll_special_file_open,
365         release:        ll_special_file_release,
366 };
367