Whamcloud - gitweb
land v0.9.1 on HEAD, in preparation for a 1.0.x branch
[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                 
67                 *pfop = filp->f_op;
68                 if (S_ISCHR(inode->i_mode)) {
69                         filp->f_op = &ll_special_chr_file_fops;
70                 }else if (S_ISFIFO(inode->i_mode)){
71                         filp->f_op = &ll_special_fifo_file_fops;
72                 }
73                 filp->f_op->owner = lli->ll_save_ffop->owner; 
74         }
75 }
76
77 static ssize_t ll_special_file_read(struct file *filp, char *buf, 
78                                     size_t count, loff_t *ppos)
79 {
80         struct file_operations** pfop = get_save_fops (filp, FILE_OPS);
81         int    rc = -EINVAL;
82
83         if (pfop && *pfop && (*pfop)->read) 
84                 rc = (*pfop)->read(filp, buf, count, ppos);
85         
86         RETURN(rc);
87 }
88
89 static ssize_t ll_special_file_write(struct file *filp, const char *buf, 
90                                      size_t count, loff_t *ppos)
91 {
92         struct file_operations** pfop = get_save_fops (filp, FILE_OPS);
93         int    rc = -EINVAL;
94         
95         if (pfop && *pfop && (*pfop)->write) 
96                 rc = (*pfop)->write(filp, buf, count, ppos);
97         
98         RETURN(rc);
99 }
100 static int ll_special_file_ioctl(struct inode *inode, struct file *filp, 
101                                  unsigned int cmd, unsigned long arg)
102 {
103         struct file_operations** pfop = get_save_fops (filp, FILE_OPS);
104         int    rc = -ENOTTY;
105
106         if (pfop && *pfop && (*pfop)->ioctl) { 
107                 struct file_operations *sfops = filp->f_op;
108                 
109                 rc = (*pfop)->ioctl(inode, filp, cmd, arg);
110                 save_fops(filp, inode, sfops);
111         }
112         RETURN(rc);
113 }
114
115 static loff_t ll_special_file_seek(struct file *filp, loff_t offset, int origin)
116 {
117         struct file_operations** pfop = get_save_fops (filp, FILE_OPS);
118         int    rc = 0;
119
120         if (pfop && *pfop && (*pfop)->llseek)  
121                 rc = (*pfop)->llseek(filp, offset, origin);
122         else
123                 rc = default_llseek(filp, offset, origin);
124        
125         RETURN(rc);
126 }
127
128
129 #define DEFAULT_POLLMASK (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)
130
131 static unsigned int
132 ll_special_file_poll(struct file *filp, struct poll_table_struct *poll_table) 
133 {
134         struct file_operations** pfop = get_save_fops (filp, FILE_OPS);
135         int    rc = DEFAULT_POLLMASK;
136
137         if (pfop && *pfop && (*pfop)->poll)  
138                 rc = (*pfop)->poll(filp, poll_table);
139
140         RETURN(rc);
141 }
142
143 static int ll_special_file_open(struct inode *inode, struct file *filp)
144 {
145         struct file_operations** pfop = get_save_fops (filp, FILE_OPS);
146         int rc = -EINVAL;
147
148         if (pfop && *pfop && (*pfop)->open)  
149                 rc = (*pfop)->open(inode, filp);
150         
151         RETURN(rc);
152 }
153
154 static ssize_t ll_special_read(struct file *filp, char *buf, 
155                                size_t count, loff_t *ppos)
156 {
157         struct file_operations** pfop = get_save_fops (filp, INODE_OPS);
158         int    rc = -EINVAL;
159
160         if (pfop && *pfop && (*pfop)->read)  
161                 rc = (*pfop)->read(filp, buf, count, ppos);
162         
163         RETURN(rc);
164 }
165
166 static ssize_t ll_special_write(struct file *filp, const char *buf, 
167                                 size_t count, loff_t *ppos)
168 {
169         struct file_operations** pfop = get_save_fops (filp, INODE_OPS);
170         int    rc = -EINVAL;
171
172         if (pfop && *pfop && (*pfop)->write)  
173                 rc = (*pfop)->write(filp, buf, count, ppos);
174         
175         RETURN(rc);
176 }
177
178 static int ll_special_ioctl(struct inode *inode, struct file *filp, 
179                             unsigned int cmd, unsigned long arg)
180 {
181         struct file_operations** pfop = get_save_fops (filp, INODE_OPS);
182         int    rc = -ENOTTY;
183
184         if (pfop && *pfop && (*pfop)->ioctl) { 
185                 struct file_operations *sfops = filp->f_op;
186                 
187                 rc = (*pfop)->ioctl(inode, filp, cmd, arg);
188                 /* sometimes, file_operations will be changed in ioctl */
189                 save_fops(filp, inode, sfops);
190         }
191
192         RETURN(rc);
193 }
194
195 static int ll_special_mmap(struct file * filp, struct vm_area_struct * vma)
196 {
197         struct file_operations** pfop = get_save_fops (filp, INODE_OPS);
198         int    rc = -ENODEV;
199
200         if (pfop && *pfop && (*pfop)->mmap)  
201                 rc = (*pfop)->mmap(filp, vma);
202         
203         RETURN(rc);
204 }
205
206 static loff_t ll_special_seek(struct file *filp, loff_t offset, int origin)
207 {
208         struct file_operations** pfop = get_save_fops (filp, INODE_OPS);
209         int    rc = 0;
210
211         if (pfop && *pfop && (*pfop)->llseek)  
212                 rc = (*pfop)->llseek(filp, offset, origin);
213         else
214                 rc = default_llseek(filp, offset, origin);
215        
216         RETURN(rc);
217 }
218
219 static int ll_special_fsync(struct file *filp, struct dentry *dentry, int data)
220 {
221         struct file_operations** pfop = get_save_fops (filp, INODE_OPS);
222         int    rc = -EINVAL;
223
224         if (pfop && *pfop && (*pfop)->fsync)  
225                 rc = (*pfop)->fsync(filp, dentry, data);
226
227         RETURN(rc);
228 }
229
230 static int ll_special_file_fasync(int fd, struct file *filp, int on)
231 {
232         struct file_operations** pfop = get_save_fops (filp, FILE_OPS);
233         int    rc = -EINVAL;
234
235         if (pfop && *pfop && (*pfop)->fasync)  
236                 rc = (*pfop)->fasync(fd, filp, on);
237
238         RETURN(rc);
239 }
240
241 static int ll_special_open(struct inode *inode, struct file *filp)
242 {
243         struct ptlrpc_request *req;
244         struct file_operations** pfop = get_save_fops (filp, INODE_OPS);
245         struct lookup_intent *it;
246         int rc = -EINVAL;
247         ENTRY;
248         
249         if (pfop && *pfop && (*pfop)->open) { 
250                 struct file_operations *sfops = filp->f_op;
251                 
252                 rc = (*pfop)->open(inode, filp);
253                  /* sometimes the file_operations will be changed in open */
254                 save_fops(filp, inode, sfops);
255         }
256         
257         lprocfs_counter_incr(ll_i2sbi(inode)->ll_stats, LPROC_LL_OPEN);
258         
259         it = filp->f_it;
260         
261         rc = ll_local_open(filp, it);
262         if (rc)
263                 RETURN(rc);
264         req = it->d.lustre.it_data;
265         if (req)
266                 ptlrpc_req_finished(req);
267         
268         RETURN(rc);
269 }
270
271 static int ll_special_release(struct inode *inode, struct file *filp)
272 {
273        struct ll_sb_info *sbi = ll_i2sbi(inode);
274        struct file_operations** pfop = get_save_fops (filp, INODE_OPS);
275        int rc = 0, rc2 = 0;
276        ENTRY;
277
278         if (pfop && *pfop && (*pfop)->release) { 
279                 rc = (*pfop)->release(inode, filp);
280         }
281         lprocfs_counter_incr(sbi->ll_stats, LPROC_LL_RELEASE);
282                 
283         rc2 = ll_mdc_close(sbi->ll_mdc_exp, inode, filp);
284                 
285         if (rc2 && !rc)
286                 rc = rc2;
287         
288         RETURN(rc);
289 }
290
291 static int ll_special_file_release(struct inode *inode, struct file *filp)
292 {
293         struct ll_sb_info *sbi = ll_i2sbi(inode);
294         struct file_operations** pfop = get_save_fops (filp, FILE_OPS);
295         int rc = 0, rc2 = 0;
296         ENTRY;
297
298         if (pfop && *pfop && (*pfop)->release) { 
299                 rc = (*pfop)->release(inode, filp);
300         }
301         lprocfs_counter_incr(sbi->ll_stats, LPROC_LL_RELEASE);
302                 
303         rc2 = ll_mdc_close(sbi->ll_mdc_exp, inode, filp);
304                 
305         if (rc2 && !rc)
306                rc = rc2;
307
308         RETURN(rc);
309
310 }
311
312 struct inode_operations ll_special_inode_operations = {
313         setattr_raw:    ll_setattr_raw,
314         setattr:        ll_setattr,
315 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
316         getattr_it:     ll_getattr,
317 #else
318         revalidate_it:  ll_inode_revalidate_it,
319 #endif
320 };
321
322 struct file_operations ll_special_chr_inode_fops = {
323        open:           ll_special_open,
324 };
325
326 struct file_operations ll_special_blk_inode_fops = {
327         read:           ll_special_read,
328         write:          ll_special_write,
329         ioctl:          ll_special_ioctl,
330         open:           ll_special_open,
331         release:        ll_special_release,
332         mmap:           ll_special_mmap,
333         llseek:         ll_special_seek,
334         fsync:          ll_special_fsync,
335 };
336
337 struct file_operations ll_special_fifo_inode_fops = {
338         open:           ll_special_open,      
339 };
340
341 struct file_operations ll_special_sock_inode_fops = {
342         open:           ll_special_open
343 };
344
345 struct file_operations ll_special_chr_file_fops = {
346         llseek:         ll_special_file_seek,
347         read:           ll_special_file_read,
348         write:          ll_special_file_write,
349         poll:           ll_special_file_poll,
350         ioctl:          ll_special_file_ioctl,
351         open:           ll_special_file_open,
352         release:        ll_special_file_release,
353         fasync:         ll_special_file_fasync,
354 };
355
356 struct file_operations ll_special_fifo_file_fops = {
357         llseek:         ll_special_file_seek,
358         read:           ll_special_file_read,
359         write:          ll_special_file_write,
360         poll:           ll_special_file_poll,
361         ioctl:          ll_special_file_ioctl,
362         open:           ll_special_file_open,
363         release:        ll_special_file_release,
364 };
365