Whamcloud - gitweb
Update smfs: fix bugs of smfs_create
[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 void smfs_clear_dentry(struct dentry *dentry)
18 {
19         struct qstr *name = NULL; 
20
21         if (dentry) {   
22                 if (!atomic_dec_and_lock(&dentry->d_count, &dcache_lock))
23                         return;
24                 list_del(&dentry->d_hash);
25                 INIT_LIST_HEAD(&dentry->d_hash);
26                 list_del(&dentry->d_child);
27                 if (dentry->d_inode) {
28                         dentry->d_inode = NULL;
29                         list_del_init(&dentry->d_alias);
30                 }
31         
32                 name = &(dentry->d_name);
33                 if (name->len > DNAME_INLINE_LEN-1) {
34                         SM_FREE((char *)name->name, NAME_ALLOC_LEN(name->len));
35                 }
36         }
37 }
38
39 int smfs_prepare_dentry(struct dentry *dentry, 
40                         struct dentry *parent,
41                         struct qstr *name)
42 {
43         char *str = NULL;
44
45         if (name->len > DNAME_INLINE_LEN-1) {
46                 SM_ALLOC(str, NAME_ALLOC_LEN(name->len));
47                 if (!str) 
48                         return (-ENOMEM);
49         } else
50                 str = dentry->d_iname; 
51
52         memcpy(str, name->name, name->len);
53         str[name->len] = 0;
54         
55         atomic_set(&dentry->d_count, 1);
56         dentry->d_vfs_flags = 0;
57         dentry->d_flags = 0;
58         dentry->d_inode = NULL;
59         dentry->d_parent = NULL;
60         dentry->d_sb = NULL;
61         dentry->d_name.name = str;
62         dentry->d_name.len = name->len;
63         dentry->d_name.hash = name->hash;
64         dentry->d_op = NULL;
65         dentry->d_fsdata = NULL;
66         dentry->d_mounted = 0;
67         INIT_LIST_HEAD(&dentry->d_hash);
68         INIT_LIST_HEAD(&dentry->d_lru);
69         INIT_LIST_HEAD(&dentry->d_subdirs);
70         INIT_LIST_HEAD(&dentry->d_alias);
71         
72         if (parent) {
73                 dentry->d_parent = dget(parent);
74                 dentry->d_sb = parent->d_sb;
75                 list_add(&dentry->d_child, &parent->d_subdirs);
76         } else
77                 INIT_LIST_HEAD(&dentry->d_child);
78
79         return 0;
80 }                                                                                                                                                                                                     
81 static void prepare_parent_dentry(struct dentry *dentry, struct inode *inode)
82 {
83         atomic_set(&dentry->d_count, 1);
84         dentry->d_vfs_flags = 0;
85         dentry->d_flags = 0;
86         dentry->d_inode = inode;
87         dentry->d_op = NULL;
88         dentry->d_fsdata = NULL;
89         dentry->d_mounted = 0;
90         INIT_LIST_HEAD(&dentry->d_hash);
91         INIT_LIST_HEAD(&dentry->d_lru);
92         INIT_LIST_HEAD(&dentry->d_subdirs);
93         INIT_LIST_HEAD(&dentry->d_alias);
94 }
95
96 static int smfs_create(struct inode *dir, 
97                        struct dentry *dentry, 
98                        int mode)
99 {
100         struct  inode *cache_dir; 
101         struct  inode *cache_inode = NULL, *inode;
102         struct  dentry parent; 
103         struct  dentry cache_dentry;
104         int     rc;
105         
106         ENTRY;
107         
108         cache_dir = I2CI(dir);
109         if (!cache_dir)
110                 RETURN(-ENOENT);
111        
112         prepare_parent_dentry(&parent, cache_dir);      
113         smfs_prepare_dentry(&cache_dentry, &parent, &dentry->d_name);
114          
115         if (cache_dir && cache_dir->i_op->create)
116                 rc = cache_dir->i_op->create(cache_dir, &cache_dentry, mode);
117         if (rc)
118                 GOTO(exit, rc);
119  
120         cache_inode = cache_dentry.d_inode;
121         
122         inode = iget(dir->i_sb, cache_inode->i_ino);    
123
124         if (!inode) 
125                 GOTO(exit, rc = -ENOMEM);
126                 
127         d_instantiate(dentry, inode);   
128         
129         sm_set_inode_ops(cache_inode, inode);
130 exit:
131         smfs_clear_dentry(&cache_dentry);       
132         RETURN(rc);
133 }
134
135 static struct dentry *smfs_lookup(struct inode *dir,
136                                   struct dentry *dentry)
137 {
138         struct  inode *cache_dir; 
139         struct  inode *cache_inode = NULL, *inode;
140         struct  dentry tmp; 
141         struct  dentry cache_dentry;
142         struct  dentry *rc = NULL;
143         
144         ENTRY;
145         
146         cache_dir = I2CI(dir);
147         if (!cache_dir)
148                 RETURN(ERR_PTR(-ENOENT));
149         prepare_parent_dentry(&tmp, cache_dir);      
150         smfs_prepare_dentry(&cache_dentry, &tmp, &dentry->d_name);
151       
152         if(cache_dir && cache_dir->i_op->lookup)
153                 rc = cache_dir->i_op->lookup(cache_dir, &cache_dentry);
154
155         if (rc || !cache_dentry.d_inode || 
156             is_bad_inode(cache_dentry.d_inode) ||
157             IS_ERR(cache_dentry.d_inode)) {
158                 GOTO(exit, rc); 
159         }
160
161         cache_inode = cache_dentry.d_inode;
162         
163         inode = iget(dir->i_sb, cache_inode->i_ino);    
164                 
165         d_add(dentry, inode);   
166 exit:
167         smfs_clear_dentry(&cache_dentry);       
168         RETURN(rc);
169 }                      
170
171 static int smfs_lookup_raw(struct inode *dir, const char *name,
172                            int len, ino_t *data)
173 {
174         struct  inode *cache_dir; 
175         int     rc = 0;
176
177         cache_dir = I2CI(dir);
178
179         if (!cache_dir) 
180                 RETURN(-ENOENT);
181         
182         if (cache_dir->i_op->lookup_raw)
183                 rc = cache_dir->i_op->lookup_raw(cache_dir, name, len, data);           
184                 
185         RETURN(rc);
186 }
187
188 static int smfs_link(struct dentry * old_dentry,
189                      struct inode * dir, struct dentry *dentry)
190 {
191         struct  inode *cache_old_inode = NULL; 
192         struct  inode *cache_dir = I2CI(dir); 
193         struct  inode *inode = NULL; 
194         struct  dentry cache_dentry;
195         struct  dentry cache_old_dentry;
196         struct  dentry tmp; 
197         struct  dentry tmp_old; 
198         int     rc = 0;
199
200         inode = old_dentry->d_inode;
201         
202         cache_old_inode = I2CI(inode);
203         
204         if (!cache_old_inode || !cache_dir) 
205                 RETURN(-ENOENT);
206         
207         prepare_parent_dentry(&tmp, cache_dir);
208         smfs_prepare_dentry(&cache_dentry, &tmp, &dentry->d_name);
209         
210         prepare_parent_dentry(&tmp_old, cache_dir);
211         smfs_prepare_dentry(&cache_old_dentry, &tmp_old, &dentry->d_name);
212         d_add(&cache_old_dentry, cache_old_inode); 
213         
214         if (cache_dir->i_op->link)
215                 rc = cache_dir->i_op->link(&cache_old_dentry, cache_dir, &cache_dentry);                
216         
217         if (rc == 0) {
218                 d_instantiate(dentry, inode);
219         }       
220         
221         smfs_clear_dentry(&cache_dentry);
222         smfs_clear_dentry(&cache_old_dentry);
223         RETURN(rc);
224 }
225
226 static int smfs_unlink(struct inode * dir, 
227                        struct dentry *dentry)
228 {
229         struct inode *cache_dir = I2CI(dir);
230         struct inode *cache_inode = I2CI(dentry->d_inode);
231         struct dentry cache_dentry;
232         struct dentry tmp; 
233         int    rc = 0;
234
235         if (!cache_dir || !cache_inode)
236                 RETURN(-ENOENT);
237         
238         prepare_parent_dentry(&tmp, cache_dir);
239         smfs_prepare_dentry(&cache_dentry, &tmp, &dentry->d_name);
240         d_add(&cache_dentry, cache_inode);
241
242         if (cache_dir->i_op->unlink)
243                 rc = cache_dir->i_op->unlink(cache_dir, &cache_dentry);
244         
245         duplicate_inode(cache_dentry.d_inode, dentry->d_inode);
246         duplicate_inode(cache_dir, dir);
247         
248         smfs_clear_dentry(&cache_dentry);
249         RETURN(rc);     
250 }
251
252 static int smfs_symlink (struct inode * dir,
253                          struct dentry *dentry, 
254                          const char * symname)
255 {
256         struct inode *cache_dir = I2CI(dir);
257         struct inode *cache_inode = NULL;
258         struct inode *inode = NULL;
259         struct dentry cache_dentry; 
260         struct dentry tmp; 
261         int    rc = 0;
262
263         if (!cache_dir) 
264                 RETURN(-ENOENT);
265         
266         prepare_parent_dentry(&tmp, cache_dir);
267         smfs_prepare_dentry(&cache_dentry, &tmp, &dentry->d_name);
268
269         if (cache_dir->i_op->symlink)
270                 rc = cache_dir->i_op->symlink(cache_dir, &cache_dentry, symname);
271         
272         cache_inode = cache_dentry.d_inode;
273         
274         inode = iget(dir->i_sb, cache_inode->i_ino);
275
276         if (inode)
277                 d_instantiate(dentry, inode);
278         else
279                 rc = -ENOENT;
280         
281         smfs_clear_dentry(&cache_dentry);
282         RETURN(rc);                     
283 }
284
285 static int smfs_mkdir(struct inode * dir, 
286                       struct dentry * dentry, 
287                       int mode)
288 {
289         struct inode *cache_dir = I2CI(dir);
290         struct inode *cache_inode = NULL;
291         struct inode *inode = NULL;
292         struct dentry cache_dentry;
293         struct dentry tmp;
294         int    rc = 0;
295
296         if (!cache_dir) 
297                 RETURN(-ENOENT);
298         
299         prepare_parent_dentry(&tmp, cache_dir);
300         smfs_prepare_dentry(&cache_dentry, &tmp, &dentry->d_name);
301         
302         if (cache_dir->i_op->mkdir)
303                 rc = cache_dir->i_op->mkdir(cache_dir, &cache_dentry, mode);
304
305         cache_inode = cache_dentry.d_inode;
306
307         inode = iget(dir->i_sb, cache_inode->i_ino);
308
309         if (!inode)
310                 GOTO(exit, rc = -ENOENT);
311  
312         d_instantiate(dentry, inode);   
313         duplicate_inode(cache_dir, dir);
314 exit:
315         smfs_clear_dentry(&cache_dentry);
316         RETURN(rc);             
317 }
318
319 static int  smfs_rmdir(struct inode * dir, 
320                        struct dentry *dentry) 
321 {
322         struct inode *cache_dir = I2CI(dir);
323         struct inode *cache_inode = I2CI(dentry->d_inode);
324         struct dentry cache_dentry;
325         struct dentry tmp;
326         int    rc = 0;
327
328         if (!cache_dir) 
329                 RETURN(-ENOENT);
330         
331         prepare_parent_dentry(&tmp, cache_dir);
332         smfs_prepare_dentry(&cache_dentry, &tmp, &dentry->d_name);
333         d_add(&cache_dentry, cache_inode);
334         
335         if (cache_dir->i_op->rmdir)
336                 rc = cache_dir->i_op->rmdir(cache_dir, &cache_dentry);
337
338         duplicate_inode(cache_dir, dir);
339         duplicate_inode(cache_dentry.d_inode, dentry->d_inode);
340
341         smfs_clear_dentry(&cache_dentry);
342         RETURN(rc);             
343 }
344
345 static int smfs_mknod(struct inode * dir, struct dentry *dentry,
346                       int mode, int rdev)
347 {
348         struct inode *cache_dir = I2CI(dir);
349         struct inode *inode = NULL;
350         struct inode *cache_inode = NULL;
351         struct dentry cache_dentry;
352         struct dentry tmp;
353         int    rc = 0;
354
355         if (!cache_dir) 
356                 RETURN(-ENOENT);
357
358         prepare_parent_dentry(&tmp, cache_dir);
359         smfs_prepare_dentry(&cache_dentry, &tmp, &dentry->d_name);
360                 
361         if (cache_dir->i_op->mknod)
362                 rc = cache_dir->i_op->mknod(cache_dir, &cache_dentry, mode, rdev);
363         
364         if (!rc) {
365                 cache_inode = cache_dentry.d_inode;
366                 inode = iget(dir->i_sb, cache_inode->i_ino);
367                 d_instantiate(dentry, inode);
368                 duplicate_inode(cache_dir, dir);
369                 duplicate_inode(cache_dentry.d_inode, dentry->d_inode);
370         }
371         smfs_clear_dentry(&cache_dentry);
372         RETURN(rc);             
373 }
374 static int smfs_rename(struct inode * old_dir, struct dentry *old_dentry,
375                        struct inode * new_dir,struct dentry *new_dentry)
376 {
377         struct inode *cache_old_dir = I2CI(old_dir);
378         struct inode *cache_new_dir = I2CI(new_dir);
379         struct inode *cache_old_inode = I2CI(old_dentry->d_inode);
380         struct inode *cache_new_inode = NULL;
381         struct inode *new_inode = NULL;
382         struct dentry cache_old_dentry;
383         struct dentry cache_new_dentry;
384         struct dentry tmp_new;
385         struct dentry tmp_old;
386         int    rc = 0;
387
388         if (!cache_old_dir || !cache_new_dir || !cache_old_inode) 
389                 RETURN(-ENOENT);
390         
391         prepare_parent_dentry(&tmp_old, cache_old_dir);
392         smfs_prepare_dentry(&cache_old_dentry, &tmp_old, &old_dentry->d_name); 
393         d_add(&cache_old_dentry, cache_old_inode);
394
395         prepare_parent_dentry(&tmp_new, cache_new_dir);
396         smfs_prepare_dentry(&cache_new_dentry, &tmp_new, &new_dentry->d_name); 
397         
398         if (cache_old_dir->i_op->rename)
399                 rc = cache_old_dir->i_op->rename(cache_old_dir, &cache_old_dentry,
400                                                  cache_new_dir, &cache_new_dentry);
401
402         duplicate_inode(cache_old_dir, old_dir);
403         duplicate_inode(cache_new_dir, new_dir);
404         smfs_clear_dentry(&cache_old_dentry);
405         smfs_clear_dentry(&cache_new_dentry);
406
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 };