Whamcloud - gitweb
get rid of some .h file we do not need in options.c
[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 static void prepare_parent_dentry(struct dentry *dentry, struct inode *inode)
18 {
19         atomic_set(&dentry->d_count, 1);
20         dentry->d_vfs_flags = 0;
21         dentry->d_flags = 0;
22         dentry->d_inode = inode;
23         dentry->d_op = NULL;
24         dentry->d_fsdata = NULL;
25         dentry->d_mounted = 0;
26         INIT_LIST_HEAD(&dentry->d_hash);
27         INIT_LIST_HEAD(&dentry->d_lru);
28         INIT_LIST_HEAD(&dentry->d_subdirs);
29         INIT_LIST_HEAD(&dentry->d_alias);
30 }
31
32 void d_unalloc(struct dentry *dentry)
33 {
34
35         list_del(&dentry->d_hash);
36         INIT_LIST_HEAD(&dentry->d_hash);
37         dput(dentry); /* this will free the dentry memory */
38 }
39
40 static int smfs_create(struct inode *dir, 
41                        struct dentry *dentry, 
42                        int mode)
43 {
44         struct  inode *cache_dir; 
45         struct  inode *cache_inode = NULL, *inode;
46         struct  dentry parent; 
47         struct  dentry *cache_dentry = NULL;
48         int     rc;
49         
50         ENTRY;
51         
52         cache_dir = I2CI(dir);
53         if (!cache_dir)
54                 RETURN(-ENOENT);
55        
56         prepare_parent_dentry(&parent, cache_dir);      
57         cache_dentry = d_alloc(&parent, &dentry->d_name);
58         
59         if (!cache_dentry) {
60                 RETURN(-ENOMEM);
61         }
62                  
63         if (cache_dir && cache_dir->i_op->create)
64                 rc = cache_dir->i_op->create(cache_dir, cache_dentry, mode);
65         
66         if (rc)
67                 GOTO(exit, rc);
68
69         cache_inode = igrab(cache_dentry->d_inode);
70         
71         inode = iget(dir->i_sb, cache_inode->i_ino);    
72
73         if (!inode) 
74                 GOTO(exit, rc = -ENOMEM);
75                 
76         d_instantiate(dentry, inode);   
77         
78         sm_set_inode_ops(cache_inode, inode);
79 exit:
80         d_unalloc(cache_dentry);
81         RETURN(rc);
82 }
83
84 static struct dentry *smfs_lookup(struct inode *dir,
85                                   struct dentry *dentry)
86 {
87         struct  inode *cache_dir; 
88         struct  inode *cache_inode = NULL, *inode;
89         struct  dentry parent; 
90         struct  dentry *cache_dentry = NULL;
91         struct  dentry *rc = NULL;
92         
93         ENTRY;
94         
95         cache_dir = I2CI(dir);
96         if (!cache_dir)
97                 RETURN(ERR_PTR(-ENOENT));
98         prepare_parent_dentry(&parent, cache_dir);      
99         cache_dentry = d_alloc(&parent, &dentry->d_name);
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 = igrab(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;
144         struct  dentry *cache_old_dentry;
145         struct  dentry parent; 
146         struct  dentry parent_old; 
147         int     rc = 0;
148
149         inode = old_dentry->d_inode;
150         
151         cache_old_inode = I2CI(inode);
152         
153         if (!cache_old_inode || !cache_dir) 
154                 RETURN(-ENOENT);
155         
156         prepare_parent_dentry(&parent, cache_dir);
157         cache_dentry = d_alloc(&parent, &dentry->d_name);
158         
159         prepare_parent_dentry(&parent_old, cache_dir);
160         cache_old_dentry = d_alloc(&parent_old, &dentry->d_name);
161         d_add(cache_old_dentry, cache_old_inode); 
162         
163         if (cache_dir->i_op->link)
164                 rc = cache_dir->i_op->link(cache_old_dentry, cache_dir, cache_dentry);          
165         
166         if (rc)
167                 GOTO(exit, rc); 
168         
169         atomic_inc(&inode->i_count);
170         duplicate_inode(cache_old_dentry->d_inode, inode);
171         d_instantiate(dentry, inode);
172
173 exit:
174         if (cache_dentry->d_inode)      
175                 igrab(cache_dentry->d_inode);
176         if (cache_old_dentry->d_inode)
177                 igrab(cache_old_dentry->d_inode);
178         
179         d_unalloc(cache_dentry);
180         d_unalloc(cache_old_dentry);
181
182         RETURN(rc);
183 }
184
185 static int smfs_unlink(struct inode * dir, 
186                        struct dentry *dentry)
187 {
188         struct inode *cache_dir = I2CI(dir);
189         struct inode *cache_inode = I2CI(dentry->d_inode);
190         struct dentry *cache_dentry;
191         struct dentry parent; 
192         int    rc = 0;
193
194         if (!cache_dir || !cache_inode)
195                 RETURN(-ENOENT);
196         
197         prepare_parent_dentry(&parent, cache_dir);
198         cache_dentry = d_alloc(&parent, &dentry->d_name);
199         d_add(cache_dentry, cache_inode);
200
201         if (cache_dir->i_op->unlink)
202                 rc = cache_dir->i_op->unlink(cache_dir, cache_dentry);
203
204         
205         duplicate_inode(cache_dentry->d_inode, dentry->d_inode);
206         duplicate_inode(cache_dir, dir);
207         
208         igrab(cache_dentry->d_inode);
209
210         d_unalloc(cache_dentry);        
211         RETURN(rc);     
212 }
213
214 static int smfs_symlink (struct inode * dir,
215                          struct dentry *dentry, 
216                          const char * symname)
217 {
218         struct inode *cache_dir = I2CI(dir);
219         struct inode *cache_inode = NULL;
220         struct inode *inode = NULL;
221         struct dentry *cache_dentry; 
222         struct dentry parent; 
223         int    rc = 0;
224
225         if (!cache_dir) 
226                 RETURN(-ENOENT);
227         
228         prepare_parent_dentry(&parent, cache_dir);
229         cache_dentry = d_alloc(&parent, &dentry->d_name);
230
231         if (cache_dir->i_op->symlink)
232                 rc = cache_dir->i_op->symlink(cache_dir, cache_dentry, symname);
233         
234         cache_inode = igrab(cache_dentry->d_inode);
235         
236         inode = iget(dir->i_sb, cache_inode->i_ino);
237
238         if (inode)
239                 d_instantiate(dentry, inode);
240         else
241                 rc = -ENOENT;
242         
243         d_unalloc(cache_dentry);        
244         
245         RETURN(rc);                     
246 }
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;
256         struct dentry parent;
257         int    rc = 0;
258
259         if (!cache_dir) 
260                 RETURN(-ENOENT);
261         
262         prepare_parent_dentry(&parent, cache_dir);
263         cache_dentry = d_alloc(&parent, &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 = igrab(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
282 static int  smfs_rmdir(struct inode * dir, 
283                        struct dentry *dentry) 
284 {
285         struct inode *cache_dir = I2CI(dir);
286         struct inode *cache_inode = I2CI(dentry->d_inode);
287         struct dentry *cache_dentry;
288         struct dentry parent;
289         int    rc = 0;
290
291         if (!cache_dir) 
292                 RETURN(-ENOENT);
293         
294         prepare_parent_dentry(&parent, cache_dir);
295         cache_dentry = d_alloc(&parent, &dentry->d_name);
296         d_add(cache_dentry, cache_inode);
297         
298         igrab(cache_inode);
299         
300         if (cache_dir->i_op->rmdir)
301                 rc = cache_dir->i_op->rmdir(cache_dir, cache_dentry);
302
303         duplicate_inode(cache_dir, dir);
304         duplicate_inode(cache_dentry->d_inode, dentry->d_inode);
305
306         d_unalloc(cache_dentry);
307         RETURN(rc);             
308 }
309
310 static int smfs_mknod(struct inode * dir, struct dentry *dentry,
311                       int mode, int rdev)
312 {
313         struct inode *cache_dir = I2CI(dir);
314         struct inode *inode = NULL;
315         struct inode *cache_inode = NULL;
316         struct dentry *cache_dentry;
317         struct dentry parent;
318         int    rc = 0;
319
320         if (!cache_dir) 
321                 RETURN(-ENOENT);
322
323         prepare_parent_dentry(&parent, cache_dir);
324         cache_dentry = d_alloc(&parent, &dentry->d_name);
325         
326         if (cache_dir->i_op->mknod)
327                 rc = cache_dir->i_op->mknod(cache_dir, cache_dentry, mode, rdev);
328         
329         if (cache_dentry->d_inode)
330                 cache_inode = igrab(cache_dentry->d_inode);
331         if (rc)
332                 GOTO(exit, rc);
333         
334         inode = iget(dir->i_sb, cache_inode->i_ino);
335         d_instantiate(dentry, inode);
336         duplicate_inode(cache_dir, dir);
337         duplicate_inode(cache_dentry->d_inode, dentry->d_inode);
338 exit:
339         d_unalloc(cache_dentry);
340         RETURN(rc);             
341 }
342 static int smfs_rename(struct inode * old_dir, struct dentry *old_dentry,
343                        struct inode * new_dir,struct dentry *new_dentry)
344 {
345         struct inode *cache_old_dir = I2CI(old_dir);
346         struct inode *cache_new_dir = I2CI(new_dir);
347         struct inode *cache_old_inode = I2CI(old_dentry->d_inode);
348         struct dentry *cache_old_dentry;
349         struct dentry *cache_new_dentry;
350         struct dentry parent_new;
351         struct dentry parent_old;
352         int    rc = 0;
353
354         if (!cache_old_dir || !cache_new_dir || !cache_old_inode) 
355                 RETURN(-ENOENT);
356         
357         prepare_parent_dentry(&parent_old, cache_old_dir);
358         cache_old_dentry = d_alloc(&parent_old, &old_dentry->d_name);
359         d_add(cache_old_dentry, cache_old_inode);
360         igrab(cache_old_inode); 
361
362         prepare_parent_dentry(&parent_new, cache_new_dir);
363         cache_new_dentry = d_alloc(&parent_new, &new_dentry->d_name);
364         
365         if (cache_old_dir->i_op->rename)
366                 rc = cache_old_dir->i_op->rename(cache_old_dir, cache_old_dentry,
367                                                  cache_new_dir, cache_new_dentry);
368
369         duplicate_inode(cache_old_dir, old_dir);
370         duplicate_inode(cache_new_dir, new_dir);
371         if (cache_new_dentry->d_inode) {
372                 igrab(cache_new_dentry->d_inode);       
373         }
374         d_unalloc(cache_old_dentry);
375         d_unalloc(cache_new_dentry);
376         RETURN(rc);             
377 }
378
379 struct inode_operations smfs_dir_iops = {
380         create:         smfs_create,
381         lookup:         smfs_lookup,
382         lookup_raw:     smfs_lookup_raw,        /* BKL held */
383         link:           smfs_link,              /* BKL held */
384         unlink:         smfs_unlink,            /* BKL held */
385         symlink:        smfs_symlink,           /* BKL held */
386         mkdir:          smfs_mkdir,             /* BKL held */
387         rmdir:          smfs_rmdir,             /* BKL held */
388         mknod:          smfs_mknod,             /* BKL held */
389         rename:         smfs_rename,            /* BKL held */
390         setxattr:       smfs_setxattr,          /* BKL held */
391         getxattr:       smfs_getxattr,          /* BKL held */
392         listxattr:      smfs_listxattr,         /* BKL held */
393         removexattr:    smfs_removexattr,       /* BKL held */
394 };
395
396 static ssize_t smfs_read_dir(struct file *filp, char *buf, 
397                              size_t size, loff_t *ppos)
398 {
399         struct dentry *dentry = filp->f_dentry;
400         struct inode *cache_inode = NULL;
401         struct  file open_file;
402         struct  dentry open_dentry;
403         int    rc = 0;
404         
405         cache_inode = I2CI(dentry->d_inode);
406
407         if (!cache_inode) 
408                 RETURN(-EINVAL);
409
410         smfs_prepare_cachefile(dentry->d_inode, filp, cache_inode, 
411                                &open_file, &open_dentry);
412         
413         if (cache_inode->i_fop->read)
414                 rc = cache_inode->i_fop->read(&open_file, buf, size, ppos);
415
416         smfs_update_file(filp, &open_file);     
417         RETURN(rc);     
418 }
419
420 static int smfs_readdir(struct file * filp,
421                         void * dirent, 
422                         filldir_t filldir)
423 {
424         struct dentry *dentry = filp->f_dentry;
425         struct inode *cache_inode = NULL;
426         struct  file open_file;
427         struct  dentry open_dentry;
428         int    rc = 0;
429         
430         cache_inode = I2CI(dentry->d_inode);
431
432         if (!cache_inode) 
433                 RETURN(-EINVAL);
434
435         smfs_prepare_cachefile(dentry->d_inode, filp, cache_inode, 
436                                &open_file, &open_dentry);
437         
438         if (cache_inode->i_fop->readdir)
439                 rc = cache_inode->i_fop->readdir(&open_file, dirent, filldir);
440         
441         smfs_update_file(filp, &open_file);     
442         RETURN(rc);     
443 }
444
445 struct file_operations smfs_dir_fops = {
446         read:           smfs_read_dir,  
447         readdir:        smfs_readdir,           /* BKL held */
448         ioctl:          smfs_ioctl,             /* BKL held */
449         fsync:          smfs_fsync,         /* BKL held */
450 };