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