Whamcloud - gitweb
Update smfs: 1.fix bugs in smfs_link 2) decrease i_count in smfs_clear_inode
[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                 atomic_inc(&inode->i_count);
219                 duplicate_inode(cache_old_dentry.d_inode, inode);
220                 d_instantiate(dentry, inode);
221         }       
222         
223         smfs_clear_dentry(&cache_dentry);
224         smfs_clear_dentry(&cache_old_dentry);
225         RETURN(rc);
226 }
227
228 static int smfs_unlink(struct inode * dir, 
229                        struct dentry *dentry)
230 {
231         struct inode *cache_dir = I2CI(dir);
232         struct inode *cache_inode = I2CI(dentry->d_inode);
233         struct dentry cache_dentry;
234         struct dentry tmp; 
235         int    rc = 0;
236
237         if (!cache_dir || !cache_inode)
238                 RETURN(-ENOENT);
239         
240         prepare_parent_dentry(&tmp, cache_dir);
241         smfs_prepare_dentry(&cache_dentry, &tmp, &dentry->d_name);
242         d_add(&cache_dentry, cache_inode);
243
244         if (cache_dir->i_op->unlink)
245                 rc = cache_dir->i_op->unlink(cache_dir, &cache_dentry);
246         
247         duplicate_inode(cache_dentry.d_inode, dentry->d_inode);
248         duplicate_inode(cache_dir, dir);
249         
250         smfs_clear_dentry(&cache_dentry);
251         RETURN(rc);     
252 }
253
254 static int smfs_symlink (struct inode * dir,
255                          struct dentry *dentry, 
256                          const char * symname)
257 {
258         struct inode *cache_dir = I2CI(dir);
259         struct inode *cache_inode = NULL;
260         struct inode *inode = NULL;
261         struct dentry cache_dentry; 
262         struct dentry tmp; 
263         int    rc = 0;
264
265         if (!cache_dir) 
266                 RETURN(-ENOENT);
267         
268         prepare_parent_dentry(&tmp, cache_dir);
269         smfs_prepare_dentry(&cache_dentry, &tmp, &dentry->d_name);
270
271         if (cache_dir->i_op->symlink)
272                 rc = cache_dir->i_op->symlink(cache_dir, &cache_dentry, symname);
273         
274         cache_inode = cache_dentry.d_inode;
275         
276         inode = iget(dir->i_sb, cache_inode->i_ino);
277
278         if (inode)
279                 d_instantiate(dentry, inode);
280         else
281                 rc = -ENOENT;
282         
283         smfs_clear_dentry(&cache_dentry);
284         RETURN(rc);                     
285 }
286
287 static int smfs_mkdir(struct inode * dir, 
288                       struct dentry * dentry, 
289                       int mode)
290 {
291         struct inode *cache_dir = I2CI(dir);
292         struct inode *cache_inode = NULL;
293         struct inode *inode = NULL;
294         struct dentry cache_dentry;
295         struct dentry tmp;
296         int    rc = 0;
297
298         if (!cache_dir) 
299                 RETURN(-ENOENT);
300         
301         prepare_parent_dentry(&tmp, cache_dir);
302         smfs_prepare_dentry(&cache_dentry, &tmp, &dentry->d_name);
303         
304         if (cache_dir->i_op->mkdir)
305                 rc = cache_dir->i_op->mkdir(cache_dir, &cache_dentry, mode);
306
307         cache_inode = cache_dentry.d_inode;
308
309         inode = iget(dir->i_sb, cache_inode->i_ino);
310
311         if (!inode)
312                 GOTO(exit, rc = -ENOENT);
313  
314         d_instantiate(dentry, inode);   
315         duplicate_inode(cache_dir, dir);
316 exit:
317         smfs_clear_dentry(&cache_dentry);
318         RETURN(rc);             
319 }
320
321 static int  smfs_rmdir(struct inode * dir, 
322                        struct dentry *dentry) 
323 {
324         struct inode *cache_dir = I2CI(dir);
325         struct inode *cache_inode = I2CI(dentry->d_inode);
326         struct dentry cache_dentry;
327         struct dentry tmp;
328         int    rc = 0;
329
330         if (!cache_dir) 
331                 RETURN(-ENOENT);
332         
333         prepare_parent_dentry(&tmp, cache_dir);
334         smfs_prepare_dentry(&cache_dentry, &tmp, &dentry->d_name);
335         d_add(&cache_dentry, cache_inode);
336         
337         if (cache_dir->i_op->rmdir)
338                 rc = cache_dir->i_op->rmdir(cache_dir, &cache_dentry);
339
340         duplicate_inode(cache_dir, dir);
341         duplicate_inode(cache_dentry.d_inode, dentry->d_inode);
342
343         smfs_clear_dentry(&cache_dentry);
344         RETURN(rc);             
345 }
346
347 static int smfs_mknod(struct inode * dir, struct dentry *dentry,
348                       int mode, int rdev)
349 {
350         struct inode *cache_dir = I2CI(dir);
351         struct inode *inode = NULL;
352         struct inode *cache_inode = NULL;
353         struct dentry cache_dentry;
354         struct dentry tmp;
355         int    rc = 0;
356
357         if (!cache_dir) 
358                 RETURN(-ENOENT);
359
360         prepare_parent_dentry(&tmp, cache_dir);
361         smfs_prepare_dentry(&cache_dentry, &tmp, &dentry->d_name);
362                 
363         if (cache_dir->i_op->mknod)
364                 rc = cache_dir->i_op->mknod(cache_dir, &cache_dentry, mode, rdev);
365         
366         if (!rc) {
367                 cache_inode = cache_dentry.d_inode;
368                 inode = iget(dir->i_sb, cache_inode->i_ino);
369                 d_instantiate(dentry, inode);
370                 duplicate_inode(cache_dir, dir);
371                 duplicate_inode(cache_dentry.d_inode, dentry->d_inode);
372         }
373         smfs_clear_dentry(&cache_dentry);
374         RETURN(rc);             
375 }
376 static int smfs_rename(struct inode * old_dir, struct dentry *old_dentry,
377                        struct inode * new_dir,struct dentry *new_dentry)
378 {
379         struct inode *cache_old_dir = I2CI(old_dir);
380         struct inode *cache_new_dir = I2CI(new_dir);
381         struct inode *cache_old_inode = I2CI(old_dentry->d_inode);
382         struct inode *cache_new_inode = NULL;
383         struct inode *new_inode = NULL;
384         struct dentry cache_old_dentry;
385         struct dentry cache_new_dentry;
386         struct dentry tmp_new;
387         struct dentry tmp_old;
388         int    rc = 0;
389
390         if (!cache_old_dir || !cache_new_dir || !cache_old_inode) 
391                 RETURN(-ENOENT);
392         
393         prepare_parent_dentry(&tmp_old, cache_old_dir);
394         smfs_prepare_dentry(&cache_old_dentry, &tmp_old, &old_dentry->d_name); 
395         d_add(&cache_old_dentry, cache_old_inode);
396
397         prepare_parent_dentry(&tmp_new, cache_new_dir);
398         smfs_prepare_dentry(&cache_new_dentry, &tmp_new, &new_dentry->d_name); 
399         
400         if (cache_old_dir->i_op->rename)
401                 rc = cache_old_dir->i_op->rename(cache_old_dir, &cache_old_dentry,
402                                                  cache_new_dir, &cache_new_dentry);
403
404         duplicate_inode(cache_old_dir, old_dir);
405         duplicate_inode(cache_new_dir, new_dir);
406         smfs_clear_dentry(&cache_old_dentry);
407         smfs_clear_dentry(&cache_new_dentry);
408
409         RETURN(rc);             
410 }
411
412 struct inode_operations smfs_dir_iops = {
413         create:         smfs_create,
414         lookup:         smfs_lookup,
415         lookup_raw:     smfs_lookup_raw,        /* BKL held */
416         link:           smfs_link,              /* BKL held */
417         unlink:         smfs_unlink,            /* BKL held */
418         symlink:        smfs_symlink,           /* BKL held */
419         mkdir:          smfs_mkdir,             /* BKL held */
420         rmdir:          smfs_rmdir,             /* BKL held */
421         mknod:          smfs_mknod,             /* BKL held */
422         rename:         smfs_rename,            /* BKL held */
423         setxattr:       smfs_setxattr,          /* BKL held */
424         getxattr:       smfs_getxattr,          /* BKL held */
425         listxattr:      smfs_listxattr,         /* BKL held */
426         removexattr:    smfs_removexattr,       /* BKL held */
427 };
428
429 static ssize_t smfs_read_dir(struct file *filp, char *buf, 
430                              size_t size, loff_t *ppos)
431 {
432         struct dentry *dentry = filp->f_dentry;
433         struct inode *cache_inode = NULL;
434         struct  file open_file;
435         struct  dentry open_dentry;
436         int    rc = 0;
437         
438         cache_inode = I2CI(dentry->d_inode);
439
440         if (!cache_inode) 
441                 RETURN(-EINVAL);
442
443         smfs_prepare_cachefile(dentry->d_inode, filp, cache_inode, 
444                                &open_file, &open_dentry);
445         
446         if (cache_inode->i_fop->read)
447                 rc = cache_inode->i_fop->read(&open_file, buf, size, ppos);
448
449         smfs_update_file(filp, &open_file);     
450         RETURN(rc);     
451 }
452
453 static int smfs_readdir(struct file * filp,
454                         void * dirent, 
455                         filldir_t filldir)
456 {
457         struct dentry *dentry = filp->f_dentry;
458         struct inode *cache_inode = NULL;
459         struct  file open_file;
460         struct  dentry open_dentry;
461         int    rc = 0;
462         
463         cache_inode = I2CI(dentry->d_inode);
464
465         if (!cache_inode) 
466                 RETURN(-EINVAL);
467
468         smfs_prepare_cachefile(dentry->d_inode, filp, cache_inode, 
469                                &open_file, &open_dentry);
470         
471         if (cache_inode->i_fop->readdir)
472                 rc = cache_inode->i_fop->readdir(&open_file, dirent, filldir);
473         
474         smfs_update_file(filp, &open_file);     
475         RETURN(rc);     
476 }
477
478 struct file_operations smfs_dir_fops = {
479         read:           smfs_read_dir,  
480         readdir:        smfs_readdir,           /* BKL held */
481         ioctl:          smfs_ioctl,             /* BKL held */
482         fsync:          smfs_fsync,         /* BKL held */
483 };