2 fs/file_table.c | 11 ++
6 fs/nfsd/nfsfh.c | 65 +++++++++++++-
7 fs/nfsd/vfs.c | 235 ++++++++++++++++++++++++++++++++++++++++++++++++-----
8 include/linux/fs.h | 11 ++
10 9 files changed, 333 insertions(+), 34 deletions(-)
12 Index: linux-2.4.21-chaos/fs/file_table.c
13 ===================================================================
14 --- linux-2.4.21-chaos.orig/fs/file_table.c 2003-07-15 04:41:00.000000000 +0400
15 +++ linux-2.4.21-chaos/fs/file_table.c 2003-12-12 16:19:25.000000000 +0300
17 * and call the open function (if any). The caller must verify that
18 * inode->i_fop is not NULL.
20 -int init_private_file(struct file *filp, struct dentry *dentry, int mode)
21 +int init_private_file_it(struct file *filp, struct dentry *dentry, int mode,
22 + struct lookup_intent *it)
24 memset(filp, 0, sizeof(*filp));
27 filp->f_dentry = dentry;
28 filp->f_uid = current->fsuid;
29 filp->f_gid = current->fsgid;
32 filp->f_op = dentry->d_inode->i_fop;
34 return filp->f_op->open(dentry->d_inode, filp);
38 +EXPORT_SYMBOL(init_private_file_it);
40 +int init_private_file(struct file *filp, struct dentry *dentry, int mode)
42 + return init_private_file_it(filp, dentry, mode, NULL);
45 void fput(struct file * file)
47 Index: linux-2.4.21-chaos/fs/inode.c
48 ===================================================================
49 --- linux-2.4.21-chaos.orig/fs/inode.c 2003-12-12 16:18:15.000000000 +0300
50 +++ linux-2.4.21-chaos/fs/inode.c 2003-12-12 16:19:25.000000000 +0300
51 @@ -1054,9 +1054,10 @@
55 -struct inode *iget4_locked(struct super_block *sb, unsigned long ino, find_inode_t find_actor, void *opaque)
56 +struct inode *ifind(struct super_block *sb, unsigned long ino,
57 + struct list_head *head,
58 + find_inode_t find_actor, void *opaque)
60 - struct list_head * head = inode_hashtable + hash(sb,ino);
63 spin_lock(&inode_lock);
64 @@ -1069,6 +1070,24 @@
66 spin_unlock(&inode_lock);
71 +struct inode *ilookup4(struct super_block *sb, unsigned long ino,
72 + find_inode_t find_actor, void *opaque)
74 + struct list_head * head = inode_hashtable + hash(sb,ino);
75 + return ifind(sb, ino, head, find_actor, opaque);
78 +struct inode *iget4_locked(struct super_block *sb, unsigned long ino,
79 + find_inode_t find_actor, void *opaque)
81 + struct list_head * head = inode_hashtable + hash(sb,ino);
82 + struct inode *inode = ifind(sb, ino, head, find_actor, opaque);
87 * get_new_inode() will do the right thing, re-trying the search
88 * in case it had to block at any point.
89 Index: linux-2.4.21-chaos/fs/Makefile
90 ===================================================================
91 --- linux-2.4.21-chaos.orig/fs/Makefile 2003-12-12 16:18:36.000000000 +0300
92 +++ linux-2.4.21-chaos/fs/Makefile 2003-12-12 16:19:25.000000000 +0300
97 -export-objs := filesystems.o open.o dcache.o buffer.o dquot.o inode.o
98 +export-objs := filesystems.o open.o dcache.o buffer.o dquot.o inode.o \
99 + namei.o file_table.o
100 mod-subdirs := nls xfs
102 obj-y := open.o read_write.o devices.o file_table.o buffer.o \
103 Index: linux-2.4.21-chaos/fs/namei.c
104 ===================================================================
105 --- linux-2.4.21-chaos.orig/fs/namei.c 2003-12-12 16:18:06.000000000 +0300
106 +++ linux-2.4.21-chaos/fs/namei.c 2003-12-12 16:19:25.000000000 +0300
108 #include <linux/dnotify.h>
109 #include <linux/smp_lock.h>
110 #include <linux/personality.h>
111 +#include <linux/module.h>
113 #include <asm/namei.h>
114 #include <asm/uaccess.h>
116 it->it_op_release(it);
119 +EXPORT_SYMBOL(intent_release);
121 /* In order to reduce some races, while at the same time doing additional
122 * checking and hopefully speeding things up, we copy filenames to the
127 -struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
128 +struct dentry * lookup_one_len_it(const char * name, struct dentry * base,
129 + int len, struct lookup_intent *it)
133 @@ -930,11 +933,16 @@
135 this.hash = end_name_hash(hash);
137 - return lookup_hash_it(&this, base, NULL);
138 + return lookup_hash_it(&this, base, it);
140 return ERR_PTR(-EACCES);
143 +struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
145 + return lookup_one_len_it(name, base, len, NULL);
151 Index: linux-2.4.21-chaos/fs/nfsd/export.c
152 ===================================================================
153 --- linux-2.4.21-chaos.orig/fs/nfsd/export.c 2003-09-19 03:49:54.000000000 +0400
154 +++ linux-2.4.21-chaos/fs/nfsd/export.c 2003-12-12 16:19:25.000000000 +0300
156 inode = nd.dentry->d_inode;
159 + if ((inode->i_sb->s_type->fs_flags & FS_NFSEXP_FSID) &&
160 + !(nxp->ex_flags & NFSEXP_FSID)) {
161 + nxp->ex_dev = inode->i_sb->s_dev;
162 + nxp->ex_flags |= NFSEXP_FSID;
166 exp = exp_get(clp, dev, ino);
167 Index: linux-2.4.21-chaos/fs/nfsd/nfsfh.c
168 ===================================================================
169 --- linux-2.4.21-chaos.orig/fs/nfsd/nfsfh.c 2003-09-19 03:49:54.000000000 +0400
170 +++ linux-2.4.21-chaos/fs/nfsd/nfsfh.c 2003-12-12 16:19:25.000000000 +0300
172 int sequence; /* sequence counter */
175 +static struct dentry *lookup_it(struct inode *inode, struct dentry * dentry)
177 + if (inode->i_op->lookup_it)
178 + return inode->i_op->lookup_it(inode, dentry, NULL, 0);
179 + return inode->i_op->lookup(inode, dentry);
183 * A rather strange filldir function to capture
184 * the name matching the specified inode number.
188 struct nfsd_getdents_callback buffer;
189 + struct lookup_intent it;
190 + struct file *filp = NULL;
193 if (!dir || !S_ISDIR(dir->i_mode))
196 * Open the directory ...
198 - error = init_private_file(&file, dentry, FMODE_READ);
200 + if (dentry->d_op && dentry->d_op->d_revalidate_it) {
201 + if ((dentry->d_flags & DCACHE_NFSD_DISCONNECTED) &&
202 + (dentry->d_parent == dentry) ) {
203 + it.it_op_release = NULL;
205 + * XXX Temporary Hack: Simulate init_private_file without
206 + * f_op->open for disconnected dentry as we don't have
207 + * actual dentry->d_name to revalidate in revalidate_it()
210 + memset(filp, 0, sizeof(*filp));
211 + filp->f_mode = FMODE_READ;
212 + atomic_set(&filp->f_count, 1);
213 + filp->f_dentry = dentry;
214 + filp->f_uid = current->fsuid;
215 + filp->f_gid = current->fsgid;
216 + filp->f_op = dentry->d_inode->i_fop;
219 + intent_init(&it, IT_OPEN, FMODE_READ);
220 + error = revalidate_it(dentry, &it);
223 + error = init_private_file_it(&file, dentry, FMODE_READ, &it);
226 + error = init_private_file_it(&file, dentry, FMODE_READ, NULL);
232 if (!file.f_op->readdir)
238 - if (file.f_op->release)
239 + if (file.f_op->release && !filp)
240 file.f_op->release(dir, &file);
242 + if (dentry->d_op && dentry->d_op->d_revalidate_it &&
243 + it.it_op_release && !filp)
244 + intent_release(&it);
249 * it is well connected. But nobody returns different dentrys do they?
251 down(&child->d_inode->i_sem);
252 - pdentry = child->d_inode->i_op->lookup(child->d_inode, tdentry);
253 + pdentry = lookup_it(child->d_inode, tdentry);
254 up(&child->d_inode->i_sem);
255 d_drop(tdentry); /* we never want ".." hashed */
256 if (!pdentry && tdentry->d_inode == NULL) {
258 pdentry->d_flags |= DCACHE_NFSD_DISCONNECTED;
259 pdentry->d_op = child->d_op;
261 + if (child->d_op && child->d_op->d_revalidate_it)
262 + pdentry->d_op = child->d_op;
265 pdentry = ERR_PTR(-ENOMEM);
267 struct dentry *pdentry;
268 struct inode *parent;
270 + if (result->d_op && result->d_op->d_revalidate_it)
271 + dentry->d_op = result->d_op;
272 pdentry = nfsd_findparent(dentry);
273 err = PTR_ERR(pdentry);
277 inode = dentry->d_inode;
279 + /* cache coherency for non-device filesystems */
280 + if (inode->i_op && inode->i_op->revalidate_it)
281 + inode->i_op->revalidate_it(dentry, NULL);
283 /* Type check. The correct error return for type mismatches
284 * does not seem to be generally agreed upon. SunOS seems to
285 * use EISDIR if file isn't S_IFREG; a comment in the NFSv3
287 dentry->d_parent->d_name.name, dentry->d_name.name);
290 - printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n",
291 - dentry->d_parent->d_name.name, dentry->d_name.name);
292 + if (!dentry->d_parent->d_inode->i_op->mkdir_raw)
293 + printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n",
294 + dentry->d_parent->d_name.name, dentry->d_name.name);
298 Index: linux-2.4.21-chaos/fs/nfsd/vfs.c
299 ===================================================================
300 --- linux-2.4.21-chaos.orig/fs/nfsd/vfs.c 2003-09-19 03:49:54.000000000 +0400
301 +++ linux-2.4.21-chaos/fs/nfsd/vfs.c 2003-12-12 16:19:25.000000000 +0300
303 static struct raparms * raparml;
304 static struct raparms * raparm_cache;
306 +static int link_raw(struct dentry *dold, struct dentry *ddir,
307 + struct dentry *dnew)
311 + struct nameidata old_nd = { .dentry = dold };
312 + struct nameidata nd = { .dentry = ddir, .last = dnew->d_name };
313 + struct inode_operations *op = nd.dentry->d_inode->i_op;
314 + err = op->link_raw(&old_nd, &nd);
315 + igrab(dold->d_inode);
316 + d_instantiate(dnew, dold->d_inode);
317 + if (dold->d_inode->i_op && dold->d_inode->i_op->revalidate_it)
318 + dold->d_inode->i_op->revalidate_it(dnew, NULL);
323 +static int unlink_raw(struct dentry *dentry, char *fname, int flen,
324 + struct dentry *rdentry)
327 + struct qstr last = { .name = fname, .len = flen };
328 + struct nameidata nd = { .dentry = dentry, .last = last };
329 + struct inode_operations *op = nd.dentry->d_inode->i_op;
330 + err = op->unlink_raw(&nd);
337 +static int rmdir_raw(struct dentry *dentry, char *fname, int flen,
338 + struct dentry *rdentry)
341 + struct qstr last = { .name = fname, .len = flen };
342 + struct nameidata nd = { .dentry = dentry, .last = last };
343 + struct inode_operations *op = nd.dentry->d_inode->i_op;
344 + err = op->rmdir_raw(&nd);
346 + rdentry->d_inode->i_flags |= S_DEAD;
353 +static int symlink_raw(struct dentry *dentry, char *fname, int flen,
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->symlink_raw(&nd, path);
365 +static int mkdir_raw(struct dentry *dentry, char *fname, int flen, int mode)
368 + struct qstr last = { .name = fname, .len = flen };
369 + struct nameidata nd = { .dentry = dentry, .last = last };
370 + struct inode_operations *op = nd.dentry->d_inode->i_op;
371 + err = op->mkdir_raw(&nd, mode);
376 +static int mknod_raw(struct dentry *dentry, char *fname, int flen, int mode,
380 + struct qstr last = { .name = fname, .len = flen };
381 + struct nameidata nd = { .dentry = dentry, .last = last };
382 + struct inode_operations *op = nd.dentry->d_inode->i_op;
383 + err = op->mknod_raw(&nd, mode, dev);
388 +static int rename_raw(struct dentry *fdentry, struct dentry *tdentry,
389 + struct dentry *odentry, struct dentry *ndentry)
393 + struct nameidata old_nd = { .dentry = fdentry, .last = odentry->d_name};
394 + struct nameidata new_nd = { .dentry = tdentry, .last = ndentry->d_name};
395 + struct inode_operations *op = old_nd.dentry->d_inode->i_op;
396 + err = op->rename_raw(&old_nd, &new_nd);
397 + d_move(odentry, ndentry);
402 +static int setattr_raw(struct inode *inode, struct iattr *iap)
406 + iap->ia_valid |= ATTR_RAW;
407 + err = inode->i_op->setattr_raw(inode, iap);
412 +int revalidate_it(struct dentry *dentry, struct lookup_intent *it)
416 + if (dentry && dentry->d_op && dentry->d_op->d_revalidate_it) {
417 + if (!dentry->d_op->d_revalidate_it(dentry, 0, it) &&
418 + !d_invalidate(dentry)) {
428 * Look up one component of a pathname.
429 * N.B. After this call _both_ fhp and resfh need an fh_put
432 err = nfserr_notsync;
433 if (!check_guard || guardtime == inode->i_ctime) {
434 - err = notify_change(dentry, iap);
435 + if (dentry->d_inode->i_op && dentry->d_inode->i_op->setattr_raw)
436 + err = setattr_raw(dentry->d_inode, iap);
438 + err = notify_change(dentry, iap);
444 struct dentry *dentry;
446 + struct lookup_intent it;
449 /* If we get here, then the client has already done an "open", and (hopefully)
451 filp->f_mode = FMODE_READ;
454 +#ifndef O_OWNER_OVERRIDE
455 +#define O_OWNER_OVERRIDE 0200000000
457 + intent_init(&it, IT_OPEN, (filp->f_flags & ~O_ACCMODE) | filp->f_mode |
460 + err = revalidate_it(dentry, &it);
467 if (filp->f_op && filp->f_op->open) {
468 err = filp->f_op->open(inode, filp);
473 + if (it.it_op_release)
474 + intent_release(&it);
481 struct dentry *dentry, *dchild;
484 + int err, error = -EOPNOTSUPP;
488 @@ -837,20 +975,47 @@
489 dentry = fhp->fh_dentry;
490 dirp = dentry->d_inode;
494 + if (dirp->i_op->mkdir_raw)
495 + error = mkdir_raw(dentry, fname, flen, iap->ia_mode);
502 + if (dirp->i_op->mknod_raw) {
503 + if (type == S_IFREG)
505 + error = mknod_raw(dentry, fname,flen,iap->ia_mode,rdev);
509 + printk("nfsd: bad file type %o in nfsd_create\n", type);
511 + if (error && error != -EOPNOTSUPP) {
517 - if(!dirp->i_op || !dirp->i_op->lookup)
518 + if (!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it))
521 * Check whether the response file handle has been verified yet.
522 * If it has, the parent directory should already be locked.
524 - if (!resfhp->fh_dentry) {
525 - /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create */
527 + if (!resfhp->fh_dentry || dirp->i_op->lookup_it) {
528 + /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create
529 + * and nfsd_proc_create in case of lustre */
530 + if (!resfhp->fh_dentry)
532 dchild = lookup_one_len(fname, dentry, flen);
533 err = PTR_ERR(dchild);
536 + resfhp->fh_dentry = NULL;
537 err = fh_compose(resfhp, fhp->fh_export, dchild, fhp);
540 @@ -871,10 +1033,12 @@
541 * Make sure the child dentry is still negative ...
544 - if (dchild->d_inode) {
545 - dprintk("nfsd_create: dentry %s/%s not negative!\n",
546 - dentry->d_name.name, dchild->d_name.name);
548 + if (error == -EOPNOTSUPP) {
549 + if (dchild->d_inode) {
550 + dprintk("nfsd_create: dentry %s/%s not negative!\n",
551 + dentry->d_name.name, dchild->d_name.name);
556 if (!(iap->ia_valid & ATTR_MODE))
557 @@ -887,16 +1051,19 @@
561 - err = vfs_create(dirp, dchild, iap->ia_mode);
562 + if (error == -EOPNOTSUPP)
563 + err = vfs_create(dirp, dchild, iap->ia_mode);
566 - err = vfs_mkdir(dirp, dchild, iap->ia_mode);
567 + if (error == -EOPNOTSUPP)
568 + err = vfs_mkdir(dirp, dchild, iap->ia_mode);
574 - err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev);
575 + if (error == -EOPNOTSUPP)
576 + err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev);
579 printk("nfsd: bad file type %o in nfsd_create\n", type);
580 @@ -965,7 +1132,13 @@
581 /* Get all the sanity checks out of the way before
582 * we lock the parent. */
584 - if(!dirp->i_op || !dirp->i_op->lookup)
585 + if (dirp->i_op->mknod_raw) {
586 + err = mknod_raw(dentry, fname, flen, iap->ia_mode, 0);
587 + if (err && err != -EOPNOTSUPP)
591 + if (!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it))
595 @@ -1016,6 +1189,8 @@
596 case NFS3_CREATE_GUARDED:
599 + if (dirp->i_op->mknod_raw)
604 @@ -1122,7 +1297,7 @@
607 struct dentry *dentry, *dnew;
609 + int err, cerr, error = -EOPNOTSUPP;
613 @@ -1136,12 +1311,18 @@
616 dentry = fhp->fh_dentry;
618 + if (dentry->d_inode->i_op->symlink_raw)
619 + error = symlink_raw(dentry, fname, flen, path);
621 dnew = lookup_one_len(fname, dentry, flen);
626 - err = vfs_symlink(dentry->d_inode, dnew, path);
628 + if (err == -EOPNOTSUPP || !dentry->d_inode->i_op->symlink_raw)
629 + err = vfs_symlink(dentry->d_inode, dnew, path);
631 if (EX_ISSYNC(fhp->fh_export))
632 nfsd_sync_dir(dentry);
633 @@ -1148,7 +1329,10 @@ nfsd_symlink(struct svc_rqst *rqstp, str
634 iap->ia_valid |= ATTR_CTIME;
635 iap->ia_mode = (iap->ia_mode&S_IALLUGO)
637 - err = notify_change(dnew, iap);
638 + if (dnew->d_inode->i_op && dnew->d_inode->i_op->setattr_raw)
639 + err = setattr_raw(dnew->d_inode, iap);
641 + err = notify_change(dnew, iap);
644 else if (EX_ISSYNC(fhp->fh_export))
645 @@ -1211,7 +1392,10 @@
646 dold = tfhp->fh_dentry;
647 dest = dold->d_inode;
649 - err = vfs_link(dold, dirp, dnew);
650 + if (dirp->i_op->link_raw)
651 + err = link_raw(dold, ddir, dnew);
653 + err = vfs_link(dold, dirp, dnew);
655 if (EX_ISSYNC(ffhp->fh_export)) {
657 @@ -1296,7 +1480,10 @@
661 - err = vfs_rename(fdir, odentry, tdir, ndentry);
662 + if (fdir->i_op->rename_raw)
663 + err = rename_raw(fdentry, tdentry, odentry, ndentry);
665 + err = vfs_rename(fdir, odentry, tdir, ndentry);
666 if (!err && EX_ISSYNC(tfhp->fh_export)) {
667 nfsd_sync_dir(tdentry);
668 nfsd_sync_dir(fdentry);
669 @@ -1317,7 +1504,7 @@
671 double_up(&tdir->i_sem, &fdir->i_sem);
672 ffhp->fh_locked = tfhp->fh_locked = 0;
678 @@ -1363,9 +1550,15 @@
682 - err = vfs_unlink(dirp, rdentry);
683 + if (dirp->i_op->unlink_raw)
684 + err = unlink_raw(dentry, fname, flen, rdentry);
686 + err = vfs_unlink(dirp, rdentry);
687 } else { /* It's RMDIR */
688 - err = vfs_rmdir(dirp, rdentry);
689 + if (dirp->i_op->rmdir_raw)
690 + err = rmdir_raw(dentry, fname, flen, rdentry);
692 + err = vfs_rmdir(dirp, rdentry);
696 Index: linux-2.4.21-chaos/include/linux/fs.h
697 ===================================================================
698 --- linux-2.4.21-chaos.orig/include/linux/fs.h 2003-12-12 16:19:23.000000000 +0300
699 +++ linux-2.4.21-chaos/include/linux/fs.h 2003-12-12 16:19:25.000000000 +0300
701 #define FS_SINGLE 8 /* Filesystem that can have only one superblock */
702 #define FS_NOMOUNT 16 /* Never mount from userland */
703 #define FS_LITTER 32 /* Keeps the tree in dcache */
704 +#define FS_NFSEXP_FSID 64 /* Use file system specific fsid for
705 + * exporting non device filesystems. */
706 #define FS_ODD_RENAME 32768 /* Temporary stuff; will go away as soon
707 * as nfs_rename() will be cleaned up
709 @@ -1159,6 +1162,9 @@
710 struct nameidata *nd, struct lookup_intent *it);
711 extern struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt,
712 int flags, struct lookup_intent *it);
713 +extern int revalidate_it(struct dentry *dentry, struct lookup_intent *it);
714 +extern int init_private_file_it(struct file *, struct dentry *dentry, int mode,
715 + struct lookup_intent *it);
716 extern int filp_close(struct file *, fl_owner_t id);
717 extern char * getname(const char *);
719 @@ -1458,6 +1464,8 @@
720 extern int follow_down(struct vfsmount **, struct dentry **);
721 extern int follow_up(struct vfsmount **, struct dentry **);
722 extern struct dentry * lookup_one_len(const char *, struct dentry *, int);
723 +extern struct dentry * lookup_one_len_it(const char *, struct dentry *, int,
724 + struct lookup_intent *);
725 extern struct dentry * __lookup_hash(struct qstr *, struct dentry *);
726 extern struct dentry * lookup_hash(struct qstr *, struct dentry *);
727 #define user_path_walk(name,nd) __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd)
728 @@ -1477,6 +1485,8 @@
730 extern struct inode * iget4_locked(struct super_block *, unsigned long,
731 find_inode_t, void *);
732 +extern struct inode * ilookup4(struct super_block *, unsigned long,
733 + find_inode_t, void *);
735 static inline struct inode *iget4(struct super_block *sb, unsigned long ino,
736 find_inode_t find_actor, void *opaque)
737 Index: linux-2.4.21-chaos/kernel/ksyms.c
738 ===================================================================
739 --- linux-2.4.21-chaos.orig/kernel/ksyms.c 2003-12-12 16:18:36.000000000 +0300
740 +++ linux-2.4.21-chaos/kernel/ksyms.c 2003-12-12 16:19:25.000000000 +0300
742 EXPORT_SYMBOL(igrab);
743 EXPORT_SYMBOL(iunique);
744 EXPORT_SYMBOL(iget4_locked);
745 +EXPORT_SYMBOL(ilookup4);
746 EXPORT_SYMBOL(unlock_new_inode);
748 EXPORT_SYMBOL(inode_init_once);
750 EXPORT_SYMBOL(path_release);
751 EXPORT_SYMBOL(__user_walk);
752 EXPORT_SYMBOL(lookup_one_len);
753 +EXPORT_SYMBOL(lookup_one_len_it);
754 EXPORT_SYMBOL(lookup_hash);
756 EXPORT_SYMBOL(sys_close);