Whamcloud - gitweb
landing smfs.
[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  *  Copyright (C) 2004 Cluster File Systems, Inc.
5  *
6  *   This file is part of Lustre, http://www.lustre.org.
7  *
8  *   Lustre is free software; you can redistribute it and/or
9  *   modify it under the terms of version 2 of the GNU General Public
10  *   License as published by the Free Software Foundation.
11  *
12  *   Lustre is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with Lustre; if not, write to the Free Software
19  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  *
21  */
22
23 #define DEBUG_SUBSYSTEM S_SM
24
25 #include <linux/kmod.h>
26 #include <linux/init.h>
27 #include <linux/fs.h>
28 #include <linux/slab.h>
29 #include <linux/string.h>
30 #include <linux/lustre_idl.h>
31 #include <portals/list.h>
32 #include <linux/obd_class.h>
33 #include <linux/obd_support.h>
34 #include <linux/lustre_lib.h>
35 #include <linux/lustre_smfs.h>
36
37 #include "smfs_internal.h"
38 int smfs_init_sm_ops(struct smfs_super_info *smb)
39 {
40         struct sm_operations    *sm_ops;   /*cache ops for set cache inode ops*/
41
42         OBD_ALLOC(sm_ops, sizeof(struct sm_operations));
43         if (!sm_ops)
44                 RETURN(-ENOMEM);
45
46         smb->sm_ops = sm_ops;
47         RETURN(0);
48 }
49
50 void smfs_cleanup_sm_ops(struct smfs_super_info *smb)
51 {
52         if (smb->sm_ops)
53                 OBD_FREE(smb->sm_ops, sizeof(struct sm_operations));
54 }
55
56 static void setup_iops(struct inode *cache_inode,
57                        struct inode_operations *iops,
58                        struct inode_operations *cache_iops)
59 {
60
61         if (cache_inode->i_op && cache_iops && iops) {
62                 if (cache_inode->i_op->create)
63                         iops->create = cache_iops->create;
64 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
65                 if (cache_inode->i_op->create_it)
66                         iops->create_it = cache_iops->create_it;
67 #endif
68                 if (cache_inode->i_op->lookup)
69                         iops->lookup = cache_iops->lookup;
70 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
71                 if (cache_inode->i_op->lookup_raw)
72                         iops->lookup_raw = cache_iops->lookup_raw;
73                 if (cache_inode->i_op->lookup_it)
74                         iops->lookup_it = cache_iops->lookup_it;
75 #endif
76                 if (cache_inode->i_op->link)
77                         iops->link = cache_iops->link;
78                 if (cache_inode->i_op->link_raw)
79                         iops->link_raw = cache_iops->link_raw;
80                 if (cache_inode->i_op->unlink)
81                         iops->unlink = cache_iops->unlink;
82                 if (cache_inode->i_op->unlink_raw)
83                         iops->unlink_raw = cache_iops->unlink_raw;
84                 if (cache_inode->i_op->symlink)
85                         iops->symlink = cache_iops->symlink;
86                 if (cache_inode->i_op->symlink_raw)
87                         iops->symlink_raw = cache_iops->symlink_raw;
88                 if (cache_inode->i_op->mkdir)
89                         iops->mkdir = cache_iops->mkdir;
90                 if (cache_inode->i_op->mkdir_raw)
91                         iops->mkdir_raw = cache_iops->mkdir_raw;
92                 if (cache_inode->i_op->rmdir)
93                         iops->rmdir = cache_iops->rmdir;
94                 if (cache_inode->i_op->rmdir_raw)
95                         iops->rmdir_raw = cache_iops->rmdir_raw;
96                 if (cache_inode->i_op->mknod)
97                         iops->mknod = cache_iops->mknod;
98                 if (cache_inode->i_op->mknod_raw)
99                         iops->mknod_raw = cache_iops->mknod_raw;
100                 if (cache_inode->i_op->rename)
101                         iops->rename = cache_iops->rename;
102                 if (cache_inode->i_op->rename_raw)
103                         iops->rename_raw = cache_iops->rename_raw;
104                 if (cache_inode->i_op->readlink)
105                         iops->readlink = cache_iops->readlink;
106                 if (cache_inode->i_op->follow_link)
107                         iops->follow_link = cache_iops->follow_link;
108                 if (cache_inode->i_op->truncate)
109                         iops->truncate = cache_iops->truncate;
110                 if (cache_inode->i_op->permission)
111                         iops->permission = cache_iops->permission;
112 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
113                 if (cache_inode->i_op->revalidate)
114                         iops->revalidate = cache_iops->revalidate;
115                 if (cache_inode->i_op->revalidate_it)
116                         iops->revalidate_it = cache_iops->revalidate_it;
117 #endif
118                 if (cache_inode->i_op->setattr)
119                         iops->setattr = cache_iops->setattr;
120                 if (cache_inode->i_op->setattr_raw)
121                         iops->setattr_raw = cache_iops->setattr_raw;
122                 if (cache_inode->i_op->getattr)
123                         iops->getattr = cache_iops->getattr;
124                 if (cache_inode->i_op->setxattr)
125                         iops->setxattr = cache_iops->setxattr;
126                 if (cache_inode->i_op->getxattr)
127                         iops->getxattr = cache_iops->getxattr;
128                 if (cache_inode->i_op->listxattr)
129                         iops->listxattr = cache_iops->listxattr;
130                 if (cache_inode->i_op->removexattr)
131                         iops->removexattr = cache_iops->removexattr;
132         }
133 }
134
135 static void setup_fops(struct inode *cache_inode,
136                        struct file_operations *fops,
137                        struct file_operations *cache_fops)
138 {
139         if (cache_inode->i_fop && cache_fops && fops) {
140                 if (cache_inode->i_fop->llseek)
141                         fops->llseek = cache_fops->llseek;
142                 if (cache_inode->i_fop->read)
143                         fops->read = cache_fops->read;
144                 if (cache_inode->i_fop->write)
145                         fops->write = cache_fops->write;
146                 if (cache_inode->i_fop->readdir)
147                         fops->readdir = cache_fops->readdir;
148                 if (cache_inode->i_fop->poll)
149                         fops->poll = cache_fops->poll;
150                 if (cache_inode->i_fop->ioctl)
151                         fops->ioctl = cache_fops->ioctl;
152                 if (cache_inode->i_fop->mmap)
153                         fops->mmap = cache_fops->mmap;
154 //                if (cache_inode->i_fop->open)
155                         fops->open = cache_fops->open;
156                 if (cache_inode->i_fop->flush)
157                         fops->flush = cache_fops->flush;
158         //        if (cache_inode->i_fop->release)
159                         fops->release = cache_fops->release;
160                 if (cache_inode->i_fop->fsync)
161                         fops->fsync = cache_fops->fsync;
162                 if (cache_inode->i_fop->fasync)
163                         fops->fasync = cache_fops->fasync;
164                 if (cache_inode->i_fop->lock)
165                         fops->lock = cache_fops->lock;
166                 if (cache_inode->i_fop->readv)
167                         fops->readv = cache_fops->readv;
168                 if (cache_inode->i_fop->writev)
169                         fops->writev = cache_fops->writev;
170                 if (cache_inode->i_fop->sendpage)
171                         fops->sendpage = cache_fops->sendpage;
172                 if (cache_inode->i_fop->get_unmapped_area)
173                         fops->get_unmapped_area = cache_fops->get_unmapped_area;
174         }
175 }
176
177 static void setup_sm_file_ops(struct inode *cache_inode,
178                               struct inode *inode,
179                               struct inode_operations *cache_iops,
180                               struct file_operations *cache_fops)
181 {
182         struct smfs_super_info *smb;
183         struct inode_operations *iops;
184         struct file_operations *fops;
185
186         smb = S2SMI(inode->i_sb);
187
188         if (smb->ops_check & FILE_OPS_CHECK)
189                 return;
190         smb->ops_check |= FILE_OPS_CHECK;
191
192         iops = cache_fiops(smb);
193         fops = cache_ffops(smb);
194
195         memset(iops , 0 , sizeof (struct inode_operations));
196         memset(fops , 0 , sizeof (struct file_operations));
197
198         setup_iops(cache_inode, iops, cache_iops);
199         setup_fops(cache_inode, fops, cache_fops);
200
201         return;
202 }
203
204 static void setup_sm_dir_ops(struct inode *cache_inode,
205                              struct inode *inode,
206                              struct inode_operations *cache_dir_iops,
207                              struct file_operations *cache_dir_fops)
208 {
209         struct smfs_super_info *smb;
210         struct inode_operations *iops;
211         struct file_operations *fops;
212
213         smb = S2SMI(inode->i_sb);
214
215         if (smb->ops_check & DIR_OPS_CHECK)
216                 return;
217         smb->ops_check |= DIR_OPS_CHECK;
218
219         iops = cache_diops(smb);
220         fops = cache_dfops(smb);
221
222         memset(iops, 0, sizeof (struct inode_operations));
223         memset(fops, 0, sizeof (struct file_operations));
224
225         setup_iops(cache_inode, iops, cache_dir_iops);
226         setup_fops(cache_inode, fops, cache_dir_fops);
227
228         return;
229 }
230
231 static void setup_sm_symlink_ops(struct inode *cache_inode,
232                                  struct inode *inode,
233                                  struct inode_operations *cache_sym_iops,
234                                  struct file_operations *cache_sym_fops)
235 {
236         struct smfs_super_info *smb;
237         struct inode_operations *iops;
238         struct file_operations *fops;
239
240         smb = S2SMI(inode->i_sb);
241
242         if (smb->ops_check & SYMLINK_OPS_CHECK)
243                 return;
244         smb->ops_check |= SYMLINK_OPS_CHECK;
245
246         iops = cache_siops(smb);
247         fops = cache_sfops(smb);
248
249         memset(iops , 0 , sizeof (struct inode_operations));
250         memset(fops , 0 , sizeof (struct file_operations));
251
252         setup_iops(cache_inode, iops, cache_sym_iops);
253         setup_fops(cache_inode, fops, cache_sym_fops);
254
255         return;
256 }
257
258 static void setup_sm_sb_ops(struct super_block *cache_sb,
259                             struct super_block *sb,
260                             struct super_operations *smfs_sops)
261 {
262         struct smfs_super_info *smb;
263         struct super_operations *sops;
264
265         ENTRY;
266
267         smb = S2SMI(sb);
268
269         if (smb->ops_check & SB_OPS_CHECK)
270                 return;
271         smb->ops_check |= SB_OPS_CHECK;
272         sops = cache_sops(smb);
273         memset(sops, 0, sizeof (struct super_operations));
274
275         if (cache_sb->s_op) {
276                 if (cache_sb->s_op->read_inode)
277                         sops->read_inode = smfs_sops->read_inode;
278 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
279                 if (cache_sb->s_op->read_inode2)
280                         sops->read_inode2 = smfs_sops->read_inode2;
281 #endif
282                 if (cache_sb->s_op->dirty_inode)
283                         sops->dirty_inode = smfs_sops->dirty_inode;
284                 if (cache_sb->s_op->write_inode)
285                         sops->write_inode = smfs_sops->write_inode;
286                 if (cache_sb->s_op->put_inode)
287                         sops->put_inode = smfs_sops->put_inode;
288                 if (cache_sb->s_op->delete_inode)
289                         sops->delete_inode = smfs_sops->delete_inode;
290                 if (cache_sb->s_op->put_super)
291                         sops->put_super = smfs_sops->put_super;
292                 if (cache_sb->s_op->write_super)
293                         sops->write_super = smfs_sops->write_super;
294                 if (cache_sb->s_op->write_super_lockfs)
295                         sops->write_super_lockfs =smfs_sops->write_super_lockfs;
296                 if (cache_sb->s_op->unlockfs)
297                         sops->unlockfs = smfs_sops->unlockfs;
298                 if (cache_sb->s_op->statfs)
299                         sops->statfs = smfs_sops->statfs;
300                 if (cache_sb->s_op->remount_fs)
301                         sops->remount_fs = smfs_sops->remount_fs;
302                 if (cache_sb->s_op->umount_begin)
303                         sops->umount_begin = smfs_sops->umount_begin;
304 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
305                 if (cache_sb->s_op->fh_to_dentry)
306                         sops->fh_to_dentry = smfs_sops->fh_to_dentry;
307                 if (cache_sb->s_op->dentry_to_fh)
308                         sops->dentry_to_fh = smfs_sops->dentry_to_fh;
309 #endif
310                 if (cache_sb->s_op->show_options)
311                         sops->show_options = smfs_sops->show_options;
312                 
313                 /* FIXME-WANGDI: we need this method to clear the cache
314                  * inode. */
315                 sops->clear_inode = smfs_sops->clear_inode;
316         }
317
318         return;
319 }
320
321 void sm_set_inode_ops(struct inode *cache_inode, struct inode *inode)
322 {
323         struct smfs_super_info *smb = S2SMI(inode->i_sb);
324         /* XXX now set the correct sm_{file,dir,sym}_iops */
325         if (S_ISDIR(inode->i_mode)) {
326                        setup_sm_dir_ops(cache_inode, inode,
327                                  &smfs_dir_iops,
328                                  &smfs_dir_fops);
329                 inode->i_op = cache_diops(smb);
330                 inode->i_fop = cache_dfops(smb);
331         } else if (S_ISREG(inode->i_mode)) {
332                 setup_sm_file_ops(cache_inode, inode,
333                                   &smfs_file_iops,
334                                   &smfs_file_fops);
335                 CDEBUG(D_INODE, "inode %lu, i_op at %p\n",
336                        inode->i_ino, inode->i_op);
337                 inode->i_fop = cache_ffops(smb);
338                 inode->i_op = cache_fiops(smb);
339
340         } else if (S_ISLNK(inode->i_mode)) {
341                 setup_sm_symlink_ops(cache_inode, inode,
342                                      &smfs_sym_iops,
343                                      &smfs_sym_fops);
344                 inode->i_op = cache_siops(smb);
345                 inode->i_fop = cache_sfops(smb);
346                 CDEBUG(D_INODE, "inode %lu, i_op at %p\n",
347                        inode->i_ino, inode->i_op);
348         }
349 }
350
351 void sm_set_sb_ops(struct super_block *cache_sb, struct super_block *sb)
352 {
353         struct smfs_super_info *smb;
354
355         smb = S2SMI(sb);
356
357         setup_sm_sb_ops(cache_sb, sb, &smfs_super_ops);
358
359         sb->s_op = cache_sops(smb);
360         return;
361 }