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