Whamcloud - gitweb
* updates to HEAD lustre since landing b_port_step on portals
[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         }
107 }
108
109 static void setup_fops(struct inode *cache_inode,
110                        struct file_operations *fops,
111                        struct file_operations *cache_fops)
112 {
113         if (cache_inode->i_fop && cache_fops && fops) {
114                 if (cache_inode->i_fop->llseek)
115                         fops->llseek = cache_fops->llseek;
116                 if (cache_inode->i_fop->read)
117                         fops->read = cache_fops->read;
118                 if (cache_inode->i_fop->write)
119                         fops->write = cache_fops->write;
120                 if (cache_inode->i_fop->readdir)
121                         fops->readdir = cache_fops->readdir;
122                 if (cache_inode->i_fop->poll)
123                         fops->poll = cache_fops->poll;
124                 if (cache_inode->i_fop->ioctl)
125                         fops->ioctl = cache_fops->ioctl;
126                 if (cache_inode->i_fop->mmap)
127                         fops->mmap = cache_fops->mmap;
128                 if (cache_inode->i_fop->flush)
129                         fops->flush = cache_fops->flush;
130                 if (cache_inode->i_fop->fsync)
131                         fops->fsync = cache_fops->fsync;
132                 if (cache_inode->i_fop->fasync)
133                         fops->fasync = cache_fops->fasync;
134                 if (cache_inode->i_fop->lock)
135                         fops->lock = cache_fops->lock;
136                 if (cache_inode->i_fop->readv)
137                         fops->readv = cache_fops->readv;
138                 if (cache_inode->i_fop->writev)
139                         fops->writev = cache_fops->writev;
140                 if (cache_inode->i_fop->sendpage)
141                         fops->sendpage = cache_fops->sendpage;
142                 if (cache_inode->i_fop->get_unmapped_area)
143                         fops->get_unmapped_area = cache_fops->get_unmapped_area;
144
145                 /* for dir file we also need replace the open and release method,
146                  * because we need initialize the cache file structs. */
147                 fops->open = cache_fops->open;
148                 fops->release = cache_fops->release;
149         }
150 }
151
152 static void setup_sm_file_ops(struct inode *cache_inode, struct inode *inode,
153                               struct inode_operations *cache_iops,
154                               struct file_operations *cache_fops)
155 {
156         struct smfs_super_info *smb;
157         struct inode_operations *iops;
158         struct file_operations *fops;
159
160         smb = S2SMI(inode->i_sb);
161
162         if (smb->smsi_ops_check & FILE_OPS_CHECK)
163                 return;
164
165         iops = cache_fiops(smb);
166         fops = cache_ffops(smb);
167
168         setup_iops(cache_inode, iops, cache_iops);
169         setup_fops(cache_inode, fops, cache_fops);
170
171         lock_kernel();
172         smb->smsi_ops_check |= FILE_OPS_CHECK;
173         unlock_kernel();
174 }
175
176 static void setup_sm_dir_ops(struct inode *cache_inode, struct inode *inode,
177                              struct inode_operations *cache_dir_iops,
178                              struct file_operations *cache_dir_fops)
179 {
180         struct smfs_super_info *smb;
181         struct inode_operations *iops;
182         struct file_operations *fops;
183
184         smb = S2SMI(inode->i_sb);
185
186         if (smb->smsi_ops_check & DIR_OPS_CHECK)
187                 return;
188
189         iops = cache_diops(smb);
190         fops = cache_dfops(smb);
191
192         setup_iops(cache_inode, iops, cache_dir_iops);
193         setup_fops(cache_inode, fops, cache_dir_fops);
194
195         lock_kernel();
196         smb->smsi_ops_check |= DIR_OPS_CHECK;
197         unlock_kernel();
198 }
199
200 static void setup_sm_symlink_ops(struct inode *cache_inode, struct inode *inode,
201                                  struct inode_operations *cache_sym_iops,
202                                  struct file_operations *cache_sym_fops)
203 {
204         struct smfs_super_info *smb;
205         struct inode_operations *iops;
206         struct file_operations *fops;
207
208         smb = S2SMI(inode->i_sb);
209
210         if (smb->smsi_ops_check & SYMLINK_OPS_CHECK)
211                 return;
212
213         iops = cache_siops(smb);
214         fops = cache_sfops(smb);
215
216         setup_iops(cache_inode, iops, cache_sym_iops);
217         setup_fops(cache_inode, fops, cache_sym_fops);
218
219         lock_kernel();
220         smb->smsi_ops_check |= SYMLINK_OPS_CHECK;
221         unlock_kernel();
222 }
223
224 static void setup_sm_sb_ops(struct super_block *cache_sb, struct super_block *sb,
225                             struct super_operations *smfs_sops)
226 {
227         struct smfs_super_info *smb;
228         struct super_operations *sops;
229
230         ENTRY;
231
232         smb = S2SMI(sb);
233
234         if (smb->smsi_ops_check & SB_OPS_CHECK)
235                 return;
236
237         sops = cache_sops(smb);
238         memset(sops, 0, sizeof (struct super_operations));
239
240         if (cache_sb->s_op) {
241                 if (cache_sb->s_op->dirty_inode)
242                         sops->dirty_inode = smfs_sops->dirty_inode;
243                 if (cache_sb->s_op->write_inode)
244                         sops->write_inode = smfs_sops->write_inode;
245                 if (cache_sb->s_op->put_inode)
246                         sops->put_inode = smfs_sops->put_inode;
247                 if (cache_sb->s_op->delete_inode)
248                         sops->delete_inode = smfs_sops->delete_inode;
249                 if (cache_sb->s_op->put_super)
250                         sops->put_super = smfs_sops->put_super;
251                 if (cache_sb->s_op->write_super)
252                         sops->write_super = smfs_sops->write_super;
253                 if (cache_sb->s_op->write_super_lockfs)
254                         sops->write_super_lockfs = smfs_sops->write_super_lockfs;
255                 if (cache_sb->s_op->unlockfs)
256                         sops->unlockfs = smfs_sops->unlockfs;
257                 if (cache_sb->s_op->statfs)
258                         sops->statfs = smfs_sops->statfs;
259                 if (cache_sb->s_op->remount_fs)
260                         sops->remount_fs = smfs_sops->remount_fs;
261                 if (cache_sb->s_op->umount_begin)
262                         sops->umount_begin = smfs_sops->umount_begin;
263
264 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
265                 if (cache_sb->s_op->fh_to_dentry)
266                         sops->fh_to_dentry = smfs_sops->fh_to_dentry;
267                 if (cache_sb->s_op->dentry_to_fh)
268                         sops->dentry_to_fh = smfs_sops->dentry_to_fh;
269                 if (cache_sb->s_op->show_options)
270                         sops->show_options = smfs_sops->show_options;
271                 sops->read_inode2 = smfs_sops->read_inode2;
272 #endif
273                 /* FIXME-WANGDI we need this method to clear the cache inode. */
274                 sops->clear_inode = smfs_sops->clear_inode;
275         }
276
277         lock_kernel();
278         smb->smsi_ops_check |= SB_OPS_CHECK;
279         unlock_kernel();
280         return;
281 }
282
283 void sm_set_inode_ops(struct inode *cache_inode, struct inode *inode)
284 {
285         struct smfs_super_info *smb = S2SMI(inode->i_sb);
286
287         /* XXX now set the correct sm_{file,dir,sym}_iops */
288         if (S_ISDIR(inode->i_mode)) {
289                 setup_sm_dir_ops(cache_inode, inode,
290                                  &smfs_dir_iops,
291                                  &smfs_dir_fops);
292                 inode->i_op = cache_diops(smb);
293                 inode->i_fop = cache_dfops(smb);
294         } else if (S_ISREG(inode->i_mode)) {
295                 setup_sm_file_ops(cache_inode, inode,
296                                   &smfs_file_iops,
297                                   &smfs_file_fops);
298                 CDEBUG(D_INODE, "inode %lu, i_op at %p\n",
299                        inode->i_ino, inode->i_op);
300                 inode->i_fop = cache_ffops(smb);
301                 inode->i_op = cache_fiops(smb);
302
303         } else if (S_ISLNK(inode->i_mode)) {
304                 setup_sm_symlink_ops(cache_inode, inode,
305                                      &smfs_sym_iops,
306                                      &smfs_sym_fops);
307                 inode->i_op = cache_siops(smb);
308                 inode->i_fop = cache_sfops(smb);
309                 CDEBUG(D_INODE, "inode %lu, i_op at %p\n",
310                        inode->i_ino, inode->i_op);
311         }
312 }
313
314 void sm_set_sb_ops(struct super_block *cache_sb, struct super_block *sb)
315 {
316         struct smfs_super_info *smb;
317
318         smb = S2SMI(sb);
319
320         setup_sm_sb_ops(cache_sb, sb, &smfs_super_ops);
321
322         sb->s_op = cache_sops(smb);
323         return;
324 }
325