1 Index: linux-2.4.22-vanilla/fs/Makefile
2 ===================================================================
3 --- linux-2.4.22-vanilla.orig/fs/Makefile 2003-11-03 23:41:40.000000000 +0300
4 +++ linux-2.4.22-vanilla/fs/Makefile 2003-11-03 23:45:07.000000000 +0300
9 -export-objs := filesystems.o open.o dcache.o buffer.o dquot.o inode.o
10 +export-objs := filesystems.o open.o dcache.o buffer.o dquot.o inode.o \
11 + namei.o file_table.o
14 obj-y := open.o read_write.o devices.o file_table.o buffer.o \
15 Index: linux-2.4.22-vanilla/fs/file_table.c
16 ===================================================================
17 --- linux-2.4.22-vanilla.orig/fs/file_table.c 2003-05-16 05:29:12.000000000 +0400
18 +++ linux-2.4.22-vanilla/fs/file_table.c 2003-11-03 23:44:38.000000000 +0300
20 * and call the open function (if any). The caller must verify that
21 * inode->i_fop is not NULL.
23 -int init_private_file(struct file *filp, struct dentry *dentry, int mode)
24 +int init_private_file_it(struct file *filp, struct dentry *dentry, int mode,
25 + struct lookup_intent *it)
27 memset(filp, 0, sizeof(*filp));
30 filp->f_dentry = dentry;
31 filp->f_uid = current->fsuid;
32 filp->f_gid = current->fsgid;
35 filp->f_op = dentry->d_inode->i_fop;
37 return filp->f_op->open(dentry->d_inode, filp);
41 +EXPORT_SYMBOL(init_private_file_it);
43 +int init_private_file(struct file *filp, struct dentry *dentry, int mode)
45 + return init_private_file_it(filp, dentry, mode, NULL);
48 void fput(struct file * file)
50 Index: linux-2.4.22-vanilla/fs/inode.c
51 ===================================================================
52 --- linux-2.4.22-vanilla.orig/fs/inode.c 2003-11-03 23:25:33.000000000 +0300
53 +++ linux-2.4.22-vanilla/fs/inode.c 2003-11-03 23:44:38.000000000 +0300
58 -struct inode *iget4(struct super_block *sb, unsigned long ino, find_inode_t find_actor, void *opaque)
59 +static inline struct inode *ifind(struct super_block *sb, unsigned long ino,
60 + struct list_head *head,
61 + find_inode_t find_actor, void *opaque)
63 - struct list_head * head = inode_hashtable + hash(sb,ino);
66 spin_lock(&inode_lock);
69 spin_unlock(&inode_lock);
74 +struct inode *ilookup4(struct super_block *sb, unsigned long ino,
75 + find_inode_t find_actor, void *opaque)
77 + struct list_head * head = inode_hashtable + hash(sb,ino);
78 + return ifind(sb, ino, head, find_actor, opaque);
81 +struct inode *iget4(struct super_block *sb, unsigned long ino,
82 + find_inode_t find_actor, void *opaque)
84 + struct list_head * head = inode_hashtable + hash(sb,ino);
85 + struct inode *inode = ifind(sb, ino, head, find_actor, opaque);
90 * get_new_inode() will do the right thing, re-trying the search
91 * in case it had to block at any point.
92 Index: linux-2.4.22-vanilla/fs/namei.c
93 ===================================================================
94 --- linux-2.4.22-vanilla.orig/fs/namei.c 2003-11-03 23:22:22.000000000 +0300
95 +++ linux-2.4.22-vanilla/fs/namei.c 2003-11-03 23:44:38.000000000 +0300
97 #include <linux/dnotify.h>
98 #include <linux/smp_lock.h>
99 #include <linux/personality.h>
100 +#include <linux/module.h>
102 #include <asm/namei.h>
103 #include <asm/uaccess.h>
105 it->it_op_release(it);
108 +EXPORT_SYMBOL(intent_release);
110 /* In order to reduce some races, while at the same time doing additional
111 * checking and hopefully speeding things up, we copy filenames to the
116 -struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
117 +struct dentry * lookup_one_len_it(const char * name, struct dentry * base,
118 + int len, struct lookup_intent *it)
122 @@ -922,11 +925,16 @@
124 this.hash = end_name_hash(hash);
126 - return lookup_hash_it(&this, base, NULL);
127 + return lookup_hash_it(&this, base, it);
129 return ERR_PTR(-EACCES);
132 +struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
134 + return lookup_one_len_it(name, base, len, NULL);
140 Index: linux-2.4.22-vanilla/fs/nfsd/export.c
141 ===================================================================
142 --- linux-2.4.22-vanilla.orig/fs/nfsd/export.c 2003-11-03 23:22:11.000000000 +0300
143 +++ linux-2.4.22-vanilla/fs/nfsd/export.c 2003-11-03 23:44:38.000000000 +0300
145 inode = nd.dentry->d_inode;
148 + if ((inode->i_sb->s_type->fs_flags & FS_NFSEXP_FSID) &&
149 + !(nxp->ex_flags & NFSEXP_FSID)) {
150 + nxp->ex_dev = inode->i_sb->s_dev;
151 + nxp->ex_flags |= NFSEXP_FSID;
155 exp = exp_get(clp, dev, ino);
156 Index: linux-2.4.22-vanilla/fs/nfsd/nfsfh.c
157 ===================================================================
158 --- linux-2.4.22-vanilla.orig/fs/nfsd/nfsfh.c 2003-11-03 23:22:11.000000000 +0300
159 +++ linux-2.4.22-vanilla/fs/nfsd/nfsfh.c 2003-11-03 23:44:38.000000000 +0300
161 int sequence; /* sequence counter */
164 +static struct dentry *lookup_it(struct inode *inode, struct dentry * dentry)
166 + if (inode->i_op->lookup_it)
167 + return inode->i_op->lookup_it(inode, dentry, NULL, 0);
168 + return inode->i_op->lookup(inode, dentry);
172 * A rather strange filldir function to capture
173 * the name matching the specified inode number.
177 struct nfsd_getdents_callback buffer;
178 + struct lookup_intent it;
179 + struct file *filp = NULL;
182 if (!dir || !S_ISDIR(dir->i_mode))
185 * Open the directory ...
187 - error = init_private_file(&file, dentry, FMODE_READ);
189 + if (dentry->d_op && dentry->d_op->d_revalidate_it) {
190 + if ((dentry->d_flags & DCACHE_NFSD_DISCONNECTED) &&
191 + (dentry->d_parent == dentry) ) {
192 + it.it_op_release = NULL;
194 + * XXX Temporary Hack: Simulate init_private_file without
195 + * f_op->open for disconnected dentry as we don't have
196 + * actual dentry->d_name to revalidate in revalidate_it()
199 + memset(filp, 0, sizeof(*filp));
200 + filp->f_mode = FMODE_READ;
201 + atomic_set(&filp->f_count, 1);
202 + filp->f_dentry = dentry;
203 + filp->f_uid = current->fsuid;
204 + filp->f_gid = current->fsgid;
205 + filp->f_op = dentry->d_inode->i_fop;
208 + intent_init(&it, IT_OPEN, FMODE_READ);
209 + error = revalidate_it(dentry, &it);
212 + error = init_private_file_it(&file, dentry, FMODE_READ, &it);
215 + error = init_private_file_it(&file, dentry, FMODE_READ, NULL);
221 if (!file.f_op->readdir)
227 - if (file.f_op->release)
228 + if (file.f_op->release && !filp)
229 file.f_op->release(dir, &file);
231 + if (dentry->d_op && dentry->d_op->d_revalidate_it &&
232 + it.it_op_release && !filp)
233 + intent_release(&it);
238 * it is well connected. But nobody returns different dentrys do they?
240 down(&child->d_inode->i_sem);
241 - pdentry = child->d_inode->i_op->lookup(child->d_inode, tdentry);
242 + pdentry = lookup_it(child->d_inode, tdentry);
243 up(&child->d_inode->i_sem);
244 d_drop(tdentry); /* we never want ".." hashed */
245 if (!pdentry && tdentry->d_inode == NULL) {
247 igrab(tdentry->d_inode);
248 pdentry->d_flags |= DCACHE_NFSD_DISCONNECTED;
250 + if (child->d_op && child->d_op->d_revalidate_it)
251 + pdentry->d_op = child->d_op;
254 pdentry = ERR_PTR(-ENOMEM);
256 struct dentry *pdentry;
257 struct inode *parent;
259 + if (result->d_op && result->d_op->d_revalidate_it)
260 + dentry->d_op = result->d_op;
261 pdentry = nfsd_findparent(dentry);
262 err = PTR_ERR(pdentry);
266 inode = dentry->d_inode;
268 + /* cache coherency for non-device filesystems */
269 + if (inode->i_op && inode->i_op->revalidate_it)
270 + inode->i_op->revalidate_it(dentry, NULL);
272 /* Type check. The correct error return for type mismatches
273 * does not seem to be generally agreed upon. SunOS seems to
274 * use EISDIR if file isn't S_IFREG; a comment in the NFSv3
276 dentry->d_parent->d_name.name, dentry->d_name.name);
279 - printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n",
280 - dentry->d_parent->d_name.name, dentry->d_name.name);
281 + if (!dentry->d_parent->d_inode->i_op->mkdir_raw)
282 + printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n",
283 + dentry->d_parent->d_name.name, dentry->d_name.name);
287 Index: linux-2.4.22-vanilla/fs/nfsd/vfs.c
288 ===================================================================
289 --- linux-2.4.22-vanilla.orig/fs/nfsd/vfs.c 2003-11-03 23:22:11.000000000 +0300
290 +++ linux-2.4.22-vanilla/fs/nfsd/vfs.c 2003-11-03 23:47:41.000000000 +0300
292 static struct raparms * raparml;
293 static struct raparms * raparm_cache;
295 +static int link_raw(struct dentry *dold, struct dentry *ddir,
296 + struct dentry *dnew)
300 + struct nameidata old_nd = { .dentry = dold };
301 + struct nameidata nd = { .dentry = ddir, .last = dnew->d_name };
302 + struct inode_operations *op = nd.dentry->d_inode->i_op;
303 + err = op->link_raw(&old_nd, &nd);
304 + igrab(dold->d_inode);
305 + d_instantiate(dnew, dold->d_inode);
306 + if (dold->d_inode->i_op && dold->d_inode->i_op->revalidate_it)
307 + dold->d_inode->i_op->revalidate_it(dnew, NULL);
312 +static int unlink_raw(struct dentry *dentry, char *fname, int flen,
313 + struct dentry *rdentry)
316 + struct qstr last = { .name = fname, .len = flen };
317 + struct nameidata nd = { .dentry = dentry, .last = last };
318 + struct inode_operations *op = nd.dentry->d_inode->i_op;
319 + err = op->unlink_raw(&nd);
326 +static int rmdir_raw(struct dentry *dentry, char *fname, int flen,
327 + struct dentry *rdentry)
330 + struct qstr last = { .name = fname, .len = flen };
331 + struct nameidata nd = { .dentry = dentry, .last = last };
332 + struct inode_operations *op = nd.dentry->d_inode->i_op;
333 + err = op->rmdir_raw(&nd);
335 + rdentry->d_inode->i_flags |= S_DEAD;
342 +static int symlink_raw(struct dentry *dentry, char *fname, int flen,
346 + struct qstr last = { .name = fname, .len = flen };
347 + struct nameidata nd = { .dentry = dentry, .last = last };
348 + struct inode_operations *op = nd.dentry->d_inode->i_op;
349 + err = op->symlink_raw(&nd, path);
354 +static int mkdir_raw(struct dentry *dentry, char *fname, int flen, int mode)
357 + struct qstr last = { .name = fname, .len = flen };
358 + struct nameidata nd = { .dentry = dentry, .last = last };
359 + struct inode_operations *op = nd.dentry->d_inode->i_op;
360 + err = op->mkdir_raw(&nd, mode);
365 +static int mknod_raw(struct dentry *dentry, char *fname, int flen, int mode,
369 + struct qstr last = { .name = fname, .len = flen };
370 + struct nameidata nd = { .dentry = dentry, .last = last };
371 + struct inode_operations *op = nd.dentry->d_inode->i_op;
372 + err = op->mknod_raw(&nd, mode, dev);
377 +static int rename_raw(struct dentry *fdentry, struct dentry *tdentry,
378 + struct dentry *odentry, struct dentry *ndentry)
382 + struct nameidata old_nd = { .dentry = fdentry, .last = odentry->d_name};
383 + struct nameidata new_nd = { .dentry = tdentry, .last = ndentry->d_name};
384 + struct inode_operations *op = old_nd.dentry->d_inode->i_op;
385 + err = op->rename_raw(&old_nd, &new_nd);
386 + d_move(odentry, ndentry);
391 +static int setattr_raw(struct inode *inode, struct iattr *iap)
395 + iap->ia_valid |= ATTR_RAW;
396 + err = inode->i_op->setattr_raw(inode, iap);
401 +int revalidate_it(struct dentry *dentry, struct lookup_intent *it)
405 + if (dentry && dentry->d_op && dentry->d_op->d_revalidate_it) {
406 + if (!dentry->d_op->d_revalidate_it(dentry, 0, it) &&
407 + !d_invalidate(dentry)) {
417 * Look up one component of a pathname.
418 * N.B. After this call _both_ fhp and resfh need an fh_put
421 err = nfserr_notsync;
422 if (!check_guard || guardtime == inode->i_ctime) {
423 - err = notify_change(dentry, iap);
424 + if (dentry->d_inode->i_op && dentry->d_inode->i_op->setattr_raw)
425 + err = setattr_raw(dentry->d_inode, iap);
427 + err = notify_change(dentry, iap);
433 struct dentry *dentry;
435 + struct lookup_intent it;
438 /* If we get here, then the client has already done an "open", and (hopefully)
440 filp->f_mode = FMODE_READ;
443 +#ifndef O_OWNER_OVERRIDE
444 +#define O_OWNER_OVERRIDE 0200000000
446 + intent_init(&it, IT_OPEN, (filp->f_flags & ~O_ACCMODE) | filp->f_mode |
449 + err = revalidate_it(dentry, &it);
456 if (filp->f_op && filp->f_op->open) {
457 err = filp->f_op->open(inode, filp);
462 + if (it.it_op_release)
463 + intent_release(&it);
470 struct dentry *dentry, *dchild;
473 + int err, error = -EOPNOTSUPP;
477 @@ -836,20 +974,47 @@
478 dentry = fhp->fh_dentry;
479 dirp = dentry->d_inode;
483 + if (dirp->i_op->mkdir_raw)
484 + error = mkdir_raw(dentry, fname, flen, iap->ia_mode);
491 + if (dirp->i_op->mknod_raw) {
492 + if (type == S_IFREG)
494 + error = mknod_raw(dentry, fname,flen,iap->ia_mode,rdev);
498 + printk("nfsd: bad file type %o in nfsd_create\n", type);
500 + if (error && error != -EOPNOTSUPP) {
506 - if(!dirp->i_op || !dirp->i_op->lookup)
507 + if (!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it))
510 * Check whether the response file handle has been verified yet.
511 * If it has, the parent directory should already be locked.
513 - if (!resfhp->fh_dentry) {
514 - /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create */
516 + if (!resfhp->fh_dentry || dirp->i_op->lookup_it) {
517 + /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create
518 + * and nfsd_proc_create in case of lustre */
519 + if (!resfhp->fh_dentry)
521 dchild = lookup_one_len(fname, dentry, flen);
522 err = PTR_ERR(dchild);
525 + resfhp->fh_dentry = NULL;
526 err = fh_compose(resfhp, fhp->fh_export, dchild, fhp);
529 @@ -870,10 +1032,12 @@
530 * Make sure the child dentry is still negative ...
533 - if (dchild->d_inode) {
534 - dprintk("nfsd_create: dentry %s/%s not negative!\n",
535 - dentry->d_name.name, dchild->d_name.name);
537 + if (error == -EOPNOTSUPP) {
538 + if (dchild->d_inode) {
539 + dprintk("nfsd_create: dentry %s/%s not negative!\n",
540 + dentry->d_name.name, dchild->d_name.name);
545 if (!(iap->ia_valid & ATTR_MODE))
546 @@ -886,16 +1050,19 @@
550 - err = vfs_create(dirp, dchild, iap->ia_mode);
551 + if (error == -EOPNOTSUPP)
552 + err = vfs_create(dirp, dchild, iap->ia_mode);
555 - err = vfs_mkdir(dirp, dchild, iap->ia_mode);
556 + if (error == -EOPNOTSUPP)
557 + err = vfs_mkdir(dirp, dchild, iap->ia_mode);
563 - err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev);
564 + if (error == -EOPNOTSUPP)
565 + err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev);
568 printk("nfsd: bad file type %o in nfsd_create\n", type);
569 @@ -964,7 +1131,13 @@
570 /* Get all the sanity checks out of the way before
571 * we lock the parent. */
573 - if(!dirp->i_op || !dirp->i_op->lookup)
574 + if (dirp->i_op->mknod_raw) {
575 + err = mknod_raw(dentry, fname, flen, iap->ia_mode, 0);
576 + if (err && err != -EOPNOTSUPP)
580 + if (!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it))
584 @@ -1015,6 +1188,8 @@
585 case NFS3_CREATE_GUARDED:
588 + if (dirp->i_op->mknod_raw)
593 @@ -1121,7 +1296,7 @@
596 struct dentry *dentry, *dnew;
598 + int err, cerr, error = -EOPNOTSUPP;
602 @@ -1135,12 +1310,18 @@
605 dentry = fhp->fh_dentry;
607 + if (dentry->d_inode->i_op->symlink_raw)
608 + error = symlink_raw(dentry, fname, flen, path);
610 dnew = lookup_one_len(fname, dentry, flen);
615 - err = vfs_symlink(dentry->d_inode, dnew, path);
617 + if (err == -EOPNOTSUPP || !dentry->d_inode->i_op->symlink_raw)
618 + err = vfs_symlink(dentry->d_inode, dnew, path);
620 if (EX_ISSYNC(fhp->fh_export))
621 nfsd_sync_dir(dentry);
622 @@ -1150,7 +1331,10 @@
623 iap->ia_valid |= ATTR_CTIME;
624 iap->ia_mode = (iap->ia_mode&S_IALLUGO)
626 - err = notify_change(dnew, iap);
627 + if (dnew->d_inode->i_op && dnew->d_inode->i_op->setattr_raw)
628 + err = setattr_raw(dnew->d_inode, iap);
630 + err = notify_change(dnew, iap);
633 else if (EX_ISSYNC(fhp->fh_export))
634 @@ -1210,7 +1394,10 @@
635 dold = tfhp->fh_dentry;
636 dest = dold->d_inode;
638 - err = vfs_link(dold, dirp, dnew);
639 + if (dirp->i_op->link_raw)
640 + err = link_raw(dold, ddir, dnew);
642 + err = vfs_link(dold, dirp, dnew);
644 if (EX_ISSYNC(ffhp->fh_export)) {
646 @@ -1295,7 +1482,10 @@
650 - err = vfs_rename(fdir, odentry, tdir, ndentry);
651 + if (fdir->i_op->rename_raw)
652 + err = rename_raw(fdentry, tdentry, odentry, ndentry);
654 + err = vfs_rename(fdir, odentry, tdir, ndentry);
655 if (!err && EX_ISSYNC(tfhp->fh_export)) {
656 nfsd_sync_dir(tdentry);
657 nfsd_sync_dir(fdentry);
658 @@ -1316,7 +1506,7 @@
660 double_up(&tdir->i_sem, &fdir->i_sem);
661 ffhp->fh_locked = tfhp->fh_locked = 0;
667 @@ -1362,9 +1552,15 @@
671 - err = vfs_unlink(dirp, rdentry);
672 + if (dirp->i_op->unlink_raw)
673 + err = unlink_raw(dentry, fname, flen, rdentry);
675 + err = vfs_unlink(dirp, rdentry);
676 } else { /* It's RMDIR */
677 - err = vfs_rmdir(dirp, rdentry);
678 + if (dirp->i_op->rmdir_raw)
679 + err = rmdir_raw(dentry, fname, flen, rdentry);
681 + err = vfs_rmdir(dirp, rdentry);
685 Index: linux-2.4.22-vanilla/include/linux/fs.h
686 ===================================================================
687 --- linux-2.4.22-vanilla.orig/include/linux/fs.h 2003-11-03 23:41:40.000000000 +0300
688 +++ linux-2.4.22-vanilla/include/linux/fs.h 2003-11-03 23:44:38.000000000 +0300
690 #define FS_SINGLE 8 /* Filesystem that can have only one superblock */
691 #define FS_NOMOUNT 16 /* Never mount from userland */
692 #define FS_LITTER 32 /* Keeps the tree in dcache */
693 +#define FS_NFSEXP_FSID 64 /* Use file system specific fsid for
694 + * exporting non device filesystems. */
695 #define FS_ODD_RENAME 32768 /* Temporary stuff; will go away as soon
696 * as nfs_rename() will be cleaned up
698 @@ -1115,6 +1118,9 @@
699 struct nameidata *nd, struct lookup_intent *it);
700 extern struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt,
701 int flags, struct lookup_intent *it);
702 +extern int revalidate_it(struct dentry *dentry, struct lookup_intent *it);
703 +extern int init_private_file_it(struct file *, struct dentry *dentry, int mode,
704 + struct lookup_intent *it);
705 extern int filp_close(struct file *, fl_owner_t id);
706 extern char * getname(const char *);
708 @@ -1411,6 +1417,8 @@
709 extern int follow_down(struct vfsmount **, struct dentry **);
710 extern int follow_up(struct vfsmount **, struct dentry **);
711 extern struct dentry * lookup_one_len(const char *, struct dentry *, int);
712 +extern struct dentry * lookup_one_len_it(const char *, struct dentry *, int,
713 + struct lookup_intent *);
714 extern struct dentry * lookup_hash(struct qstr *, struct dentry *);
715 #define user_path_walk(name,nd) __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd)
716 #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd)
717 @@ -1425,6 +1433,8 @@
719 typedef int (*find_inode_t)(struct inode *, unsigned long, void *);
720 extern struct inode * iget4(struct super_block *, unsigned long, find_inode_t, void *);
721 +extern struct inode * ilookup4(struct super_block *, unsigned long,
722 + find_inode_t, void *);
723 static inline struct inode *iget(struct super_block *sb, unsigned long ino)
725 return iget4(sb, ino, NULL, NULL);
726 Index: linux-2.4.22-vanilla/kernel/ksyms.c
727 ===================================================================
728 --- linux-2.4.22-vanilla.orig/kernel/ksyms.c 2003-11-03 23:41:40.000000000 +0300
729 +++ linux-2.4.22-vanilla/kernel/ksyms.c 2003-11-03 23:44:38.000000000 +0300
731 EXPORT_SYMBOL(igrab);
732 EXPORT_SYMBOL(iunique);
733 EXPORT_SYMBOL(iget4);
734 +EXPORT_SYMBOL(ilookup4);
736 EXPORT_SYMBOL(inode_init_once);
737 EXPORT_SYMBOL(force_delete);
739 EXPORT_SYMBOL(path_release);
740 EXPORT_SYMBOL(__user_walk);
741 EXPORT_SYMBOL(lookup_one_len);
742 +EXPORT_SYMBOL(lookup_one_len_it);
743 EXPORT_SYMBOL(lookup_hash);
744 EXPORT_SYMBOL(sys_close);
745 EXPORT_SYMBOL(dcache_lock);