Whamcloud - gitweb
current branches now use lnet from HEAD
[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 *smfs_iops,
60                        struct inode_operations *iops)
61 {
62
63         LASSERT(cache_inode->i_op && smfs_iops && iops);
64         
65         if (cache_inode->i_op->create)
66                 iops->create = smfs_iops->create;
67         if (cache_inode->i_op->lookup)
68                 iops->lookup = smfs_iops->lookup;
69         if (cache_inode->i_op->link)
70                 iops->link = smfs_iops->link;
71         if (cache_inode->i_op->unlink)
72                 iops->unlink = smfs_iops->unlink;
73         if (cache_inode->i_op->symlink)
74                 iops->symlink = smfs_iops->symlink;
75         if (cache_inode->i_op->mkdir)
76                 iops->mkdir = smfs_iops->mkdir;
77         if (cache_inode->i_op->rmdir)
78                 iops->rmdir = smfs_iops->rmdir;
79         if (cache_inode->i_op->mknod)
80                 iops->mknod = smfs_iops->mknod;
81         if (cache_inode->i_op->rename)
82                 iops->rename = smfs_iops->rename;
83         if (cache_inode->i_op->readlink)
84                 iops->readlink = smfs_iops->readlink;
85         if (cache_inode->i_op->follow_link)
86                 iops->follow_link = smfs_iops->follow_link;
87         if (cache_inode->i_op->truncate)
88                 iops->truncate = smfs_iops->truncate;
89         if (cache_inode->i_op->permission)
90                 iops->permission = smfs_iops->permission;
91 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
92         if (cache_inode->i_op->revalidate)
93                 iops->revalidate = smfs_iops->revalidate;
94 #endif
95         if (cache_inode->i_op->setattr)
96                 iops->setattr = smfs_iops->setattr;
97         if (cache_inode->i_op->getattr)
98                 iops->getattr = smfs_iops->getattr;
99         if (cache_inode->i_op->setxattr)
100                 iops->setxattr = smfs_iops->setxattr;
101         if (cache_inode->i_op->getxattr)
102                 iops->getxattr = smfs_iops->getxattr;
103         if (cache_inode->i_op->listxattr)
104                 iops->listxattr = smfs_iops->listxattr;
105         if (cache_inode->i_op->removexattr)
106                 iops->removexattr = smfs_iops->removexattr;
107 #if HAVE_LOOKUP_RAW
108         if (cache_inode->i_op->lookup_raw)
109                 iops->lookup_raw = smfs_iops->lookup_raw;
110 #endif
111
112 }
113
114 static void setup_fops(struct inode *cache_inode,
115                        struct file_operations *smfs_fops,
116                        struct file_operations *fops)
117 {
118         LASSERT(cache_inode->i_fop && smfs_fops && fops);
119         
120         if (cache_inode->i_fop->llseek)
121                 fops->llseek = smfs_fops->llseek;
122         if (cache_inode->i_fop->read)
123                 fops->read = smfs_fops->read;
124         if (cache_inode->i_fop->write)
125                 fops->write = smfs_fops->write;
126         if (cache_inode->i_fop->readdir)
127                 fops->readdir = smfs_fops->readdir;
128         if (cache_inode->i_fop->poll)
129                 fops->poll = smfs_fops->poll;
130         if (cache_inode->i_fop->ioctl)
131                 fops->ioctl = smfs_fops->ioctl;
132         if (cache_inode->i_fop->mmap)
133                 fops->mmap = smfs_fops->mmap;
134         if (cache_inode->i_fop->flush)
135                 fops->flush = smfs_fops->flush;
136         if (cache_inode->i_fop->fsync)
137                 fops->fsync = smfs_fops->fsync;
138         if (cache_inode->i_fop->fasync)
139                 fops->fasync = smfs_fops->fasync;
140         if (cache_inode->i_fop->lock)
141                 fops->lock = smfs_fops->lock;
142         if (cache_inode->i_fop->readv)
143                 fops->readv = smfs_fops->readv;
144         if (cache_inode->i_fop->writev)
145                 fops->writev = smfs_fops->writev;
146         if (cache_inode->i_fop->sendpage)
147                 fops->sendpage = smfs_fops->sendpage;
148         if (cache_inode->i_fop->get_unmapped_area)
149                 fops->get_unmapped_area = smfs_fops->get_unmapped_area;
150                 
151         /* for dir file we also need replace the open and release method,
152          * because we need initialize the cache file structs. */
153         fops->open = smfs_fops->open;
154         fops->release = smfs_fops->release;
155 }
156
157 static void setup_sm_file_ops(struct inode *inode)
158 {
159         struct smfs_super_info *smb = S2SMI(inode->i_sb);
160         struct inode *cache_inode = I2CI(inode);
161         
162         setup_iops(cache_inode, &smfs_file_iops, &smb->sm_ops->sm_file_iops);
163         setup_fops(cache_inode, &smfs_file_fops, &smb->sm_ops->sm_file_fops);
164
165         lock_kernel();
166         smb->smsi_ops_check |= FILE_OPS_CHECK;
167         unlock_kernel();
168 }
169
170 static void setup_sm_dir_ops(struct inode *inode)
171 {
172         struct smfs_super_info *smb = S2SMI(inode->i_sb);
173         struct inode *cache_inode = I2CI(inode);
174         
175         setup_iops(cache_inode, &smfs_dir_iops, &smb->sm_ops->sm_dir_iops);
176         setup_fops(cache_inode, &smfs_dir_fops, &smb->sm_ops->sm_dir_fops);
177
178         lock_kernel();
179         smb->smsi_ops_check |= DIR_OPS_CHECK;
180         unlock_kernel();
181 }
182
183 static void setup_sm_symlink_ops(struct inode *inode)
184 {
185         struct smfs_super_info *smb = S2SMI(inode->i_sb);
186         struct inode *cache_inode = I2CI(inode);
187         
188         setup_iops(cache_inode, &smfs_sym_iops, &smb->sm_ops->sm_sym_iops);
189         setup_fops(cache_inode, &smfs_sym_fops, &smb->sm_ops->sm_sym_fops);
190
191         lock_kernel();
192         smb->smsi_ops_check |= SYMLINK_OPS_CHECK;
193         unlock_kernel();
194 }
195
196 static void setup_sm_special_ops(struct inode *inode)
197 {
198         struct smfs_super_info *smb = S2SMI(inode->i_sb);
199         struct inode *cache_inode = I2CI(inode);
200         
201         setup_iops(cache_inode, &smfs_special_iops, &smb->sm_ops->sm_special_iops);
202
203         lock_kernel();
204         smb->smsi_ops_check |= SPECIAL_OPS_CHECK;
205         unlock_kernel();
206 }
207
208 void sm_set_inode_ops(struct inode *inode)
209 {
210         struct smfs_super_info *smb = S2SMI(inode->i_sb);
211
212         //iopen stuff
213         if (inode->i_ino == SMFS_IOPEN_INO) {
214                 inode->i_op = &smfs_iopen_iops;
215                 inode->i_fop = &smfs_iopen_fops;
216                 return;
217         }
218
219         /* set the correct sm_{file,dir,sym}_iops */
220         if (S_ISDIR(inode->i_mode)) {
221                 if (!(smb->smsi_ops_check & DIR_OPS_CHECK))
222                         setup_sm_dir_ops(inode);
223                 inode->i_op = &smb->sm_ops->sm_dir_iops;
224                 inode->i_fop = &smb->sm_ops->sm_dir_fops;   
225         } else if (S_ISREG(inode->i_mode)) {
226                 if (!(smb->smsi_ops_check & FILE_OPS_CHECK))
227                         setup_sm_file_ops(inode);
228                 inode->i_fop = &smb->sm_ops->sm_file_fops;
229                 inode->i_op = &smb->sm_ops->sm_file_iops;
230
231         } else if (S_ISLNK(inode->i_mode)) {
232                 if (!(smb->smsi_ops_check & SYMLINK_OPS_CHECK))
233                         setup_sm_symlink_ops(inode);
234                 inode->i_op = &smb->sm_ops->sm_sym_iops;
235                 inode->i_fop =  &smb->sm_ops->sm_sym_fops;
236         } else {
237                 if (!(smb->smsi_ops_check & SPECIAL_OPS_CHECK))
238                         setup_sm_special_ops(inode);
239                 inode->i_op = &smb->sm_ops->sm_special_iops;
240         }
241 }
242
243
244 void sm_set_sb_ops(struct super_block *cache_sb, struct super_block *sb)
245 {
246         struct smfs_super_info *smb = S2SMI(sb);
247         struct super_operations *sops = &smb->sm_ops->sm_sb_ops;
248         struct super_operations *smfs_sops = &smfs_super_ops;
249         ENTRY;
250
251         if (smb->smsi_ops_check & SB_OPS_CHECK)
252                 return;
253         
254         //set up only operations exist in backfs
255         memset(sops, 0, sizeof (struct super_operations));
256         if (cache_sb->s_op) {
257                 if (cache_sb->s_op->dirty_inode)
258                         sops->dirty_inode = smfs_sops->dirty_inode;
259                 if (cache_sb->s_op->write_inode)
260                         sops->write_inode = smfs_sops->write_inode;
261                 if (cache_sb->s_op->put_super)
262                         sops->put_super = smfs_sops->put_super;
263                 if (cache_sb->s_op->write_super)
264                         sops->write_super = smfs_sops->write_super;
265                 if (cache_sb->s_op->write_super_lockfs)
266                         sops->write_super_lockfs = smfs_sops->write_super_lockfs;
267                 if (cache_sb->s_op->unlockfs)
268                         sops->unlockfs = smfs_sops->unlockfs;
269                 if (cache_sb->s_op->statfs)
270                         sops->statfs = smfs_sops->statfs;
271                 if (cache_sb->s_op->remount_fs)
272                         sops->remount_fs = smfs_sops->remount_fs;
273                 //if (cache_sb->s_op->umount_begin)
274                 //      sops->umount_begin = smfs_sops->umount_begin;
275
276 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
277                 if (cache_sb->s_op->fh_to_dentry)
278                         sops->fh_to_dentry = smfs_sops->fh_to_dentry;
279                 if (cache_sb->s_op->dentry_to_fh)
280                         sops->dentry_to_fh = smfs_sops->dentry_to_fh;
281                 if (cache_sb->s_op->show_options)
282                         sops->show_options = smfs_sops->show_options;
283                 
284                 sops->read_inode2 = smfs_sops->read_inode2;
285 #endif
286                 /* these ops are needed always */
287                 sops->clear_inode = smfs_sops->clear_inode;
288                 sops->delete_inode = smfs_sops->delete_inode;
289
290         }
291
292         lock_kernel();
293         smb->smsi_ops_check |= SB_OPS_CHECK;
294         unlock_kernel();
295         sb->s_op = sops;
296         return;
297 }
298
299