Whamcloud - gitweb
774bde8ffca041410638acaf224b14cf374b0ca5
[fs/lustre-release.git] / lustre / smfs / dir.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Copyright (C) 2004 Cluster File Systems, Inc.
5  *
6  *   This file is part of Lustre, http://www.lustre.org.
7  *
8  *   Lustre is free software; you can redistribute it and/or
9  *   modify it under the terms of version 2 of the GNU General Public
10  *   License as published by the Free Software Foundation.
11  *
12  *   Lustre is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with Lustre; if not, write to the Free Software
19  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  *
21  */
22
23 #define DEBUG_SUBSYSTEM S_SM
24
25 #include <linux/module.h>
26 #include <linux/kernel.h>
27 #include <linux/string.h>
28 #include <linux/slab.h>
29 #include <linux/stat.h>
30 #include <linux/unistd.h>
31 #include <linux/smp_lock.h>
32 #include <linux/obd_class.h>
33 #include <linux/obd_support.h>
34 #include <linux/lustre_lib.h>
35 #include <linux/lustre_idl.h>
36 #include <linux/lustre_fsfilt.h>
37 #include <linux/lustre_smfs.h>
38 #include <linux/lustre_snap.h>
39
40 #include "smfs_internal.h"
41
42 #define NAME_ALLOC_LEN(len)     ((len+16) & ~15)
43
44 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
45 static int smfs_create(struct inode *dir, struct dentry *dentry,
46                        int mode)
47 #else
48 static int smfs_create(struct inode *dir, struct dentry *dentry,
49                        int mode, struct nameidata *nd)
50 #endif
51 {
52         struct inode  *inode = NULL;
53         struct inode  *cache_dir = NULL;
54         struct dentry *cache_dentry = NULL;
55         struct dentry *cache_parent = NULL;
56         void *handle = NULL;
57         struct inode *cache_inode = NULL;
58         int rc = 0;
59
60         ENTRY;
61
62         cache_dir = I2CI(dir);
63         LASSERT(cache_dir && cache_dir->i_op->create);
64
65         //lock_kernel();
66         cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry);
67         cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry);
68
69         if (!cache_dentry || !cache_parent)
70                 GOTO(exit, rc = -ENOMEM);
71        
72         pre_smfs_inode(dir, cache_dir);
73         
74         handle = smfs_trans_start(dir, FSFILT_OP_CREATE, NULL);
75         if (IS_ERR(handle))
76                        GOTO(exit, rc = -ENOSPC);
77         
78         SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_CREATE, handle,
79                   PRE_HOOK, rc, exit);
80         
81 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
82         rc = cache_dir->i_op->create(cache_dir, cache_dentry, mode);
83 #else
84         rc = cache_dir->i_op->create(cache_dir, cache_dentry, mode, nd);
85 #endif
86         cache_inode = cache_dentry->d_inode;
87         
88         if (rc)
89                 GOTO(exit, rc);
90         
91         SMFS_IGET(dir, cache_inode->i_ino, inode, rc, exit); 
92
93         d_instantiate(dentry, inode);
94
95         SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_CREATE, handle,
96                   POST_HOOK, rc,  exit); 
97
98         post_smfs_inode(dir, cache_dir);
99
100 exit:
101         //unlock_kernel();
102         post_smfs_dentry(cache_dentry);
103         post_smfs_dentry(cache_parent);
104         smfs_trans_commit(dir, handle, 0);
105         RETURN(rc);
106 }
107
108 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
109 static struct dentry *smfs_lookup(struct inode *dir, struct dentry *dentry)
110 #else
111 static struct dentry *smfs_lookup(struct inode *dir, struct dentry *dentry,
112                                   struct nameidata *nd)
113 #endif
114 {
115         struct inode *cache_dir;
116         struct inode *cache_inode;
117         struct inode *inode = NULL;
118         struct dentry *cache_dentry = NULL;
119         struct dentry *cache_parent = NULL;
120         struct dentry *rdentry = NULL;
121         int rc = 0;
122
123         ENTRY;
124
125         cache_dir = I2CI(dir);
126         if (!cache_dir || !cache_dir->i_op->lookup)
127                 RETURN(ERR_PTR(-ENOENT));
128
129         /* preparing artificial backing fs dentries. */
130         cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry->d_parent);
131         cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry);
132
133         if (!cache_dentry || !cache_parent)
134                 RETURN (ERR_PTR(-ENOMEM));
135
136         SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_LOOKUP, NULL, 
137                   PRE_HOOK, rc, exit); 
138
139         /* perform lookup in backing fs. */
140 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
141         rdentry = cache_dir->i_op->lookup(cache_dir, cache_dentry);
142 #else
143         rdentry = cache_dir->i_op->lookup(cache_dir, cache_dentry, nd);
144 #endif
145         cache_inode = cache_dentry->d_inode;
146         
147         if (rdentry) {
148                 if (IS_ERR(rdentry))
149                         GOTO(exit, rdentry);
150         
151                 cache_inode = rdentry->d_inode;
152                 dput(rdentry);
153                 rdentry = NULL;
154         }
155         
156         if (cache_inode) 
157                 SMFS_IGET(dir, cache_inode->i_ino, inode, rc, exit);
158      
159         
160         //rdentry = d_splice_alias(inode, dentry);
161         d_add(dentry, inode);
162         //CDEBUG(D_INODE, "dir %p (inode %p)\n", dir, cache_dir);
163
164         SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_LOOKUP, NULL, POST_HOOK, rc, 
165                   exit); 
166 exit:
167         post_smfs_dentry(cache_dentry);
168         post_smfs_dentry(cache_parent);
169         return rdentry;
170 }
171
172 static int smfs_link(struct dentry *old_dentry,
173                      struct inode *dir, struct dentry *dentry)
174 {
175         struct inode *cache_old_inode = NULL;
176         struct inode *cache_dir = NULL;
177         struct inode *old_inode = NULL;
178         struct dentry *cache_dentry = NULL;
179         struct dentry *cache_old_dentry = NULL;
180         struct dentry *cache_parent = NULL;
181         void *handle = NULL;
182         int rc = 0;
183
184         ENTRY;
185
186         cache_dir = I2CI(dir);
187         if (!cache_dir || !cache_dir->i_op->link)
188                 GOTO(exit, rc = -ENOENT);
189         
190         old_inode = old_dentry->d_inode;        
191         cache_old_inode = I2CI(old_inode);
192         if (!cache_old_inode)
193                 GOTO(exit, rc = -ENOENT);
194         
195         cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry);
196         cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry);
197         if (!cache_parent || !cache_dentry)
198                 GOTO(exit, rc = -ENOMEM);
199
200         cache_old_dentry = pre_smfs_dentry(NULL, cache_old_inode,
201                                            old_dentry);
202         if (!cache_old_dentry)
203                 GOTO(exit, rc = -ENOMEM);
204         
205         pre_smfs_inode(dir, cache_dir);
206         pre_smfs_inode(old_inode, cache_old_inode);
207
208         handle = smfs_trans_start(dir, FSFILT_OP_LINK, NULL);
209         if (IS_ERR(handle))
210                  GOTO(exit, rc = -ENOSPC);
211         
212         //lock_kernel();
213         SMFS_HOOK(dir, old_dentry, NULL, NULL, HOOK_LINK, handle,
214                   PRE_HOOK, rc, exit); 
215
216         rc = cache_dir->i_op->link(cache_old_dentry, cache_dir,
217                                            cache_dentry);
218         if (rc)
219                 GOTO(exit, rc);
220
221         atomic_inc(&old_inode->i_count);
222         d_instantiate(dentry, old_inode);
223
224         post_smfs_inode(old_inode, cache_old_inode);
225         post_smfs_inode(dir, cache_dir);
226
227         SMFS_HOOK(dir, old_dentry, dentry, NULL, HOOK_LINK, handle,
228                   POST_HOOK, rc, exit); 
229 exit:
230         //unlock_kernel();
231         post_smfs_dentry(cache_dentry);
232         post_smfs_dentry(cache_parent);
233         post_smfs_dentry(cache_old_dentry);
234         smfs_trans_commit(dir, handle, 0);
235         RETURN(rc);
236 }
237
238 static int smfs_unlink(struct inode * dir,
239                        struct dentry *dentry)
240 {
241         struct inode *cache_dir = I2CI(dir);
242         struct inode *cache_inode = I2CI(dentry->d_inode);
243         struct dentry *cache_dentry;
244         struct dentry *cache_parent;
245         void   *handle = NULL;
246         int    rc = 0;
247         int    mode = 0;
248
249         ENTRY;
250         
251         if (!cache_dir || !cache_inode || !cache_dir->i_op->unlink)
252                 RETURN(-ENOENT);
253
254         cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry);
255         cache_dentry = pre_smfs_dentry(cache_parent, cache_inode, dentry);
256
257         if (!cache_parent || !cache_dentry)
258                 GOTO(exit, rc = -ENOMEM);
259                 
260         //lock_kernel();
261         pre_smfs_inode(dir, cache_dir);
262         pre_smfs_inode(dentry->d_inode, cache_inode);
263
264         handle = smfs_trans_start(dir, FSFILT_OP_UNLINK, NULL);
265         if (IS_ERR(handle))
266                 GOTO(exit, rc = -ENOSPC);
267
268         SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_UNLINK, handle, PRE_HOOK, rc, 
269                   exit); 
270         
271         rc = cache_dir->i_op->unlink(cache_dir, cache_dentry);
272         if (rc)
273                 GOTO(exit, rc);
274         
275         post_smfs_inode(dentry->d_inode, cache_dentry->d_inode);
276         post_smfs_inode(dir, cache_dir);
277         //unlock_kernel();
278         
279         SMFS_HOOK(dir, dentry, &mode, NULL, HOOK_UNLINK, handle, POST_HOOK, 
280                   rc, exit); 
281 exit:
282         smfs_trans_commit(dir, handle, 0);
283         post_smfs_dentry(cache_dentry);
284         post_smfs_dentry(cache_parent);
285         RETURN(rc);
286 }
287
288 static int smfs_symlink(struct inode *dir, struct dentry *dentry,
289                         const char *symname)
290 {
291         struct inode *cache_dir = I2CI(dir);
292         struct inode *inode = NULL;
293         struct dentry *cache_dentry;
294         struct dentry *cache_parent;
295         void   *handle = NULL;
296         int    rc = 0, tgt_len;
297
298         ENTRY;
299         
300         if (!cache_dir || !cache_dir->i_op->symlink)
301                 RETURN(-ENOENT);
302
303         cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry);
304         cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry);
305
306         if (!cache_parent || !cache_dentry)
307                 GOTO(exit, rc = -ENOMEM);
308        
309         pre_smfs_inode(dir, cache_dir);
310         
311         handle = smfs_trans_start(dir, FSFILT_OP_SYMLINK, NULL);
312         if (IS_ERR(handle))
313                 GOTO(exit, rc = -ENOSPC);
314         
315         //lock_kernel();
316         SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_SYMLINK, handle, PRE_HOOK, rc, 
317                   exit); 
318         
319         rc = cache_dir->i_op->symlink(cache_dir, cache_dentry, symname);
320         if (rc)
321                 GOTO(exit, rc);
322         
323         SMFS_IGET(dir, cache_dentry->d_inode->i_ino, inode, rc, exit); 
324         
325         d_instantiate(dentry, inode);
326         post_smfs_inode(dir, cache_dir);
327         
328         tgt_len = strlen(symname) + 1;
329         SMFS_HOOK(dir, dentry, (char *)symname, &tgt_len, HOOK_SYMLINK, handle, 
330                   POST_HOOK, rc, exit); 
331         
332 exit:
333         //unlock_kernel();
334         smfs_trans_commit(dir, handle, 0);
335         post_smfs_dentry(cache_dentry);
336         post_smfs_dentry(cache_parent);
337         RETURN(rc);
338 }
339
340 static int smfs_mkdir(struct inode *dir, struct dentry *dentry,
341                       int mode)
342 {
343         struct inode *cache_dir = I2CI(dir);
344         struct inode *inode = NULL;
345         struct dentry *cache_dentry;
346         struct dentry *cache_parent;
347         void   *handle = NULL;
348         int    rc = 0;
349
350         ENTRY;
351         
352         if (!cache_dir || !cache_dir->i_op->mkdir)
353                 RETURN(-ENOENT);
354
355         cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry);
356         cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry);
357
358         if (!cache_parent || !cache_dentry)
359                 GOTO(exit, rc = -ENOMEM);
360
361         pre_smfs_inode(dir, cache_dir);
362
363         handle = smfs_trans_start(dir, FSFILT_OP_MKDIR, NULL);
364         if (IS_ERR(handle))
365                 GOTO(exit, rc = -ENOSPC);
366
367         //lock_kernel();
368         
369         SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_MKDIR, handle, PRE_HOOK, rc, 
370                   exit); 
371         
372         rc = cache_dir->i_op->mkdir(cache_dir, cache_dentry, mode);
373
374         if (rc)
375                 GOTO(exit, rc);
376   
377         SMFS_IGET(dir, cache_dentry->d_inode->i_ino, inode, rc, exit);
378         
379         d_instantiate(dentry, inode);
380         post_smfs_inode(dir, cache_dir);
381
382         SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_MKDIR, handle, POST_HOOK, rc,
383                   exit); 
384 exit:
385         //unlock_kernel();
386         smfs_trans_commit(dir, handle, 0);
387         post_smfs_dentry(cache_dentry);
388         post_smfs_dentry(cache_parent);
389         RETURN(rc);
390 }
391
392 static int smfs_rmdir(struct inode *dir, struct dentry *dentry)
393 {
394         struct inode *cache_dir = I2CI(dir);
395         struct inode *cache_inode = I2CI(dentry->d_inode);
396         struct dentry *cache_dentry = NULL;
397         struct dentry *cache_parent = NULL;
398         void *handle = NULL;
399         int    rc = 0, mode = S_IFDIR;
400
401         ENTRY;
402         
403         if (!cache_dir || !cache_dir->i_op->rmdir)
404                 RETURN(-ENOENT);
405
406         cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry);
407         cache_dentry = pre_smfs_dentry(cache_parent, cache_inode, dentry);
408
409         if (!cache_parent || !cache_dentry)
410                 GOTO(exit, rc = -ENOMEM);
411
412         pre_smfs_inode(dir, cache_dir);
413         pre_smfs_inode(dentry->d_inode, cache_dentry->d_inode);
414         
415         handle = smfs_trans_start(dir, FSFILT_OP_RMDIR, NULL);
416         if (IS_ERR(handle) ) {
417                 CERROR("smfs_do_mkdir: no space for transaction\n");
418                 GOTO(exit, rc = -ENOSPC);
419         }
420
421         //lock_kernel();
422
423         SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_RMDIR, handle, PRE_HOOK, rc, 
424                   exit); 
425
426         rc = cache_dir->i_op->rmdir(cache_dir, cache_dentry);
427         if (rc)
428                 GOTO(exit, rc);
429         
430         post_smfs_inode(dir, cache_dir);
431         post_smfs_inode(dentry->d_inode, cache_dentry->d_inode);
432         //unlock_kernel();
433         
434         SMFS_HOOK(dir, dentry, &mode, NULL, HOOK_RMDIR, handle, POST_HOOK, 
435                   rc, exit); 
436 exit:
437         smfs_trans_commit(dir, handle, 0);
438         post_smfs_dentry(cache_dentry);
439         post_smfs_dentry(cache_parent);
440         RETURN(rc);
441 }
442
443 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
444 static int smfs_mknod(struct inode *dir, struct dentry *dentry,
445                       int mode, int rdev)
446 #else
447 static int smfs_mknod(struct inode *dir, struct dentry *dentry,
448                       int mode, dev_t rdev)
449 #endif
450 {
451         struct inode *cache_dir = I2CI(dir);
452         struct inode *inode = NULL;
453         struct dentry *cache_dentry = NULL;
454         struct dentry *cache_parent = NULL;
455         void *handle = NULL;
456         int rc = 0;
457
458         ENTRY;
459         
460         if (!cache_dir || !cache_dir->i_op->mknod)
461                 RETURN(-ENOENT);
462
463         cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry->d_parent);
464         cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry);
465         
466         if (!cache_parent || !cache_dentry)
467                 GOTO(exit, rc = -ENOMEM);
468
469         pre_smfs_inode(dir, cache_dir);
470         pre_smfs_inode(dentry->d_inode, cache_dentry->d_inode);
471
472         handle = smfs_trans_start(dir, FSFILT_OP_MKNOD, NULL);
473         if (IS_ERR(handle)) {
474                 CERROR("smfs_do_mkdir: no space for transaction\n");
475                 GOTO(exit, rc = -ENOSPC);
476         }
477
478         //lock_kernel();
479         SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_MKNOD, handle, PRE_HOOK, rc, 
480                   exit); 
481         
482         rc = cache_dir->i_op->mknod(cache_dir, cache_dentry, mode, rdev);
483         if (rc)
484                 GOTO(exit, rc);
485
486         SMFS_IGET(dir, cache_dentry->d_inode->i_ino, inode, rc, exit); 
487
488         d_instantiate(dentry, inode);
489
490         post_smfs_inode(dir, cache_dir);
491         post_smfs_inode(dentry->d_inode, cache_dentry->d_inode);
492
493         SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_MKNOD, handle, POST_HOOK, rc, 
494                   exit); 
495         
496 exit:
497         //unlock_kernel();
498         smfs_trans_commit(dir, handle, 0);
499         post_smfs_dentry(cache_dentry);
500         post_smfs_dentry(cache_parent);
501         RETURN(rc);
502 }
503
504 static int smfs_rename(struct inode *old_dir, struct dentry *old_dentry,
505                        struct inode *new_dir,struct dentry *new_dentry)
506 {
507         struct inode *cache_old_dir = I2CI(old_dir);
508         struct inode *cache_new_dir = I2CI(new_dir);
509         struct inode *cache_old_inode = I2CI(old_dentry->d_inode);
510
511         struct inode *cache_new_inode = new_dentry->d_inode ?
512             I2CI(new_dentry->d_inode) : NULL;
513
514         struct dentry *cache_old_dentry = NULL;
515         struct dentry *cache_new_dentry = NULL;
516         struct dentry *cache_new_parent = NULL;
517         struct dentry *cache_old_parent = NULL;
518         void *handle = NULL;
519         int    rc = 0;
520
521         ENTRY;
522         
523         if (!cache_old_dir || !cache_new_dir || !cache_old_inode
524             || !cache_old_dir->i_op->rename)
525                 RETURN(-ENOENT);
526
527         cache_old_parent = pre_smfs_dentry(NULL, cache_old_dir, old_dentry);
528
529         cache_old_dentry = pre_smfs_dentry(cache_old_parent, cache_old_inode,
530                                            old_dentry);
531         
532         if (!cache_old_parent || !cache_old_dentry)
533                 GOTO(exit, rc = -ENOMEM);
534
535         cache_new_parent = pre_smfs_dentry(NULL, cache_new_dir, new_dentry);
536         cache_new_dentry = pre_smfs_dentry(cache_new_parent, cache_new_inode,
537                                            new_dentry);
538
539         if (!cache_new_parent || !cache_new_dentry)
540                 GOTO(exit, rc = -ENOMEM);
541
542         pre_smfs_inode(old_dir, cache_old_dir);
543         pre_smfs_inode(new_dir, cache_new_dir);
544
545         handle = smfs_trans_start(old_dir, FSFILT_OP_RENAME, NULL);
546         if (IS_ERR(handle)) {
547                 CERROR("smfs_do_mkdir: no space for transaction\n");
548                 GOTO(exit, rc = -ENOSPC);
549         }
550         //lock_kernel();
551         
552         SMFS_HOOK(old_dir, old_dentry, new_dir, new_dentry, HOOK_RENAME,
553                   handle, PRE_HOOK, rc, exit); 
554         
555         rc = cache_old_dir->i_op->rename(cache_old_dir, cache_old_dentry,
556                                          cache_new_dir, cache_new_dentry);
557         
558         post_smfs_inode(old_dir, cache_old_dir);
559         post_smfs_inode(new_dir, cache_new_dir);
560
561         if (new_dentry->d_inode)
562                 post_smfs_inode(new_dentry->d_inode, cache_new_dentry->d_inode);
563         
564         SMFS_HOOK(old_dir, old_dentry, new_dir, new_dentry, HOOK_RENAME, handle, 
565                   POST_HOOK, rc, exit); 
566         
567
568 exit:
569         //unlock_kernel();
570         smfs_trans_commit(old_dir, handle, 0);
571         post_smfs_dentry(cache_old_dentry);
572         post_smfs_dentry(cache_old_parent);
573         post_smfs_dentry(cache_new_dentry);
574         post_smfs_dentry(cache_new_parent);
575         RETURN(rc);
576 }
577
578 struct inode_operations smfs_dir_iops = {
579         create:         smfs_create,
580         lookup:         smfs_lookup,
581         link:           smfs_link,              /* BKL held */
582         unlink:         smfs_unlink,            /* BKL held */
583         symlink:        smfs_symlink,           /* BKL held */
584         mkdir:          smfs_mkdir,             /* BKL held */
585         rmdir:          smfs_rmdir,             /* BKL held */
586         mknod:          smfs_mknod,             /* BKL held */
587         rename:         smfs_rename,            /* BKL held */
588         setxattr:       smfs_setxattr,          /* BKL held */
589         getxattr:       smfs_getxattr,          /* BKL held */
590         listxattr:      smfs_listxattr,         /* BKL held */
591         removexattr:    smfs_removexattr,       /* BKL held */
592 };
593
594 static ssize_t smfs_read_dir(struct file *filp, char *buf,
595                              size_t size, loff_t *ppos)
596 {
597         struct dentry *dentry = filp->f_dentry;
598         struct inode *cache_inode = NULL;
599         struct smfs_file_info *sfi = NULL;
600         loff_t tmp_ppos;
601         loff_t *cache_ppos = NULL;
602         int    rc = 0;
603
604         ENTRY;
605         
606         cache_inode = I2CI(dentry->d_inode);
607
608         if (!cache_inode || !cache_inode->i_fop->read)
609                 RETURN(-EINVAL);
610
611         sfi = F2SMFI(filp);
612         if (sfi->magic != SMFS_FILE_MAGIC)
613                 BUG();
614
615         if (ppos != &(filp->f_pos))
616                 cache_ppos = &tmp_ppos;
617         else
618                 cache_ppos = &sfi->c_file->f_pos;
619         
620         *cache_ppos = *ppos;
621
622         rc = cache_inode->i_fop->read(sfi->c_file, buf, size, cache_ppos);
623         if (rc)
624                 RETURN(rc);
625
626         *ppos = *cache_ppos;
627         
628         duplicate_file(filp, sfi->c_file);
629         
630         RETURN(rc);
631 }
632
633 static int smfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
634 {
635         struct dentry *dentry = filp->f_dentry;
636         struct inode *cache_inode = NULL;
637         struct smfs_file_info *sfi = NULL;
638         int    rc = 0;
639
640         ENTRY;
641         
642         cache_inode = I2CI(dentry->d_inode);
643         if (!cache_inode || !cache_inode->i_fop->readdir)
644                 RETURN(-EINVAL);
645
646         sfi = F2SMFI(filp);
647         if (sfi->magic != SMFS_FILE_MAGIC) BUG();
648
649         SMFS_HOOK(dentry->d_inode, filp, dirent, filldir, HOOK_READDIR, NULL, 
650                   PRE_HOOK, rc, exit); 
651         
652         rc = cache_inode->i_fop->readdir(sfi->c_file, dirent, filldir);
653         CDEBUG(D_INODE,"readdir rc=%u\n",rc);
654         if (rc < 0)
655                 RETURN(rc);
656
657         duplicate_file(filp, sfi->c_file);
658
659         SMFS_HOOK(dentry->d_inode, filp, dirent, filldir, HOOK_READDIR, NULL, 
660                   POST_HOOK, rc, exit);
661         
662 exit:
663         if (rc > 0)
664                 rc = 0;
665         RETURN(rc);
666 }
667
668 struct file_operations smfs_dir_fops = {
669         .read           = smfs_read_dir,
670         .readdir        = smfs_readdir,       /* BKL held */
671         .ioctl          = smfs_ioctl,         /* BKL held */
672         .fsync          = smfs_fsync,         /* BKL held */
673         .open           = smfs_open,
674         .release        = smfs_release,
675 };