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