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