1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
5 * Lustre filesystem abstraction routines
7 * Copyright (C) 2004 Cluster File Systems, Inc.
9 * This file is part of Lustre, http://www.lustre.org.
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.
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.
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.
24 #define DEBUG_SUBSYSTEM S_SM
26 #include <linux/kmod.h>
27 #include <linux/init.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>
39 #include "smfs_internal.h"
40 int smfs_init_sm_ops(struct smfs_super_info *smb)
42 struct sm_operations *sm_ops; /*cache ops for set cache inode ops*/
44 OBD_ALLOC(sm_ops, sizeof(struct sm_operations));
52 void smfs_cleanup_sm_ops(struct smfs_super_info *smb)
55 OBD_FREE(smb->sm_ops, sizeof(struct sm_operations));
58 static void setup_iops(struct inode *cache_inode,
59 struct inode_operations *iops,
60 struct inode_operations *cache_iops)
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;
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;
109 static void setup_fops(struct inode *cache_inode,
110 struct file_operations *fops,
111 struct file_operations *cache_fops)
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;
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;
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)
156 struct smfs_super_info *smb;
157 struct inode_operations *iops;
158 struct file_operations *fops;
160 smb = S2SMI(inode->i_sb);
162 if (smb->smsi_ops_check & FILE_OPS_CHECK)
165 iops = cache_fiops(smb);
166 fops = cache_ffops(smb);
168 setup_iops(cache_inode, iops, cache_iops);
169 setup_fops(cache_inode, fops, cache_fops);
172 smb->smsi_ops_check |= FILE_OPS_CHECK;
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)
180 struct smfs_super_info *smb;
181 struct inode_operations *iops;
182 struct file_operations *fops;
184 smb = S2SMI(inode->i_sb);
186 if (smb->smsi_ops_check & DIR_OPS_CHECK)
189 iops = cache_diops(smb);
190 fops = cache_dfops(smb);
192 setup_iops(cache_inode, iops, cache_dir_iops);
193 setup_fops(cache_inode, fops, cache_dir_fops);
196 smb->smsi_ops_check |= DIR_OPS_CHECK;
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)
204 struct smfs_super_info *smb;
205 struct inode_operations *iops;
206 struct file_operations *fops;
208 smb = S2SMI(inode->i_sb);
210 if (smb->smsi_ops_check & SYMLINK_OPS_CHECK)
213 iops = cache_siops(smb);
214 fops = cache_sfops(smb);
216 setup_iops(cache_inode, iops, cache_sym_iops);
217 setup_fops(cache_inode, fops, cache_sym_fops);
220 smb->smsi_ops_check |= SYMLINK_OPS_CHECK;
225 void sm_set_inode_ops(struct inode *cache_inode, struct inode *inode)
227 struct smfs_super_info *smb = S2SMI(inode->i_sb);
229 /* XXX now set the correct sm_{file,dir,sym}_iops */
230 if (S_ISDIR(inode->i_mode)) {
231 setup_sm_dir_ops(cache_inode, inode,
234 inode->i_op = cache_diops(smb);
235 inode->i_fop = cache_dfops(smb);
236 } else if (S_ISREG(inode->i_mode)) {
237 setup_sm_file_ops(cache_inode, inode,
240 CDEBUG(D_INODE, "inode %lu, i_op at %p\n",
241 inode->i_ino, inode->i_op);
242 inode->i_fop = cache_ffops(smb);
243 inode->i_op = cache_fiops(smb);
245 } else if (S_ISLNK(inode->i_mode)) {
246 setup_sm_symlink_ops(cache_inode, inode,
249 inode->i_op = cache_siops(smb);
250 inode->i_fop = cache_sfops(smb);
251 CDEBUG(D_INODE, "inode %lu, i_op at %p\n",
252 inode->i_ino, inode->i_op);
257 void sm_set_sb_ops(struct super_block *cache_sb, struct super_block *sb)
259 struct smfs_super_info *smb = S2SMI(sb);
260 struct super_operations *sops = &smb->sm_ops->sm_sb_ops;
261 struct super_operations *smfs_sops = &smfs_super_ops;
264 if (smb->smsi_ops_check & SB_OPS_CHECK)
267 //set up only operations exist in backfs
268 memset(sops, 0, sizeof (struct super_operations));
269 if (cache_sb->s_op) {
270 if (cache_sb->s_op->dirty_inode)
271 sops->dirty_inode = smfs_sops->dirty_inode;
272 if (cache_sb->s_op->write_inode)
273 sops->write_inode = smfs_sops->write_inode;
274 if (cache_sb->s_op->put_super)
275 sops->put_super = smfs_sops->put_super;
276 if (cache_sb->s_op->write_super)
277 sops->write_super = smfs_sops->write_super;
278 if (cache_sb->s_op->write_super_lockfs)
279 sops->write_super_lockfs = smfs_sops->write_super_lockfs;
280 if (cache_sb->s_op->unlockfs)
281 sops->unlockfs = smfs_sops->unlockfs;
282 if (cache_sb->s_op->statfs)
283 sops->statfs = smfs_sops->statfs;
284 if (cache_sb->s_op->remount_fs)
285 sops->remount_fs = smfs_sops->remount_fs;
286 //if (cache_sb->s_op->umount_begin)
287 // sops->umount_begin = smfs_sops->umount_begin;
289 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
290 if (cache_sb->s_op->fh_to_dentry)
291 sops->fh_to_dentry = smfs_sops->fh_to_dentry;
292 if (cache_sb->s_op->dentry_to_fh)
293 sops->dentry_to_fh = smfs_sops->dentry_to_fh;
294 if (cache_sb->s_op->show_options)
295 sops->show_options = smfs_sops->show_options;
297 sops->read_inode2 = smfs_sops->read_inode2;
299 /* these ops are needed always */
300 sops->clear_inode = smfs_sops->clear_inode;
301 sops->delete_inode = smfs_sops->delete_inode;
306 smb->smsi_ops_check |= SB_OPS_CHECK;