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