Whamcloud - gitweb
update smfs 1)some fix in cache mount 2)some fix in lookup and touch, create
[fs/lustre-release.git] / lustre / smfs / cache.c
1 /*  
2  *  snapfs/cache.c
3  */
4
5 #define DEBUG_SUBSYSTEM S_SM
6
7 #include <linux/kmod.h>
8 #include <linux/init.h>
9 #include <linux/fs.h>
10 #include <linux/slab.h>
11 #include <linux/string.h>
12 #include <portals/list.h>
13 #include "smfs_internal.h" 
14 struct sm_ops smfs_operations;
15  
16 extern struct inode_operations smfs_file_iops;
17 extern struct file_operations  smfs_file_fops;
18 extern struct address_space_operations smfs_file_aops;
19 extern struct inode_operations smfs_sym_iops; 
20 extern struct file_operations smfs_sym_fops;
21 extern struct super_operations smfs_super_ops;
22
23 inline struct super_operations *cache_sops(struct sm_ops *smfs_ops)
24 {
25         return &smfs_ops->sm_sb_ops;
26 }
27
28 inline struct inode_operations *cache_diops(struct sm_ops *smfs_ops)
29 {
30         return &smfs_ops->sm_dir_iops;
31 }
32
33 inline struct inode_operations *cache_fiops(struct sm_ops *smfs_ops)
34 {
35         return &smfs_ops->sm_file_iops;
36 }
37
38 inline struct inode_operations *cache_siops(struct sm_ops *smfs_ops)
39 {
40         return &smfs_ops->sm_sym_iops;
41 }
42
43 inline struct file_operations *cache_dfops(struct sm_ops *smfs_ops) 
44 {
45         return &smfs_ops->sm_dir_fops;
46 }
47
48 inline struct file_operations *cache_ffops(struct sm_ops *smfs_ops)
49 {
50         return &smfs_ops->sm_file_fops;
51 }
52
53 inline struct address_space_operations *cache_faops(struct sm_ops *smfs_ops) 
54 {
55         return &smfs_ops->sm_file_aops;
56 }
57
58 inline struct file_operations *cache_sfops(struct sm_ops *smfs_ops)
59 {
60         return &smfs_ops->sm_sym_fops;
61 }
62
63 inline struct dentry_operations *cache_dops(struct sm_ops *smfs_ops)
64 {
65         return &smfs_ops->sm_dentry_ops;
66 }
67
68 void init_smfs_cache()
69 {
70         memset(&smfs_operations, 0, sizeof(struct sm_ops)); 
71 }
72 void cleanup_smfs_cache()
73 {
74         return;
75 }
76
77 static void setup_iops(struct inode *cache_inode, 
78                        struct inode_operations *iops,
79                        struct inode_operations *cache_iops)
80 {
81
82         if (cache_inode->i_op && cache_iops && iops) {
83                 if (cache_inode->i_op->create) 
84                         iops->create = cache_iops->create;
85                 if (cache_inode->i_op->create_it) 
86                         iops->create_it = cache_iops->create_it;
87                 if (cache_inode->i_op->lookup)
88                         iops->lookup = cache_iops->lookup;
89                 if (cache_inode->i_op->lookup_raw)
90                         iops->lookup_raw = cache_iops->lookup_raw;
91                 if (cache_inode->i_op->lookup_it)
92                         iops->lookup_it = cache_iops->lookup_it;
93                 if (cache_inode->i_op->link)
94                         iops->link = cache_iops->link;
95                 if (cache_inode->i_op->link_raw)
96                         iops->link_raw = cache_iops->link_raw;
97                 if (cache_inode->i_op->unlink)
98                         iops->unlink = cache_iops->unlink;
99                 if (cache_inode->i_op->unlink_raw)
100                         iops->unlink_raw = cache_iops->unlink_raw;
101                 if (cache_inode->i_op->symlink)
102                         iops->symlink = cache_iops->symlink;
103                 if (cache_inode->i_op->symlink_raw)
104                         iops->symlink_raw = cache_iops->symlink_raw;
105                 if (cache_inode->i_op->mkdir)
106                         iops->mkdir = cache_iops->mkdir;
107                 if (cache_inode->i_op->mkdir_raw)
108                         iops->mkdir_raw = cache_iops->mkdir_raw;
109                 if (cache_inode->i_op->rmdir)
110                         iops->rmdir = cache_iops->rmdir;
111                 if (cache_inode->i_op->rmdir_raw)
112                         iops->rmdir_raw = cache_iops->rmdir_raw;
113                 if (cache_inode->i_op->mknod)
114                         iops->mknod = cache_iops->mknod;
115                 if (cache_inode->i_op->mknod_raw)
116                         iops->mknod_raw = cache_iops->mknod_raw;
117                 if (cache_inode->i_op->rename)
118                         iops->rename = cache_iops->rename;
119                 if (cache_inode->i_op->rename_raw)
120                         iops->rename_raw = cache_iops->rename_raw;
121                 if (cache_inode->i_op->readlink)
122                         iops->readlink = cache_iops->readlink;
123                 if (cache_inode->i_op->follow_link)
124                         iops->follow_link = cache_iops->follow_link;
125                 if (cache_inode->i_op->truncate)
126                         iops->truncate = cache_iops->truncate;
127                 if (cache_inode->i_op->permission)
128                         iops->permission = cache_iops->permission;
129                 if (cache_inode->i_op->revalidate)
130                         iops->revalidate = cache_iops->revalidate;
131                 if (cache_inode->i_op->revalidate_it)
132                         iops->revalidate_it = cache_iops->revalidate_it;
133                 if (cache_inode->i_op->setattr)
134                         iops->setattr = cache_iops->setattr;
135                 if (cache_inode->i_op->setattr_raw)
136                         iops->setattr_raw = cache_iops->setattr_raw;
137                 if (cache_inode->i_op->getattr)
138                         iops->getattr = cache_iops->getattr;
139                 if (cache_inode->i_op->setxattr)
140                         iops->setxattr = cache_iops->setxattr;
141                 if (cache_inode->i_op->getxattr)
142                         iops->getxattr = cache_iops->getxattr;
143                 if (cache_inode->i_op->listxattr)
144                         iops->listxattr = cache_iops->listxattr;
145                 if (cache_inode->i_op->removexattr)
146                         iops->removexattr = cache_iops->removexattr;
147         }
148 }
149 static void setup_fops(struct inode *cache_inode,
150                        struct file_operations *fops,
151                        struct file_operations *cache_fops)
152 {
153         if (cache_inode->i_fop && cache_fops && fops) {
154                 if (cache_inode->i_fop->llseek)
155                         fops->llseek = cache_fops->llseek;
156                 if (cache_inode->i_fop->read)
157                         fops->read = cache_fops->read;
158                 if (cache_inode->i_fop->write)
159                         fops->write = cache_fops->write;
160                 if (cache_inode->i_fop->readdir)
161                         fops->readdir = cache_fops->readdir;
162                 if (cache_inode->i_fop->poll)
163                         fops->poll = cache_fops->poll;
164                 if (cache_inode->i_fop->ioctl)
165                         fops->ioctl = cache_fops->ioctl;
166                 if (cache_inode->i_fop->mmap)
167                         fops->mmap = cache_fops->mmap;
168                 if (cache_inode->i_fop->open)
169                         fops->open = cache_fops->open;
170                 if (cache_inode->i_fop->flush)
171                         fops->flush = cache_fops->flush;
172                 if (cache_inode->i_fop->release)
173                         fops->release = cache_fops->release;
174                 if (cache_inode->i_fop->fsync)
175                         fops->fsync = cache_fops->fsync;
176                 if (cache_inode->i_fop->fasync)
177                         fops->fasync = cache_fops->fasync;
178                 if (cache_inode->i_fop->lock)
179                         fops->lock = cache_fops->lock;
180                 if (cache_inode->i_fop->readv)
181                         fops->readv = cache_fops->readv;
182                 if (cache_inode->i_fop->writev)
183                         fops->writev = cache_fops->writev;
184                 if (cache_inode->i_fop->sendpage)
185                         fops->sendpage = cache_fops->sendpage;
186                 if (cache_inode->i_fop->get_unmapped_area)
187                         fops->get_unmapped_area = cache_fops->get_unmapped_area;                                                                                        
188         }
189 }
190 static void setup_aops(struct inode *cache_inode,
191                        struct address_space_operations *aops,
192                        struct address_space_operations *cache_aops)
193 {
194         if (cache_inode && cache_inode->i_mapping && 
195             aops && cache_aops) {
196                 struct address_space_operations *caops = cache_inode->i_mapping->a_ops;
197
198                 if (caops->writepage) 
199                         aops->writepage = cache_aops->writepage;
200                 if (caops->readpage)
201                         aops->readpage = cache_aops->readpage;
202                 if (caops->sync_page)
203                         aops->sync_page = cache_aops->sync_page;
204                 if (caops->prepare_write)
205                         aops->prepare_write = cache_aops->prepare_write;
206                 if (caops->commit_write)
207                         aops->commit_write = cache_aops->commit_write;
208                 if (caops->bmap)
209                         aops->bmap = cache_aops->bmap;
210                 if (caops->flushpage)
211                         aops->flushpage = cache_aops->flushpage;
212                 if (caops->releasepage)
213                         aops->releasepage = cache_aops->releasepage;
214                 if (caops->direct_IO)
215                         aops->direct_IO = cache_aops->direct_IO;
216                 if (caops->removepage)
217                         aops->removepage = cache_aops->removepage;
218         }                                                                       
219 };
220                 
221 static void setup_sm_file_ops(struct inode *cache_inode, 
222                               struct inode *inode,
223                               struct inode_operations *cache_iops,
224                               struct file_operations *cache_fops,
225                               struct address_space_operations *cache_aops)
226 {
227         
228         struct smfs_super_info *smb;
229         struct inode_operations *iops;
230         struct file_operations *fops;
231         struct address_space_operations *aops;
232
233         smb = S2SMI(inode->i_sb); 
234         
235         if (smb->ops_check & FILE_OPS_CHECK) 
236                 return; 
237         smb->ops_check |= FILE_OPS_CHECK;
238
239         iops = cache_fiops(&smfs_operations);
240         fops = cache_ffops(&smfs_operations);
241         aops = cache_faops(&smfs_operations);
242
243         memset(iops , 0 , sizeof (struct inode_operations));    
244         memset(fops , 0 , sizeof (struct file_operations));     
245         memset(aops , 0 , sizeof (struct address_space_operations));    
246
247         setup_iops(cache_inode, iops, cache_iops);      
248         setup_fops(cache_inode, fops, cache_fops);
249         setup_aops(cache_inode, aops, cache_aops);
250
251         return;
252 }
253
254 static void setup_sm_dir_ops(struct inode *cache_inode, 
255                              struct  inode *inode,
256                              struct inode_operations *cache_dir_iops,
257                              struct file_operations *cache_dir_fops)
258 {
259         struct smfs_super_info *smb;
260         struct inode_operations *iops;
261         struct file_operations *fops;
262
263         smb = S2SMI(inode->i_sb); 
264         
265         if (smb->ops_check & DIR_OPS_CHECK) 
266                 return; 
267         smb->ops_check |= DIR_OPS_CHECK;
268
269         iops = cache_diops(&smfs_operations);
270         fops = cache_dfops(&smfs_operations);
271
272         memset(iops, 0, sizeof (struct inode_operations));      
273         memset(fops, 0, sizeof (struct file_operations));       
274
275         setup_iops(cache_inode, iops, cache_dir_iops);  
276         setup_fops(cache_inode, fops, cache_dir_fops);
277
278         return;
279 }
280
281 static void setup_sm_symlink_ops(struct inode *cache_inode, 
282                                  struct  inode *inode,
283                                  struct inode_operations *cache_sym_iops,
284                                  struct file_operations *cache_sym_fops)
285 {
286         struct smfs_super_info *smb;
287         struct inode_operations *iops;
288         struct file_operations *fops;
289
290         smb = S2SMI(inode->i_sb); 
291         
292         if (smb->ops_check & SYMLINK_OPS_CHECK) 
293                 return; 
294         smb->ops_check |= SYMLINK_OPS_CHECK;
295
296         iops = cache_siops(&smfs_operations);
297         fops = cache_sfops(&smfs_operations);
298
299         memset(iops , 0 , sizeof (struct inode_operations));    
300         memset(fops , 0 , sizeof (struct file_operations));     
301
302         setup_iops(cache_inode, iops, cache_sym_iops);  
303         setup_fops(cache_inode, fops, cache_sym_fops);
304
305         return;
306 }
307
308 static void setup_sm_sb_ops(struct super_block *cache_sb, 
309                             struct super_block *sb, 
310                             struct super_operations *smfs_sops) 
311 {
312         struct smfs_super_info *smb;
313         struct super_operations *sops;
314
315         ENTRY;
316
317         smb = S2SMI(sb); 
318         
319         if (smb->ops_check & SB_OPS_CHECK) 
320                 return; 
321         smb->ops_check |= SB_OPS_CHECK;
322         sops = cache_sops(&smfs_operations);
323         memset(sops, 0, sizeof (struct super_operations));      
324
325         if (cache_sb->s_op) {
326                 if (cache_sb->s_op->read_inode) 
327                         sops->read_inode = smfs_sops->read_inode;
328                 if (cache_sb->s_op->read_inode2)
329                         sops->read_inode2 = smfs_sops->read_inode2;
330                 if (cache_sb->s_op->dirty_inode)
331                         sops->dirty_inode = smfs_sops->dirty_inode;
332                 if (cache_sb->s_op->write_inode)
333                         sops->write_inode = smfs_sops->write_inode;
334                 if (cache_sb->s_op->put_inode)
335                         sops->put_inode = smfs_sops->put_inode;
336                 if (cache_sb->s_op->delete_inode)
337                         sops->delete_inode = smfs_sops->delete_inode;
338                 if (cache_sb->s_op->put_super)
339                         sops->put_super = smfs_sops->put_super;
340                 if (cache_sb->s_op->write_super)
341                         sops->write_super = smfs_sops->write_super;
342                 if (cache_sb->s_op->write_super_lockfs)
343                         sops->write_super_lockfs = smfs_sops->write_super_lockfs;
344                 if (cache_sb->s_op->unlockfs)
345                         sops->unlockfs = smfs_sops->unlockfs;
346                 if (cache_sb->s_op->statfs)
347                         sops->statfs = smfs_sops->statfs;
348                 if (cache_sb->s_op->remount_fs)
349                         sops->remount_fs = smfs_sops->remount_fs;
350                 if (cache_sb->s_op->clear_inode)
351                         sops->clear_inode = smfs_sops->clear_inode;
352                 if (cache_sb->s_op->umount_begin)
353                         sops->umount_begin = smfs_sops->umount_begin;
354                 if (cache_sb->s_op->fh_to_dentry)
355                         sops->fh_to_dentry = smfs_sops->fh_to_dentry;
356                 if (cache_sb->s_op->dentry_to_fh)
357                         sops->dentry_to_fh = smfs_sops->dentry_to_fh;
358                 if (cache_sb->s_op->show_options)
359                         sops->show_options = smfs_sops->show_options;
360         }
361                                         
362         return;
363 }       
364 void sm_set_inode_ops(struct inode *cache_inode, struct inode *inode)
365 {
366         /* XXX now set the correct snap_{file,dir,sym}_iops */
367         if (S_ISDIR(inode->i_mode)) {
368                 setup_sm_dir_ops(cache_inode, inode,
369                                  &smfs_dir_iops,
370                                  &smfs_dir_fops);
371                 inode->i_op = cache_diops(&smfs_operations);
372                 inode->i_fop = cache_dfops(&smfs_operations);
373         } else if (S_ISREG(inode->i_mode)) {
374                 setup_sm_file_ops(cache_inode, inode,
375                                   &smfs_file_iops,
376                                   &smfs_file_fops,
377                                   &smfs_file_aops);
378                 CDEBUG(D_INODE, "inode %lu, i_op at %p\n",
379                        inode->i_ino, inode->i_op);
380                 inode->i_fop = cache_ffops(&smfs_operations);
381                 inode->i_op = cache_fiops(&smfs_operations);
382                 if (inode->i_mapping)
383                         inode->i_mapping->a_ops = cache_faops(&smfs_operations);
384         
385         } else if (S_ISLNK(inode->i_mode)) {
386                 setup_sm_symlink_ops(cache_inode, inode,
387                                      &smfs_sym_iops, 
388                                      &smfs_sym_fops);
389                 inode->i_op = cache_siops(&smfs_operations);
390                 inode->i_fop = cache_sfops(&smfs_operations);
391                 CDEBUG(D_INODE, "inode %lu, i_op at %p\n",
392                        inode->i_ino, inode->i_op);
393         }
394 }
395 void sm_set_sb_ops (struct super_block *cache_sb,
396                       struct super_block *sb)
397 {
398         struct smfs_super_info *smb;
399
400         smb = S2SMI(sb); 
401         
402         setup_sm_sb_ops(cache_sb, sb, &smfs_super_ops); 
403         
404         sb->s_op = cache_sops(&smfs_operations);
405         return; 
406 }
407