Whamcloud - gitweb
Update smfs:some minor fix in smfs
[fs/lustre-release.git] / lustre / smfs / dir.c
1 /*
2  * dir.c
3  */
4 #define DEBUG_SUBSYSTEM S_SNAP
5
6 #include <linux/module.h>
7 #include <linux/kernel.h>
8 #include <linux/string.h>
9 #include <linux/slab.h>
10 #include <linux/stat.h>
11 #include <linux/unistd.h>
12 #include <linux/lustre_idl.h> 
13 #include <linux/smp_lock.h>
14
15 #include "smfs_internal.h" 
16 #include "kml_idl.h" 
17
18 #define NAME_ALLOC_LEN(len)     ((len+16) & ~15)
19                                                                                                                                                                                         
20 void prepare_parent_dentry(struct dentry *dentry, struct inode *inode)
21 {
22         atomic_set(&dentry->d_count, 1);
23         dentry->d_vfs_flags = 0;
24         dentry->d_flags = 0;
25         dentry->d_inode = inode;
26         dentry->d_op = NULL;
27         dentry->d_fsdata = NULL;
28         dentry->d_mounted = 0;
29         INIT_LIST_HEAD(&dentry->d_hash);
30         INIT_LIST_HEAD(&dentry->d_lru);
31         INIT_LIST_HEAD(&dentry->d_subdirs);
32         INIT_LIST_HEAD(&dentry->d_alias);
33 }
34
35 void d_unalloc(struct dentry *dentry)
36 {
37
38         list_del(&dentry->d_hash);
39         INIT_LIST_HEAD(&dentry->d_hash);
40         dput(dentry); /* this will free the dentry memory */
41 }
42
43 static int smfs_create(struct inode *dir, 
44                        struct dentry *dentry, 
45                        int mode)
46 {
47         struct  inode *cache_dir; 
48         struct  inode *cache_inode = NULL, *inode;
49         struct  dentry parent; 
50         struct  dentry *cache_dentry = NULL;
51         int     rc;
52         
53         ENTRY;
54         
55         cache_dir = I2CI(dir);
56         if (!cache_dir)
57                 RETURN(-ENOENT);
58        
59         prepare_parent_dentry(&parent, cache_dir);      
60         cache_dentry = d_alloc(&parent, &dentry->d_name);
61         
62         if (!cache_dentry) {
63                 RETURN(-ENOMEM);
64         }
65                  
66         if (cache_dir && cache_dir->i_op->create)
67                 rc = cache_dir->i_op->create(cache_dir, cache_dentry, mode);
68         
69         if (rc)
70                 GOTO(exit, rc);
71
72         cache_inode = igrab(cache_dentry->d_inode);
73         
74         inode = iget(dir->i_sb, cache_inode->i_ino);    
75
76         if (!inode) 
77                 GOTO(exit, rc = -ENOMEM);
78                 
79         d_instantiate(dentry, inode);   
80         
81         sm_set_inode_ops(cache_inode, inode);
82 exit:
83         d_unalloc(cache_dentry);
84         RETURN(rc);
85 }
86
87 static struct dentry *smfs_lookup(struct inode *dir,
88                                   struct dentry *dentry)
89 {
90         struct  inode *cache_dir; 
91         struct  inode *cache_inode = NULL, *inode;
92         struct  dentry parent; 
93         struct  dentry *cache_dentry = NULL;
94         struct  dentry *rc = NULL;
95         
96         ENTRY;
97         
98         cache_dir = I2CI(dir);
99         if (!cache_dir)
100                 RETURN(ERR_PTR(-ENOENT));
101         prepare_parent_dentry(&parent, cache_dir);      
102         cache_dentry = d_alloc(&parent, &dentry->d_name);
103       
104         if(cache_dir && cache_dir->i_op->lookup)
105                 rc = cache_dir->i_op->lookup(cache_dir, cache_dentry);
106
107         if (rc || !cache_dentry->d_inode || 
108             is_bad_inode(cache_dentry->d_inode) ||
109             IS_ERR(cache_dentry->d_inode)) {
110                 GOTO(exit, rc); 
111         }
112
113         cache_inode = igrab(cache_dentry->d_inode);
114         
115         inode = iget(dir->i_sb, cache_inode->i_ino);    
116                 
117         d_add(dentry, inode);   
118 exit:
119         d_unalloc(cache_dentry);
120         RETURN(rc);
121 }                      
122
123 static int smfs_lookup_raw(struct inode *dir, const char *name,
124                            int len, ino_t *data)
125 {
126         struct  inode *cache_dir; 
127         int     rc = 0;
128
129         cache_dir = I2CI(dir);
130
131         if (!cache_dir) 
132                 RETURN(-ENOENT);
133         
134         if (cache_dir->i_op->lookup_raw)
135                 rc = cache_dir->i_op->lookup_raw(cache_dir, name, len, data);           
136                 
137         RETURN(rc);
138 }
139
140 static int smfs_link(struct dentry * old_dentry,
141                      struct inode * dir, struct dentry *dentry)
142 {
143         struct  inode *cache_old_inode = NULL; 
144         struct  inode *cache_dir = I2CI(dir); 
145         struct  inode *inode = NULL; 
146         struct  dentry *cache_dentry;
147         struct  dentry *cache_old_dentry;
148         struct  dentry parent; 
149         struct  dentry parent_old; 
150         int     rc = 0;
151
152         inode = old_dentry->d_inode;
153         
154         cache_old_inode = I2CI(inode);
155         
156         if (!cache_old_inode || !cache_dir) 
157                 RETURN(-ENOENT);
158         
159         prepare_parent_dentry(&parent, cache_dir);
160         cache_dentry = d_alloc(&parent, &dentry->d_name);
161         
162         prepare_parent_dentry(&parent_old, cache_dir);
163         cache_old_dentry = d_alloc(&parent_old, &dentry->d_name);
164         d_add(cache_old_dentry, cache_old_inode); 
165         pre_smfs_inode(inode, cache_old_dentry->d_inode);
166         
167         if (cache_dir->i_op->link)
168                 rc = cache_dir->i_op->link(cache_old_dentry, cache_dir, cache_dentry);          
169         
170         if (rc)
171                 GOTO(exit, rc); 
172         
173         atomic_inc(&inode->i_count);
174         post_smfs_inode(inode, cache_old_dentry->d_inode);
175         d_instantiate(dentry, inode);
176
177 exit:
178         if (cache_dentry->d_inode)      
179                 igrab(cache_dentry->d_inode);
180         if (cache_old_dentry->d_inode)
181                 igrab(cache_old_dentry->d_inode);
182         
183         d_unalloc(cache_dentry);
184         d_unalloc(cache_old_dentry);
185
186         RETURN(rc);
187 }
188
189 static int smfs_unlink(struct inode * dir, 
190                        struct dentry *dentry)
191 {
192         struct inode *cache_dir = I2CI(dir);
193         struct inode *cache_inode = I2CI(dentry->d_inode);
194         struct dentry *cache_dentry;
195         struct dentry parent; 
196         int    rc = 0;
197
198         if (!cache_dir || !cache_inode)
199                 RETURN(-ENOENT);
200         
201         prepare_parent_dentry(&parent, cache_dir);
202         cache_dentry = d_alloc(&parent, &dentry->d_name);
203         d_add(cache_dentry, cache_inode);
204
205         pre_smfs_inode(dentry->d_inode, cache_dentry->d_inode);
206         pre_smfs_inode(dir, cache_dir);
207         
208         if (cache_dir->i_op->unlink)
209                 rc = cache_dir->i_op->unlink(cache_dir, cache_dentry);
210
211         
212         post_smfs_inode(dentry->d_inode, cache_dentry->d_inode);
213         post_smfs_inode(dir, cache_dir);
214         
215         igrab(cache_dentry->d_inode);
216
217         d_unalloc(cache_dentry);        
218         RETURN(rc);     
219 }
220
221 static int smfs_symlink (struct inode * dir,
222                          struct dentry *dentry, 
223                          const char * symname)
224 {
225         struct inode *cache_dir = I2CI(dir);
226         struct inode *cache_inode = NULL;
227         struct inode *inode = NULL;
228         struct dentry *cache_dentry; 
229         struct dentry parent; 
230         int    rc = 0;
231
232         if (!cache_dir) 
233                 RETURN(-ENOENT);
234         
235         prepare_parent_dentry(&parent, cache_dir);
236         cache_dentry = d_alloc(&parent, &dentry->d_name);
237
238         if (cache_dir->i_op->symlink)
239                 rc = cache_dir->i_op->symlink(cache_dir, cache_dentry, symname);
240         
241         cache_inode = igrab(cache_dentry->d_inode);
242         
243         inode = iget(dir->i_sb, cache_inode->i_ino);
244
245         if (inode)
246                 d_instantiate(dentry, inode);
247         else
248                 rc = -ENOENT;
249         
250         d_unalloc(cache_dentry);        
251         
252         RETURN(rc);                     
253 }
254
255 static int smfs_mkdir(struct inode * dir, 
256                       struct dentry * dentry, 
257                       int mode)
258 {
259         struct inode *cache_dir = I2CI(dir);
260         struct inode *cache_inode = NULL;
261         struct inode *inode = NULL;
262         struct dentry *cache_dentry;
263         struct dentry parent;
264         void   *handle;
265         int    rc = 0;
266
267         if (!cache_dir) 
268                 RETURN(-ENOENT);
269
270         handle = smfs_trans_start(cache_dir, KML_OPCODE_MKDIR);
271         if (IS_ERR(handle) ) {
272                 CERROR("smfs_do_mkdir: no space for transaction\n");
273                 RETURN(-ENOSPC);
274         }
275         
276         prepare_parent_dentry(&parent, cache_dir);
277         cache_dentry = d_alloc(&parent, &dentry->d_name);
278
279         pre_smfs_inode(dir, cache_dir);
280         lock_kernel();  
281         if (cache_dir->i_op->mkdir)
282                 rc = cache_dir->i_op->mkdir(cache_dir, cache_dentry, mode);
283
284         cache_inode = igrab(cache_dentry->d_inode);
285
286         inode = iget(dir->i_sb, cache_inode->i_ino);
287
288         if (!inode)
289                 GOTO(exit, rc = -ENOENT);
290  
291         d_instantiate(dentry, inode);   
292         /*Do KML post hook*/
293         if (smfs_do_kml(dir)) {
294                 rc = post_kml_mkdir(dir, dentry);
295                 GOTO(exit, rc);
296         }
297         post_smfs_inode(dir, cache_dir);
298 exit:
299         unlock_kernel();        
300         smfs_trans_commit(handle);
301         d_unalloc(cache_dentry);
302         RETURN(rc);             
303 }
304
305 static int  smfs_rmdir(struct inode * dir, 
306                        struct dentry *dentry) 
307 {
308         struct inode *cache_dir = I2CI(dir);
309         struct inode *cache_inode = I2CI(dentry->d_inode);
310         struct dentry *cache_dentry;
311         struct dentry parent;
312         int    rc = 0;
313
314         if (!cache_dir) 
315                 RETURN(-ENOENT);
316         
317         prepare_parent_dentry(&parent, cache_dir);
318         cache_dentry = d_alloc(&parent, &dentry->d_name);
319         d_add(cache_dentry, cache_inode);
320         igrab(cache_inode);
321         
322         pre_smfs_inode(dir, cache_dir);
323         pre_smfs_inode(dentry->d_inode, cache_dentry->d_inode);
324         
325         
326         if (cache_dir->i_op->rmdir)
327                 rc = cache_dir->i_op->rmdir(cache_dir, cache_dentry);
328
329         post_smfs_inode(dir, cache_dir);
330         post_smfs_inode(dentry->d_inode, cache_dentry->d_inode);
331         d_unalloc(cache_dentry);
332         RETURN(rc);             
333 }
334
335 static int smfs_mknod(struct inode * dir, struct dentry *dentry,
336                       int mode, int rdev)
337 {
338         struct inode *cache_dir = I2CI(dir);
339         struct inode *inode = NULL;
340         struct inode *cache_inode = NULL;
341         struct dentry *cache_dentry;
342         struct dentry parent;
343         int    rc = 0;
344
345         if (!cache_dir) 
346                 RETURN(-ENOENT);
347
348         prepare_parent_dentry(&parent, cache_dir);
349         cache_dentry = d_alloc(&parent, &dentry->d_name);
350         
351         pre_smfs_inode(dir, cache_dir);
352         pre_smfs_inode(dentry->d_inode, cache_dentry->d_inode);
353         
354         if (cache_dir->i_op->mknod)
355                 rc = cache_dir->i_op->mknod(cache_dir, cache_dentry, mode, rdev);
356         
357         if (cache_dentry->d_inode)
358                 cache_inode = igrab(cache_dentry->d_inode);
359         if (rc)
360                 GOTO(exit, rc);
361         
362         inode = iget(dir->i_sb, cache_inode->i_ino);
363         d_instantiate(dentry, inode);
364         post_smfs_inode(dir, cache_dir);
365         post_smfs_inode(dentry->d_inode, cache_dentry->d_inode);
366 exit:
367         d_unalloc(cache_dentry);
368         RETURN(rc);             
369 }
370 static int smfs_rename(struct inode * old_dir, struct dentry *old_dentry,
371                        struct inode * new_dir,struct dentry *new_dentry)
372 {
373         struct inode *cache_old_dir = I2CI(old_dir);
374         struct inode *cache_new_dir = I2CI(new_dir);
375         struct inode *cache_old_inode = I2CI(old_dentry->d_inode);
376         struct dentry *cache_old_dentry;
377         struct dentry *cache_new_dentry;
378         struct dentry parent_new;
379         struct dentry parent_old;
380         int    rc = 0;
381
382         if (!cache_old_dir || !cache_new_dir || !cache_old_inode) 
383                 RETURN(-ENOENT);
384         
385         prepare_parent_dentry(&parent_old, cache_old_dir);
386         cache_old_dentry = d_alloc(&parent_old, &old_dentry->d_name);
387         d_add(cache_old_dentry, cache_old_inode);
388         igrab(cache_old_inode); 
389
390         prepare_parent_dentry(&parent_new, cache_new_dir);
391         cache_new_dentry = d_alloc(&parent_new, &new_dentry->d_name);
392         
393         pre_smfs_inode(old_dir, cache_old_dir) ;
394         pre_smfs_inode(new_dir, cache_new_dir);
395         
396         if (cache_old_dir->i_op->rename)
397                 rc = cache_old_dir->i_op->rename(cache_old_dir, cache_old_dentry,
398                                                  cache_new_dir, cache_new_dentry);
399
400         post_smfs_inode(old_dir, cache_old_dir) ;
401         post_smfs_inode(new_dir, cache_new_dir);
402         if (cache_new_dentry->d_inode) {
403                 igrab(cache_new_dentry->d_inode);       
404         }
405         d_unalloc(cache_old_dentry);
406         d_unalloc(cache_new_dentry);
407         RETURN(rc);             
408 }
409
410 struct inode_operations smfs_dir_iops = {
411         create:         smfs_create,
412         lookup:         smfs_lookup,
413         lookup_raw:     smfs_lookup_raw,        /* BKL held */
414         link:           smfs_link,              /* BKL held */
415         unlink:         smfs_unlink,            /* BKL held */
416         symlink:        smfs_symlink,           /* BKL held */
417         mkdir:          smfs_mkdir,             /* BKL held */
418         rmdir:          smfs_rmdir,             /* BKL held */
419         mknod:          smfs_mknod,             /* BKL held */
420         rename:         smfs_rename,            /* BKL held */
421         setxattr:       smfs_setxattr,          /* BKL held */
422         getxattr:       smfs_getxattr,          /* BKL held */
423         listxattr:      smfs_listxattr,         /* BKL held */
424         removexattr:    smfs_removexattr,       /* BKL held */
425 };
426
427 static ssize_t smfs_read_dir(struct file *filp, char *buf, 
428                              size_t size, loff_t *ppos)
429 {
430         struct dentry *dentry = filp->f_dentry;
431         struct inode *cache_inode = NULL;
432         struct  file open_file;
433         struct  dentry open_dentry;
434         int    rc = 0;
435         
436         cache_inode = I2CI(dentry->d_inode);
437
438         if (!cache_inode) 
439                 RETURN(-EINVAL);
440
441         smfs_prepare_cachefile(dentry->d_inode, filp, cache_inode, 
442                                &open_file, &open_dentry);
443         
444         if (cache_inode->i_fop->read)
445                 rc = cache_inode->i_fop->read(&open_file, buf, size, ppos);
446
447         smfs_update_file(filp, &open_file);     
448         RETURN(rc);     
449 }
450
451 static int smfs_readdir(struct file * filp,
452                         void * dirent, 
453                         filldir_t filldir)
454 {
455         struct dentry *dentry = filp->f_dentry;
456         struct inode *cache_inode = NULL;
457         struct  file open_file;
458         struct  dentry open_dentry;
459         int    rc = 0;
460         
461         cache_inode = I2CI(dentry->d_inode);
462
463         if (!cache_inode) 
464                 RETURN(-EINVAL);
465
466         smfs_prepare_cachefile(dentry->d_inode, filp, cache_inode, 
467                                &open_file, &open_dentry);
468         
469         if (cache_inode->i_fop->readdir)
470                 rc = cache_inode->i_fop->readdir(&open_file, dirent, filldir);
471         
472         smfs_update_file(filp, &open_file);     
473         RETURN(rc);     
474 }
475
476 struct file_operations smfs_dir_fops = {
477         read:           smfs_read_dir,  
478         readdir:        smfs_readdir,           /* BKL held */
479         ioctl:          smfs_ioctl,             /* BKL held */
480         fsync:          smfs_fsync,         /* BKL held */
481 };