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