Whamcloud - gitweb
- minor fixes in smfs to support raw lookups
[fs/lustre-release.git] / lustre / smfs / cache.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  lustre/smfs/cache.c
5  *  Lustre filesystem abstraction routines
6  *
7  *  Copyright (C) 2004 Cluster File Systems, Inc.
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 #define DEBUG_SUBSYSTEM S_SM
25
26 #include <linux/kmod.h>
27 #include <linux/init.h>
28 #include <linux/fs.h>
29 #include <linux/slab.h>
30 #include <linux/string.h>
31 #include <linux/lustre_idl.h>
32 #include <libcfs/list.h>
33 #include <linux/obd_class.h>
34 #include <linux/obd_support.h>
35 #include <linux/lustre_lib.h>
36 #include <linux/lustre_fsfilt.h>
37 #include <linux/lustre_smfs.h>
38
39 #include "smfs_internal.h"
40 int smfs_init_sm_ops(struct smfs_super_info *smb)
41 {
42         struct sm_operations    *sm_ops;   /*cache ops for set cache inode ops*/
43
44         OBD_ALLOC(sm_ops, sizeof(struct sm_operations));
45         if (!sm_ops)
46                 RETURN(-ENOMEM);
47
48         smb->sm_ops = sm_ops;
49         RETURN(0);
50 }
51
52 void smfs_cleanup_sm_ops(struct smfs_super_info *smb)
53 {
54         if (smb->sm_ops)
55                 OBD_FREE(smb->sm_ops, sizeof(struct sm_operations));
56 }
57
58 static void setup_iops(struct inode *cache_inode,
59                        struct inode_operations *iops,
60                        struct inode_operations *cache_iops)
61 {
62
63         if (cache_inode->i_op && cache_iops && iops) {
64                 if (cache_inode->i_op->create)
65                         iops->create = cache_iops->create;
66                 if (cache_inode->i_op->lookup)
67                         iops->lookup = cache_iops->lookup;
68                 if (cache_inode->i_op->link)
69                         iops->link = cache_iops->link;
70                 if (cache_inode->i_op->unlink)
71                         iops->unlink = cache_iops->unlink;
72                 if (cache_inode->i_op->symlink)
73                         iops->symlink = cache_iops->symlink;
74                 if (cache_inode->i_op->mkdir)
75                         iops->mkdir = cache_iops->mkdir;
76                 if (cache_inode->i_op->rmdir)
77                         iops->rmdir = cache_iops->rmdir;
78                 if (cache_inode->i_op->mknod)
79                         iops->mknod = cache_iops->mknod;
80                 if (cache_inode->i_op->rename)
81                         iops->rename = cache_iops->rename;
82                 if (cache_inode->i_op->readlink)
83                         iops->readlink = cache_iops->readlink;
84                 if (cache_inode->i_op->follow_link)
85                         iops->follow_link = cache_iops->follow_link;
86                 if (cache_inode->i_op->truncate)
87                         iops->truncate = cache_iops->truncate;
88                 if (cache_inode->i_op->permission)
89                         iops->permission = cache_iops->permission;
90 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
91                 if (cache_inode->i_op->revalidate)
92                         iops->revalidate = cache_iops->revalidate;
93 #endif
94                 if (cache_inode->i_op->setattr)
95                         iops->setattr = cache_iops->setattr;
96                 if (cache_inode->i_op->getattr)
97                         iops->getattr = cache_iops->getattr;
98                 if (cache_inode->i_op->setxattr)
99                         iops->setxattr = cache_iops->setxattr;
100                 if (cache_inode->i_op->getxattr)
101                         iops->getxattr = cache_iops->getxattr;
102                 if (cache_inode->i_op->listxattr)
103                         iops->listxattr = cache_iops->listxattr;
104                 if (cache_inode->i_op->removexattr)
105                         iops->removexattr = cache_iops->removexattr;
106 #if HAVE_LOOKUP_RAW
107                 if (cache_inode->i_op->lookup_raw)
108                         iops->lookup_raw = cache_iops->lookup_raw;
109 #endif
110         }
111 }
112
113 static void setup_fops(struct inode *cache_inode,
114                        struct file_operations *fops,
115                        struct file_operations *cache_fops)
116 {
117         if (cache_inode->i_fop && cache_fops && fops) {
118                 if (cache_inode->i_fop->llseek)
119                         fops->llseek = cache_fops->llseek;
120                 if (cache_inode->i_fop->read)
121                         fops->read = cache_fops->read;
122                 if (cache_inode->i_fop->write)
123                         fops->write = cache_fops->write;
124                 if (cache_inode->i_fop->readdir)
125                         fops->readdir = cache_fops->readdir;
126                 if (cache_inode->i_fop->poll)
127                         fops->poll = cache_fops->poll;
128                 if (cache_inode->i_fop->ioctl)
129                         fops->ioctl = cache_fops->ioctl;
130                 if (cache_inode->i_fop->mmap)
131                         fops->mmap = cache_fops->mmap;
132                 if (cache_inode->i_fop->flush)
133                         fops->flush = cache_fops->flush;
134                 if (cache_inode->i_fop->fsync)
135                         fops->fsync = cache_fops->fsync;
136                 if (cache_inode->i_fop->fasync)
137                         fops->fasync = cache_fops->fasync;
138                 if (cache_inode->i_fop->lock)
139                         fops->lock = cache_fops->lock;
140                 if (cache_inode->i_fop->readv)
141                         fops->readv = cache_fops->readv;
142                 if (cache_inode->i_fop->writev)
143                         fops->writev = cache_fops->writev;
144                 if (cache_inode->i_fop->sendpage)
145                         fops->sendpage = cache_fops->sendpage;
146                 if (cache_inode->i_fop->get_unmapped_area)
147                         fops->get_unmapped_area = cache_fops->get_unmapped_area;
148
149                 /* for dir file we also need replace the open and release method,
150                  * because we need initialize the cache file structs. */
151                 fops->open = cache_fops->open;
152                 fops->release = cache_fops->release;
153         }
154 }
155
156 static void setup_sm_file_ops(struct inode *cache_inode, struct inode *inode,
157                               struct inode_operations *cache_iops,
158                               struct file_operations *cache_fops)
159 {
160         struct smfs_super_info *smb;
161         struct inode_operations *iops;
162         struct file_operations *fops;
163
164         smb = S2SMI(inode->i_sb);
165
166         if (smb->smsi_ops_check & FILE_OPS_CHECK)
167                 return;
168
169         iops = cache_fiops(smb);
170         fops = cache_ffops(smb);
171
172         setup_iops(cache_inode, iops, cache_iops);
173         setup_fops(cache_inode, fops, cache_fops);
174
175         lock_kernel();
176         smb->smsi_ops_check |= FILE_OPS_CHECK;
177         unlock_kernel();
178 }
179
180 static void setup_sm_dir_ops(struct inode *cache_inode, struct inode *inode,
181                              struct inode_operations *cache_dir_iops,
182                              struct file_operations *cache_dir_fops)
183 {
184         struct smfs_super_info *smb;
185         struct inode_operations *iops;
186         struct file_operations *fops;
187
188         smb = S2SMI(inode->i_sb);
189
190         if (smb->smsi_ops_check & DIR_OPS_CHECK)
191                 return;
192
193         iops = cache_diops(smb);
194         fops = cache_dfops(smb);
195
196         setup_iops(cache_inode, iops, cache_dir_iops);
197         setup_fops(cache_inode, fops, cache_dir_fops);
198
199         lock_kernel();
200         smb->smsi_ops_check |= DIR_OPS_CHECK;
201         unlock_kernel();
202 }
203
204 static void setup_sm_symlink_ops(struct inode *cache_inode, struct inode *inode,
205                                  struct inode_operations *cache_sym_iops,
206                                  struct file_operations *cache_sym_fops)
207 {
208         struct smfs_super_info *smb;
209         struct inode_operations *iops;
210         struct file_operations *fops;
211
212         smb = S2SMI(inode->i_sb);
213
214         if (smb->smsi_ops_check & SYMLINK_OPS_CHECK)
215                 return;
216
217         iops = cache_siops(smb);
218         fops = cache_sfops(smb);
219
220         setup_iops(cache_inode, iops, cache_sym_iops);
221         setup_fops(cache_inode, fops, cache_sym_fops);
222
223         lock_kernel();
224         smb->smsi_ops_check |= SYMLINK_OPS_CHECK;
225         unlock_kernel();
226 }
227
228
229 void sm_set_inode_ops(struct inode *cache_inode, struct inode *inode)
230 {
231         struct smfs_super_info *smb = S2SMI(inode->i_sb);
232
233         /* XXX now set the correct sm_{file,dir,sym}_iops */
234         if (S_ISDIR(inode->i_mode)) {
235                 setup_sm_dir_ops(cache_inode, inode,
236                                  &smfs_dir_iops,
237                                  &smfs_dir_fops);
238                 inode->i_op = cache_diops(smb);
239                 inode->i_fop = cache_dfops(smb);
240         } else if (S_ISREG(inode->i_mode)) {
241                 setup_sm_file_ops(cache_inode, inode,
242                                   &smfs_file_iops,
243                                   &smfs_file_fops);
244                 CDEBUG(D_INODE, "inode %lu, i_op at %p\n",
245                        inode->i_ino, inode->i_op);
246                 inode->i_fop = cache_ffops(smb);
247                 inode->i_op = cache_fiops(smb);
248
249         } else if (S_ISLNK(inode->i_mode)) {
250                 setup_sm_symlink_ops(cache_inode, inode,
251                                      &smfs_sym_iops,
252                                      &smfs_sym_fops);
253                 inode->i_op = cache_siops(smb);
254                 inode->i_fop = cache_sfops(smb);
255                 CDEBUG(D_INODE, "inode %lu, i_op at %p\n",
256                        inode->i_ino, inode->i_op);
257         }
258 }
259
260
261 void sm_set_sb_ops(struct super_block *cache_sb, struct super_block *sb)
262 {
263         struct smfs_super_info *smb = S2SMI(sb);
264         struct super_operations *sops = &smb->sm_ops->sm_sb_ops;
265         struct super_operations *smfs_sops = &smfs_super_ops;
266         ENTRY;
267
268         if (smb->smsi_ops_check & SB_OPS_CHECK)
269                 return;
270         
271         //set up only operations exist in backfs
272         memset(sops, 0, sizeof (struct super_operations));
273         if (cache_sb->s_op) {
274                 if (cache_sb->s_op->dirty_inode)
275                         sops->dirty_inode = smfs_sops->dirty_inode;
276                 if (cache_sb->s_op->write_inode)
277                         sops->write_inode = smfs_sops->write_inode;
278                 if (cache_sb->s_op->put_super)
279                         sops->put_super = smfs_sops->put_super;
280                 if (cache_sb->s_op->write_super)
281                         sops->write_super = smfs_sops->write_super;
282                 if (cache_sb->s_op->write_super_lockfs)
283                         sops->write_super_lockfs = smfs_sops->write_super_lockfs;
284                 if (cache_sb->s_op->unlockfs)
285                         sops->unlockfs = smfs_sops->unlockfs;
286                 if (cache_sb->s_op->statfs)
287                         sops->statfs = smfs_sops->statfs;
288                 if (cache_sb->s_op->remount_fs)
289                         sops->remount_fs = smfs_sops->remount_fs;
290                 //if (cache_sb->s_op->umount_begin)
291                 //      sops->umount_begin = smfs_sops->umount_begin;
292
293 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
294                 if (cache_sb->s_op->fh_to_dentry)
295                         sops->fh_to_dentry = smfs_sops->fh_to_dentry;
296                 if (cache_sb->s_op->dentry_to_fh)
297                         sops->dentry_to_fh = smfs_sops->dentry_to_fh;
298                 if (cache_sb->s_op->show_options)
299                         sops->show_options = smfs_sops->show_options;
300                 
301                 sops->read_inode2 = smfs_sops->read_inode2;
302 #endif
303                 /* these ops are needed always */
304                 sops->clear_inode = smfs_sops->clear_inode;
305                 sops->delete_inode = smfs_sops->delete_inode;
306
307         }
308
309         lock_kernel();
310         smb->smsi_ops_check |= SB_OPS_CHECK;
311         unlock_kernel();
312         sb->s_op = sops;
313         return;
314 }
315
316