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