Whamcloud - gitweb
Update smfs: fix bugs of smfs_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         struct smfs_super_info *smb;
228         struct inode_operations *iops;
229         struct file_operations *fops;
230         struct address_space_operations *aops;
231
232         smb = S2SMI(inode->i_sb); 
233         
234         if (smb->ops_check & FILE_OPS_CHECK) 
235                 return; 
236         smb->ops_check |= FILE_OPS_CHECK;
237
238         iops = cache_fiops(&smfs_operations);
239         fops = cache_ffops(&smfs_operations);
240         aops = cache_faops(&smfs_operations);
241
242         memset(iops , 0 , sizeof (struct inode_operations));    
243         memset(fops , 0 , sizeof (struct file_operations));     
244         memset(aops , 0 , sizeof (struct address_space_operations));    
245
246         setup_iops(cache_inode, iops, cache_iops);      
247         setup_fops(cache_inode, fops, cache_fops);
248         setup_aops(cache_inode, aops, cache_aops);
249
250         return;
251 }
252
253 static void setup_sm_dir_ops(struct inode *cache_inode, 
254                              struct  inode *inode,
255                              struct inode_operations *cache_dir_iops,
256                              struct file_operations *cache_dir_fops)
257 {
258         struct smfs_super_info *smb;
259         struct inode_operations *iops;
260         struct file_operations *fops;
261
262         smb = S2SMI(inode->i_sb); 
263         
264         if (smb->ops_check & DIR_OPS_CHECK) 
265                 return; 
266         smb->ops_check |= DIR_OPS_CHECK;
267
268         iops = cache_diops(&smfs_operations);
269         fops = cache_dfops(&smfs_operations);
270
271         memset(iops, 0, sizeof (struct inode_operations));      
272         memset(fops, 0, sizeof (struct file_operations));       
273
274         setup_iops(cache_inode, iops, cache_dir_iops);  
275         setup_fops(cache_inode, fops, cache_dir_fops);
276
277         return;
278 }
279
280 static void setup_sm_symlink_ops(struct inode *cache_inode, 
281                                  struct  inode *inode,
282                                  struct inode_operations *cache_sym_iops,
283                                  struct file_operations *cache_sym_fops)
284 {
285         struct smfs_super_info *smb;
286         struct inode_operations *iops;
287         struct file_operations *fops;
288
289         smb = S2SMI(inode->i_sb); 
290         
291         if (smb->ops_check & SYMLINK_OPS_CHECK) 
292                 return; 
293         smb->ops_check |= SYMLINK_OPS_CHECK;
294
295         iops = cache_siops(&smfs_operations);
296         fops = cache_sfops(&smfs_operations);
297
298         memset(iops , 0 , sizeof (struct inode_operations));    
299         memset(fops , 0 , sizeof (struct file_operations));     
300
301         setup_iops(cache_inode, iops, cache_sym_iops);  
302         setup_fops(cache_inode, fops, cache_sym_fops);
303
304         return;
305 }
306
307 static void setup_sm_sb_ops(struct super_block *cache_sb, 
308                             struct super_block *sb, 
309                             struct super_operations *smfs_sops) 
310 {
311         struct smfs_super_info *smb;
312         struct super_operations *sops;
313
314         ENTRY;
315
316         smb = S2SMI(sb); 
317         
318         if (smb->ops_check & SB_OPS_CHECK) 
319                 return; 
320         smb->ops_check |= SB_OPS_CHECK;
321         sops = cache_sops(&smfs_operations);
322         memset(sops, 0, sizeof (struct super_operations));      
323
324         if (cache_sb->s_op) {
325                 if (cache_sb->s_op->read_inode) 
326                         sops->read_inode = smfs_sops->read_inode;
327                 if (cache_sb->s_op->read_inode2)
328                         sops->read_inode2 = smfs_sops->read_inode2;
329                 if (cache_sb->s_op->dirty_inode)
330                         sops->dirty_inode = smfs_sops->dirty_inode;
331                 if (cache_sb->s_op->write_inode)
332                         sops->write_inode = smfs_sops->write_inode;
333                 if (cache_sb->s_op->put_inode)
334                         sops->put_inode = smfs_sops->put_inode;
335                 if (cache_sb->s_op->delete_inode)
336                         sops->delete_inode = smfs_sops->delete_inode;
337                 if (cache_sb->s_op->put_super)
338                         sops->put_super = smfs_sops->put_super;
339                 if (cache_sb->s_op->write_super)
340                         sops->write_super = smfs_sops->write_super;
341                 if (cache_sb->s_op->write_super_lockfs)
342                         sops->write_super_lockfs = smfs_sops->write_super_lockfs;
343                 if (cache_sb->s_op->unlockfs)
344                         sops->unlockfs = smfs_sops->unlockfs;
345                 if (cache_sb->s_op->statfs)
346                         sops->statfs = smfs_sops->statfs;
347                 if (cache_sb->s_op->remount_fs)
348                         sops->remount_fs = smfs_sops->remount_fs;
349                 if (cache_sb->s_op->umount_begin)
350                         sops->umount_begin = smfs_sops->umount_begin;
351                 if (cache_sb->s_op->fh_to_dentry)
352                         sops->fh_to_dentry = smfs_sops->fh_to_dentry;
353                 if (cache_sb->s_op->dentry_to_fh)
354                         sops->dentry_to_fh = smfs_sops->dentry_to_fh;
355                 if (cache_sb->s_op->show_options)
356                         sops->show_options = smfs_sops->show_options;
357                 /*FIXME we need this method to clear the cache inode */
358                 sops->clear_inode = smfs_sops->clear_inode;
359         }
360                                         
361         return;
362 }       
363 void sm_set_inode_ops(struct inode *cache_inode, struct inode *inode)
364 {
365         /* XXX now set the correct snap_{file,dir,sym}_iops */
366         if (S_ISDIR(inode->i_mode)) {
367                 setup_sm_dir_ops(cache_inode, inode,
368                                  &smfs_dir_iops,
369                                  &smfs_dir_fops);
370                 inode->i_op = cache_diops(&smfs_operations);
371                 inode->i_fop = cache_dfops(&smfs_operations);
372         } else if (S_ISREG(inode->i_mode)) {
373                 setup_sm_file_ops(cache_inode, inode,
374                                   &smfs_file_iops,
375                                   &smfs_file_fops,
376                                   &smfs_file_aops);
377                 CDEBUG(D_INODE, "inode %lu, i_op at %p\n",
378                        inode->i_ino, inode->i_op);
379                 inode->i_fop = cache_ffops(&smfs_operations);
380                 inode->i_op = cache_fiops(&smfs_operations);
381                 if (inode->i_mapping)
382                         inode->i_mapping->a_ops = cache_faops(&smfs_operations);
383         
384         } else if (S_ISLNK(inode->i_mode)) {
385                 setup_sm_symlink_ops(cache_inode, inode,
386                                      &smfs_sym_iops, 
387                                      &smfs_sym_fops);
388                 inode->i_op = cache_siops(&smfs_operations);
389                 inode->i_fop = cache_sfops(&smfs_operations);
390                 CDEBUG(D_INODE, "inode %lu, i_op at %p\n",
391                        inode->i_ino, inode->i_op);
392         }
393 }
394 void sm_set_sb_ops (struct super_block *cache_sb,
395                       struct super_block *sb)
396 {
397         struct smfs_super_info *smb;
398
399         smb = S2SMI(sb); 
400         
401         setup_sm_sb_ops(cache_sb, sb, &smfs_super_ops); 
402         
403         sb->s_op = cache_sops(&smfs_operations);
404         return; 
405 }
406