Whamcloud - gitweb
Commit OST AMD support to HEAD so we can being running with a common code base.
[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_snap.h>
38 #include <linux/lustre_smfs.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         int rc = 0;
58
59         ENTRY;
60
61         cache_dir = I2CI(dir);
62         if (!cache_dir)
63                 RETURN(-ENOENT);
64
65         handle = smfs_trans_start(dir, FSFILT_OP_CREATE, NULL);
66         if (IS_ERR(handle))
67                        RETURN(-ENOSPC);
68         
69         lock_kernel();
70         SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_CREATE, handle, PRE_HOOK, rc, 
71                   exit); 
72         cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry);
73         cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry);
74
75         if (!cache_dentry || !cache_parent)
76                 GOTO(exit, rc = -ENOMEM);
77        
78         pre_smfs_inode(dir, cache_dir);
79 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
80         if (cache_dir && cache_dir->i_op->create)
81                 rc = cache_dir->i_op->create(cache_dir, cache_dentry,
82                                              mode);
83 #else
84         if (cache_dir && cache_dir->i_op->create)
85                 rc = cache_dir->i_op->create(cache_dir, cache_dentry,
86                                              mode, nd);
87 #endif
88         if (rc)
89                 GOTO(exit, rc);
90
91         inode = iget4(dir->i_sb, cache_dentry->d_inode->i_ino, NULL,
92                       &I2SMI(dir)->smi_flags);
93         if (!inode)
94                 GOTO(exit, rc = -ENOMEM);
95
96         d_instantiate(dentry, inode);
97         sm_set_inode_ops(cache_dentry->d_inode, inode);
98         post_smfs_inode(dir, cache_dir);
99         SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_CREATE, handle, POST_HOOK, rc, 
100                   exit); 
101 exit:
102         unlock_kernel();
103         post_smfs_dentry(cache_dentry);
104         post_smfs_dentry(cache_parent);
105         smfs_trans_commit(dir, handle, 0);
106         RETURN(rc);
107 }
108
109 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
110 static struct dentry *smfs_lookup(struct inode *dir, struct dentry *dentry)
111 #else
112 static struct dentry *smfs_lookup(struct inode *dir, struct dentry *dentry,
113                                   struct nameidata *nd)
114 #endif
115 {
116         struct inode *cache_dir;
117         struct inode *cache_inode;
118         struct inode *inode = NULL;
119         struct dentry *cache_dentry = NULL;
120         struct dentry *cache_parent = NULL;
121         struct dentry *rc = NULL;
122         void *handle = NULL;
123         int rc2 = 0;
124
125         ENTRY;
126
127         if (!(cache_dir = I2CI(dir)))
128                 RETURN(ERR_PTR(-ENOENT));
129
130         SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_LOOKUP, handle, PRE_HOOK, rc2, 
131                   exit); 
132         if (rc2)
133                 RETURN(ERR_PTR(rc2));
134
135         /* preparing artificial backing fs dentries. */
136         cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry->d_parent);
137         cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry);
138
139         if (!cache_dentry || !cache_parent)
140                 GOTO(exit, rc = ERR_PTR(-ENOMEM));
141
142         if (!cache_dir && cache_dir->i_op->lookup)
143                 GOTO(exit, rc = ERR_PTR(-ENOENT));
144
145         /* perform lookup in backing fs. */
146 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
147         rc = cache_dir->i_op->lookup(cache_dir, cache_dentry);
148 #else
149         rc = cache_dir->i_op->lookup(cache_dir, cache_dentry, nd);
150 #endif
151
152         if (rc && IS_ERR(rc))
153                 GOTO(exit, rc);
154         
155         if ((cache_inode = rc ? rc->d_inode : cache_dentry->d_inode)) {
156                 if (IS_ERR(cache_inode)) {
157                         dentry->d_inode = cache_inode;
158                         GOTO(exit, rc = NULL);
159                 }
160                 inode = iget4(dir->i_sb, cache_inode->i_ino, NULL,
161                                     &I2SMI(dir)->smi_flags);
162         } else {
163                 d_add(dentry, NULL);
164                 GOTO(exit, rc);
165         }
166
167         d_add(dentry, inode);
168         rc = NULL;
169
170         SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_LOOKUP, handle, POST_HOOK, rc2, 
171                   exit); 
172 exit:
173         if (rc2)
174                 rc = ERR_PTR(rc2);
175         post_smfs_dentry(cache_dentry);
176         post_smfs_dentry(cache_parent);
177         smfs_trans_commit(dir, handle, 0);
178         RETURN(rc);
179 }
180
181 static int smfs_link(struct dentry * old_dentry,
182                      struct inode * dir, struct dentry *dentry)
183 {
184         struct        inode *cache_old_inode = NULL;
185         struct        inode *cache_dir = I2CI(dir);
186         struct        inode *inode = NULL;
187         struct  dentry *cache_dentry = NULL;
188         struct  dentry *cache_old_dentry = NULL;
189         struct  dentry *cache_parent = NULL;
190         void        *handle = NULL;
191         int        rc = 0;
192
193         inode = old_dentry->d_inode;
194
195         cache_old_inode = I2CI(inode);
196
197         handle = smfs_trans_start(dir, FSFILT_OP_LINK, NULL);
198         if (IS_ERR(handle))
199                  RETURN(-ENOSPC);
200         
201         lock_kernel();
202         SMFS_HOOK(dir, old_dentry, NULL, NULL, HOOK_LINK, handle, PRE_HOOK, rc, 
203                   exit); 
204         
205         cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry);
206         cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry);
207
208         if (!cache_parent || !cache_dentry)
209                 GOTO(exit, rc = -ENOMEM);
210
211         cache_old_dentry = pre_smfs_dentry(NULL, cache_old_inode,
212                                            old_dentry);
213         if (!cache_old_dentry)
214                 GOTO(exit, rc = -ENOMEM);
215
216         pre_smfs_inode(dir, cache_dir);
217         pre_smfs_inode(inode, cache_old_dentry->d_inode);
218
219         if (cache_dir->i_op->link)
220                 rc = cache_dir->i_op->link(cache_old_dentry, cache_dir,
221                                            cache_dentry);
222         if (rc)
223                 GOTO(exit, rc);
224
225         atomic_inc(&inode->i_count);
226         post_smfs_inode(inode, cache_old_dentry->d_inode);
227         d_instantiate(dentry, inode);
228         post_smfs_inode(dir, cache_dir);
229
230         SMFS_HOOK(dir, old_dentry, dentry, NULL, HOOK_LINK, handle, POST_HOOK, 
231                   rc, exit); 
232         
233 exit:
234         unlock_kernel();
235         post_smfs_dentry(cache_dentry);
236         post_smfs_dentry(cache_parent);
237         post_smfs_dentry(cache_old_dentry);
238         smfs_trans_commit(dir, handle, 0);
239         RETURN(rc);
240 }
241
242 static int smfs_unlink(struct inode * dir,
243                        struct dentry *dentry)
244 {
245         struct inode *cache_dir = I2CI(dir);
246         struct inode *cache_inode = I2CI(dentry->d_inode);
247         struct dentry *cache_dentry;
248         struct dentry *cache_parent;
249         void   *handle = NULL;
250         int    rc = 0;
251         int    mode = 0;
252
253         if (!cache_dir || !cache_inode)
254                 RETURN(-ENOENT);
255
256         handle = smfs_trans_start(dir, FSFILT_OP_UNLINK, NULL);
257         if (IS_ERR(handle))
258                 RETURN(-ENOSPC);
259
260         SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_UNLINK, handle, PRE_HOOK, rc, 
261                   exit); 
262         
263         cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry);
264         cache_dentry = pre_smfs_dentry(cache_parent, cache_inode, dentry);
265
266         if (!cache_parent || !cache_dentry)
267                 GOTO(exit, rc = -ENOMEM);
268                 
269         lock_kernel();
270         pre_smfs_inode(dir, cache_dir);
271         pre_smfs_inode(dentry->d_inode, cache_inode);
272         if (cache_dir->i_op->unlink)
273                 rc = cache_dir->i_op->unlink(cache_dir, cache_dentry);
274         post_smfs_inode(dentry->d_inode, cache_dentry->d_inode);
275         post_smfs_inode(dir, cache_dir);
276         unlock_kernel();
277         
278         SMFS_HOOK(dir, dentry, &mode, NULL, HOOK_UNLINK, handle, POST_HOOK, 
279                   rc, exit); 
280 exit:
281         post_smfs_dentry(cache_dentry);
282         post_smfs_dentry(cache_parent);
283         smfs_trans_commit(dir, handle, 0);
284         RETURN(rc);
285 }
286
287 static int smfs_symlink(struct inode *dir, struct dentry *dentry,
288                         const char *symname)
289 {
290         struct inode *cache_dir = I2CI(dir);
291         struct inode *inode = NULL;
292         struct dentry *cache_dentry;
293         struct dentry *cache_parent;
294         void   *handle = NULL;
295         int    rc = 0, tgt_len;
296
297         if (!cache_dir)
298                 RETURN(-ENOENT);
299
300         handle = smfs_trans_start(dir, FSFILT_OP_SYMLINK, NULL);
301         if (IS_ERR(handle))
302                 RETURN(-ENOSPC);
303         
304         lock_kernel();
305         SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_SYMLINK, handle, PRE_HOOK, rc, 
306                   exit); 
307
308         cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry);
309         cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry);
310
311         if (!cache_parent || !cache_dentry)
312                 GOTO(exit, rc = -ENOMEM);
313        
314         pre_smfs_inode(dir, cache_dir);
315         if (cache_dir->i_op->symlink)
316                 rc = cache_dir->i_op->symlink(cache_dir, cache_dentry, symname);
317
318         inode = iget4(dir->i_sb, cache_dentry->d_inode->i_ino, NULL,
319                       &I2SMI(dir)->smi_flags);
320         post_smfs_inode(dir, cache_dir);
321         if (inode)
322                 d_instantiate(dentry, inode);
323         else
324                 rc = -ENOENT;
325
326         tgt_len = strlen(symname) + 1;
327         
328         SMFS_HOOK(dir, dentry, (char *)symname, &tgt_len, HOOK_SYMLINK, handle, 
329                   POST_HOOK, rc, exit); 
330 exit:
331         unlock_kernel();
332         post_smfs_dentry(cache_dentry);
333         post_smfs_dentry(cache_parent);
334         smfs_trans_commit(dir, handle, 0);
335         RETURN(rc);
336 }
337
338 static int smfs_mkdir(struct inode *dir, struct dentry *dentry,
339                       int mode)
340 {
341         struct inode *cache_dir = I2CI(dir);
342         struct inode *inode = NULL;
343         struct dentry *cache_dentry;
344         struct dentry *cache_parent;
345         void   *handle = NULL;
346         int    rc = 0;
347
348         if (!cache_dir)
349                 RETURN(-ENOENT);
350
351         handle = smfs_trans_start(dir, FSFILT_OP_MKDIR, NULL);
352         if (IS_ERR(handle))
353                 RETURN(-ENOSPC);
354
355         lock_kernel();
356         
357         SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_MKDIR, handle, PRE_HOOK, rc, 
358                   exit); 
359         
360         cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry);
361         cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry);
362
363         if (!cache_parent || !cache_dentry)
364                 GOTO(exit, rc = -ENOMEM);
365
366         pre_smfs_inode(dir, cache_dir);
367
368         if (cache_dir->i_op->mkdir)
369                 rc = cache_dir->i_op->mkdir(cache_dir, cache_dentry, mode);
370
371         if (rc)
372                 GOTO(exit, rc);
373
374         inode = iget4(dir->i_sb, cache_dentry->d_inode->i_ino, NULL,
375                       &I2SMI(dir)->smi_flags);
376         if (!inode)
377                 GOTO(exit, rc = -ENOENT);
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         post_smfs_dentry(cache_dentry);
387         post_smfs_dentry(cache_parent);
388         smfs_trans_commit(dir, handle, 0);
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         if (!cache_dir)
402                 RETURN(-ENOENT);
403
404         handle = smfs_trans_start(dir, FSFILT_OP_RMDIR, NULL);
405         if (IS_ERR(handle) ) {
406                 CERROR("smfs_do_mkdir: no space for transaction\n");
407                 RETURN(-ENOSPC);
408         }
409
410         lock_kernel();
411
412         SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_RMDIR, handle, PRE_HOOK, rc, 
413                   exit); 
414
415         cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry);
416         cache_dentry = pre_smfs_dentry(cache_parent, cache_inode, dentry);
417
418         if (!cache_parent || !cache_dentry)
419                 GOTO(exit, rc = -ENOMEM);
420
421         pre_smfs_inode(dir, cache_dir);
422         pre_smfs_inode(dentry->d_inode, cache_dentry->d_inode);
423         if (cache_dir->i_op->rmdir)
424                 rc = cache_dir->i_op->rmdir(cache_dir, cache_dentry);
425
426         post_smfs_inode(dir, cache_dir);
427         post_smfs_inode(dentry->d_inode, cache_dentry->d_inode);
428         unlock_kernel();
429         
430         SMFS_HOOK(dir, dentry, &mode, NULL, HOOK_RMDIR, handle, POST_HOOK, 
431                   rc, exit); 
432 exit:
433         post_smfs_dentry(cache_dentry);
434         post_smfs_dentry(cache_parent);
435         smfs_trans_commit(dir, handle, 0);
436         RETURN(rc);
437 }
438
439 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
440 static int smfs_mknod(struct inode *dir, struct dentry *dentry,
441                       int mode, int rdev)
442 #else
443 static int smfs_mknod(struct inode *dir, struct dentry *dentry,
444                       int mode, dev_t rdev)
445 #endif
446 {
447         struct inode *cache_dir = I2CI(dir);
448         struct inode *inode = NULL;
449         struct dentry *cache_dentry = NULL;
450         struct dentry *cache_parent = NULL;
451         void *handle = NULL;
452         int rc = 0;
453
454         if (!cache_dir)
455                 RETURN(-ENOENT);
456
457         handle = smfs_trans_start(dir, FSFILT_OP_MKNOD, NULL);
458         if (IS_ERR(handle)) {
459                 CERROR("smfs_do_mkdir: no space for transaction\n");
460                 RETURN(-ENOSPC);
461         }
462
463         lock_kernel();
464         SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_MKNOD, handle, PRE_HOOK, rc, 
465                   exit); 
466         
467         cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry->d_parent);
468         cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry);
469         if (!cache_parent || !cache_dentry)
470                 GOTO(exit, rc = -ENOMEM);
471
472         pre_smfs_inode(dir, cache_dir);
473         pre_smfs_inode(dentry->d_inode, cache_dentry->d_inode);
474
475         if (!cache_dir->i_op->mknod)
476                 RETURN(-ENOENT);
477
478         if ((rc = cache_dir->i_op->mknod(cache_dir, cache_dentry,
479                                          mode, rdev)))
480                 GOTO(exit, rc);
481
482         inode = iget4(dir->i_sb, cache_dentry->d_inode->i_ino, NULL,
483                       &I2SMI(dir)->smi_flags);
484         d_instantiate(dentry, inode);
485
486         pre_smfs_inode(dir, cache_dir);
487         pre_smfs_inode(dentry->d_inode, cache_dentry->d_inode);
488
489         SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_MKNOD, handle, POST_HOOK, rc, 
490                   exit); 
491         
492 exit:
493         unlock_kernel();
494         post_smfs_dentry(cache_dentry);
495         post_smfs_dentry(cache_parent);
496         smfs_trans_commit(dir, handle, 0);
497         RETURN(rc);
498 }
499
500 static int smfs_rename(struct inode * old_dir, struct dentry *old_dentry,
501                        struct inode * new_dir,struct dentry *new_dentry)
502 {
503         struct inode *cache_old_dir = I2CI(old_dir);
504         struct inode *cache_new_dir = I2CI(new_dir);
505         struct inode *cache_old_inode = I2CI(old_dentry->d_inode);
506
507         struct inode *cache_new_inode = new_dentry->d_inode ?
508             I2CI(new_dentry->d_inode) : NULL;
509
510         struct dentry *cache_old_dentry = NULL;
511         struct dentry *cache_new_dentry = NULL;
512         struct dentry *cache_new_parent = NULL;
513         struct dentry *cache_old_parent = NULL;
514         void *handle = NULL;
515         int    rc = 0;
516
517         if (!cache_old_dir || !cache_new_dir || !cache_old_inode)
518                 RETURN(-ENOENT);
519
520         handle = smfs_trans_start(old_dir, FSFILT_OP_RENAME, NULL);
521         if (IS_ERR(handle)) {
522                 CERROR("smfs_do_mkdir: no space for transaction\n");
523                 RETURN(-ENOSPC);
524         }
525         lock_kernel();
526
527         
528         SMFS_HOOK(old_dir, old_dentry, new_dir, new_dentry, HOOK_RENAME, handle, 
529                   PRE_HOOK, rc, exit); 
530         
531         cache_old_parent = pre_smfs_dentry(NULL, cache_old_dir, old_dentry);
532         cache_old_dentry = pre_smfs_dentry(cache_old_parent, cache_old_inode,
533                                            old_dentry);
534         if (!cache_old_parent || !cache_old_dentry)
535                 GOTO(exit, rc = -ENOMEM);
536
537         cache_new_parent = pre_smfs_dentry(NULL, cache_new_dir, new_dentry);
538         cache_new_dentry = pre_smfs_dentry(cache_new_parent, cache_new_inode,
539                                            new_dentry);
540         if (!cache_new_parent || !cache_new_dentry)
541                 GOTO(exit, rc = -ENOMEM);
542
543         pre_smfs_inode(old_dir, cache_old_dir);
544         pre_smfs_inode(new_dir, cache_new_dir);
545
546         if (cache_old_dir->i_op->rename)
547                 rc = cache_old_dir->i_op->rename(cache_old_dir, cache_old_dentry,
548                                                  cache_new_dir, cache_new_dentry);
549         
550         post_smfs_inode(old_dir, cache_old_dir);
551         post_smfs_inode(new_dir, cache_new_dir);
552
553         SMFS_HOOK(old_dir, old_dentry, new_dir, new_dentry, HOOK_RENAME, handle, 
554                   POST_HOOK, rc, exit); 
555         
556         if (new_dentry->d_inode)
557                 post_smfs_inode(new_dentry->d_inode, cache_new_dentry->d_inode);
558 exit:
559         unlock_kernel();
560         post_smfs_dentry(cache_old_dentry);
561         post_smfs_dentry(cache_old_parent);
562         post_smfs_dentry(cache_new_dentry);
563         post_smfs_dentry(cache_new_parent);
564         smfs_trans_commit(old_dir, handle, 0);
565         RETURN(rc);
566 }
567
568 struct inode_operations smfs_dir_iops = {
569         create:         smfs_create,
570         lookup:         smfs_lookup,
571         link:           smfs_link,              /* BKL held */
572         unlink:         smfs_unlink,            /* BKL held */
573         symlink:        smfs_symlink,           /* BKL held */
574         mkdir:          smfs_mkdir,             /* BKL held */
575         rmdir:          smfs_rmdir,             /* BKL held */
576         mknod:          smfs_mknod,             /* BKL held */
577         rename:         smfs_rename,            /* BKL held */
578         setxattr:       smfs_setxattr,          /* BKL held */
579         getxattr:       smfs_getxattr,          /* BKL held */
580         listxattr:      smfs_listxattr,         /* BKL held */
581         removexattr:    smfs_removexattr,       /* BKL held */
582 };
583
584 static ssize_t smfs_read_dir(struct file *filp, char *buf,
585                              size_t size, loff_t *ppos)
586 {
587         struct dentry *dentry = filp->f_dentry;
588         struct inode *cache_inode = NULL;
589         struct smfs_file_info *sfi = NULL;
590         loff_t tmp_ppos;
591         loff_t *cache_ppos;
592         int    rc = 0;
593
594         cache_inode = I2CI(dentry->d_inode);
595
596         if (!cache_inode)
597                 RETURN(-EINVAL);
598
599         sfi = F2SMFI(filp);
600         if (sfi->magic != SMFS_FILE_MAGIC) BUG();
601
602         if (ppos != &(filp->f_pos))
603                 cache_ppos = &tmp_ppos;
604         else
605                 cache_ppos = &sfi->c_file->f_pos;
606         *cache_ppos = *ppos;
607
608         if (cache_inode->i_fop->read)
609                 rc = cache_inode->i_fop->read(sfi->c_file, buf, size,
610                                               cache_ppos);
611
612         *ppos = *cache_ppos;
613         duplicate_file(filp, sfi->c_file);
614         RETURN(rc);
615 }
616
617 static int smfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
618 {
619         struct dentry *dentry = filp->f_dentry;
620         struct inode *cache_inode = NULL;
621         struct smfs_file_info *sfi = NULL;
622         int    rc = 0;
623
624         cache_inode = I2CI(dentry->d_inode);
625         if (!cache_inode)
626                 RETURN(-EINVAL);
627
628         sfi = F2SMFI(filp);
629         if (sfi->magic != SMFS_FILE_MAGIC) BUG();
630
631         if (cache_inode->i_fop->readdir)
632                 rc = cache_inode->i_fop->readdir(sfi->c_file, dirent, filldir);
633
634         duplicate_file(filp, sfi->c_file);
635         RETURN(rc);
636 }
637
638 struct file_operations smfs_dir_fops = {
639         read:           smfs_read_dir,
640         readdir:        smfs_readdir,           /* BKL held */
641         ioctl:          smfs_ioctl,             /* BKL held */
642         fsync:          smfs_fsync,         /* BKL held */
643         open:           smfs_open,
644         release:        smfs_release,
645 };