From 1210c56d300edbdfb52bd20b2f4d4fd686f66e6f Mon Sep 17 00:00:00 2001 From: adilger Date: Wed, 16 Mar 2005 02:27:44 +0000 Subject: [PATCH] Branch: b1_4 Allow NFSD to reopen files for write that were created without write perms. This is needed for HPUX NFS clients (cp creates files with mode 000), and Linux NFS test progs that intentionally do the same because NFSD always reopens files for each client RPC and loses the Lustre initial open(O_CREAT) file handle that was allowed to open-for-write a readonly file. This only works for the file owner so it is no net loss of security (the user could always just chmod a file and then write to it). Tested at HP. b=5781 r=peter (concept) --- lustre/ChangeLog | 12 +- lustre/include/linux/lustre_idl.h | 1 + .../patches/nfs_export_kernel-2.4.20-hp.patch | 174 ++++++++------- .../patches/nfs_export_kernel-2.4.20-rh.patch | 172 +++++++-------- .../patches/nfs_export_kernel-2.4.20.patch | 172 +++++++-------- .../patches/nfs_export_kernel-2.4.21-chaos.patch | 239 ++++++++++----------- .../patches/nfs_export_kernel-2.4.21-suse2.patch | 177 ++++++++------- .../patches/nfs_export_kernel-2.4.22-rh.patch | 179 ++++++++------- .../patches/nfs_export_kernel-2.4.22.patch | 174 +++++++-------- lustre/mdc/mdc_lib.c | 2 +- lustre/mds/mds_open.c | 18 +- 11 files changed, 664 insertions(+), 656 deletions(-) diff --git a/lustre/ChangeLog b/lustre/ChangeLog index c3dcfd0..3033df3 100644 --- a/lustre/ChangeLog +++ b/lustre/ChangeLog @@ -1,4 +1,12 @@ -tbd Cluster File Systems, Inc. +2005-03-31 Cluster File Systems, Inc. + * version 1.4.2 + * bug fixes + - fix deadlock in obdfilter statistics vs. object create (5811) + - fix for HPUX NFS client breakage when NFS exporting Lustre (5781) + * miscellania + - by default create 1 inode per 4kB space on MDS, per 16kB on OSTs + +2005-03-18 Cluster File Systems, Inc. * version 1.4.1 * bug fixes - don't LASSERT in ll_release on NULL lld with NFS export (4655, 5760) @@ -14,13 +22,11 @@ tbd Cluster File Systems, Inc. - fix several locking issues related to i_size (5492,5624,5654,5672) - don't move pending lock onto export if it is already evicted (5683) - fix kernel oops when creating .foo in unlinked directory (5548) - - fix deadlock in obdfilter statistics vs. object create (5811) * miscellania - fix lustre/lustrefs init scripts for SuSE (patch from Scali, 5702) - don't hold the pinger_sem in ptlrpc_pinger_sending_on_import - change obd_increase_kms to obd_adjust_kms (up or down) (5654) - lconf, lmc search both /usr/lib and /usr/lib64 for Python libs (5800) - - by default create 1 inode per 4kB space on MDS, per 16kB on OSTs 2005-02-18 Cluster File Systems, Inc. * version 1.4.0.10 (1.4.1 release candidate 1) diff --git a/lustre/include/linux/lustre_idl.h b/lustre/include/linux/lustre_idl.h index 1101778..e1aa3c9 100644 --- a/lustre/include/linux/lustre_idl.h +++ b/lustre/include/linux/lustre_idl.h @@ -553,6 +553,7 @@ extern void lustre_swab_mds_rec_setattr (struct mds_rec_setattr *sa); #define MDS_OPEN_DIRECTORY 00200000 #define MDS_OPEN_DELAY_CREATE 0100000000 /* delay initial object create */ +#define MDS_OPEN_OWNEROVERRIDE 0200000000 /* NFSD rw-reopen ro file for owner */ #define MDS_OPEN_HAS_EA 010000000000 /* specify object create pattern */ #define MDS_OPEN_HAS_OBJS 020000000000 /* Just set the EA the obj exist */ diff --git a/lustre/kernel_patches/patches/nfs_export_kernel-2.4.20-hp.patch b/lustre/kernel_patches/patches/nfs_export_kernel-2.4.20-hp.patch index 2a669e5..a8ad4a2 100644 --- a/lustre/kernel_patches/patches/nfs_export_kernel-2.4.20-hp.patch +++ b/lustre/kernel_patches/patches/nfs_export_kernel-2.4.20-hp.patch @@ -17,7 +17,7 @@ */ -int init_private_file(struct file *filp, struct dentry *dentry, int mode) +int init_private_file_it(struct file *filp, struct dentry *dentry, int mode, -+ struct lookup_intent *it) ++ struct lookup_intent *it) { memset(filp, 0, sizeof(*filp)); filp->f_mode = mode; @@ -50,8 +50,8 @@ -struct inode *iget4_locked(struct super_block *sb, unsigned long ino, find_inode_t find_actor, void *opaque) +struct inode *ifind(struct super_block *sb, unsigned long ino, -+ struct list_head *head, -+ find_inode_t find_actor, void *opaque) ++ struct list_head *head, ++ find_inode_t find_actor, void *opaque) { - struct list_head * head = inode_hashtable + hash(sb,ino); struct inode * inode; @@ -65,14 +65,14 @@ +} + +struct inode *ilookup4(struct super_block *sb, unsigned long ino, -+ find_inode_t find_actor, void *opaque) ++ find_inode_t find_actor, void *opaque) +{ + struct list_head * head = inode_hashtable + hash(sb,ino); + return ifind(sb, ino, head, find_actor, opaque); +} + +struct inode *iget4_locked(struct super_block *sb, unsigned long ino, -+ find_inode_t find_actor, void *opaque) ++ find_inode_t find_actor, void *opaque) +{ + struct list_head * head = inode_hashtable + hash(sb,ino); + struct inode *inode = ifind(sb, ino, head, find_actor, opaque); @@ -118,7 +118,7 @@ /* SMP-safe */ -struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) +struct dentry * lookup_one_len_it(const char * name, struct dentry * base, -+ int len, struct lookup_intent *it) ++ int len, struct lookup_intent *it) { unsigned long hash; struct qstr this; @@ -148,25 +148,23 @@ ino = inode->i_ino; + if ((inode->i_sb->s_type->fs_flags & FS_NFSEXP_FSID) && + !(nxp->ex_flags & NFSEXP_FSID)) { -+ nxp->ex_dev = inode->i_sb->s_dev; -+ nxp->ex_flags |= NFSEXP_FSID; ++ nxp->ex_dev = inode->i_sb->s_dev; ++ nxp->ex_flags |= NFSEXP_FSID; + } err = -EINVAL; exp = exp_get(clp, dev, ino); --- linux-2.4.20-hp4-pnnl13/fs/nfsd/nfsfh.c~nfs_export_kernel-2.4.20-hp 2002-11-29 02:53:15.000000000 +0300 +++ linux-2.4.20-hp4-pnnl13-alexey/fs/nfsd/nfsfh.c 2003-10-08 10:54:08.000000000 +0400 -@@ -36,6 +36,15 @@ struct nfsd_getdents_callback { +@@ -36,6 +36,13 @@ struct nfsd_getdents_callback { int sequence; /* sequence counter */ }; +static struct dentry *lookup_it(struct inode *inode, struct dentry * dentry) +{ + if (inode->i_op->lookup_it) -+ return inode->i_op->lookup_it(inode, dentry, NULL, 0); -+ else -+ return inode->i_op->lookup(inode, dentry); -+ ++ return inode->i_op->lookup_it(inode, dentry, NULL, 0); ++ return inode->i_op->lookup(inode, dentry); +} + /* @@ -191,10 +189,10 @@ + if ((dentry->d_flags & DCACHE_NFSD_DISCONNECTED) && + (dentry->d_parent == dentry) ) { + it.it_op_release = NULL; -+ /* -+ * XXX Temporary Hack: Simulating init_private_file without -+ * f_op->open for disconnected dentry Since we don't have actual -+ * dentry->d_name to revalidate in revalidate_it() ++ /* ++ * XXX Temporary Hack: Simulate init_private_file without ++ * f_op->open for disconnected dentry as we don't have ++ * actual dentry->d_name to revalidate in revalidate_it() + */ + filp = &file; + memset(filp, 0, sizeof(*filp)); @@ -215,13 +213,13 @@ + } else { + error = init_private_file_it(&file, dentry, FMODE_READ, NULL); + } -+ if (error) ++ if (error) goto out; + error = -EINVAL; if (!file.f_op->readdir) goto out_close; -@@ -113,9 +152,13 @@ static int nfsd_get_name(struct dentry * +@@ -113,9 +152,12 @@ static int nfsd_get_name(struct dentry * } out_close: @@ -229,8 +227,7 @@ + if (file.f_op->release && !filp) file.f_op->release(dir, &file); out: -+ if (dentry->d_op && -+ dentry->d_op->d_revalidate_it && ++ if (dentry->d_op && dentry->d_op->d_revalidate_it && + it.it_op_release && !filp) + intent_release(&it); return error; @@ -263,14 +260,13 @@ pdentry = nfsd_findparent(dentry); err = PTR_ERR(pdentry); if (IS_ERR(pdentry)) -@@ -662,6 +709,11 @@ fh_verify(struct svc_rqst *rqstp, struct +@@ -662,6 +709,10 @@ fh_verify(struct svc_rqst *rqstp, struct inode = dentry->d_inode; + /* cache coherency for non-device filesystems */ -+ if (inode->i_op && inode->i_op->revalidate_it) { -+ inode->i_op->revalidate_it(dentry, NULL); -+ } ++ if (inode->i_op && inode->i_op->revalidate_it) ++ inode->i_op->revalidate_it(dentry, NULL); + /* Type check. The correct error return for type mismatches * does not seem to be generally agreed upon. SunOS seems to @@ -281,9 +277,9 @@ out_uptodate: - printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n", - dentry->d_parent->d_name.name, dentry->d_name.name); -+ if(!dentry->d_parent->d_inode->i_op->mkdir_raw) ++ if (!dentry->d_parent->d_inode->i_op->mkdir_raw) + printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n", -+ dentry->d_parent->d_name.name, dentry->d_name.name); ++ dentry->d_parent->d_name.name, dentry->d_name.name); goto out; } @@ -294,7 +290,7 @@ static struct raparms * raparm_cache; +static int link_raw(struct dentry *dold, struct dentry *ddir, -+ struct dentry *dnew) ++ struct dentry *dnew) +{ + int err; + @@ -303,17 +299,17 @@ + struct inode_operations *op = nd.dentry->d_inode->i_op; + err = op->link_raw(&old_nd, &nd); + d_instantiate(dnew, dold->d_inode); -+ if(dold->d_inode->i_op && dold->d_inode->i_op->revalidate_it) ++ if (dold->d_inode->i_op && dold->d_inode->i_op->revalidate_it) + dold->d_inode->i_op->revalidate_it(dnew, NULL); + + return err; +} + +static int unlink_raw(struct dentry *dentry, char *fname, int flen, -+ struct dentry *rdentry) ++ struct dentry *rdentry) +{ + int err; -+ struct qstr last = { .name = fname, .len = flen }; ++ struct qstr last = { .name = fname, .len = flen }; + struct nameidata nd = { .dentry = dentry, .last = last }; + struct inode_operations *op = nd.dentry->d_inode->i_op; + err = op->unlink_raw(&nd); @@ -324,14 +320,14 @@ +} + +static int rmdir_raw(struct dentry *dentry, char *fname, int flen, -+ struct dentry *rdentry) ++ struct dentry *rdentry) +{ + int err; -+ struct qstr last = { .name = fname, .len = flen }; ++ struct qstr last = { .name = fname, .len = flen }; + struct nameidata nd = { .dentry = dentry, .last = last }; + struct inode_operations *op = nd.dentry->d_inode->i_op; + err = op->rmdir_raw(&nd); -+ if(!err) { ++ if (!err) { + rdentry->d_inode->i_flags |= S_DEAD; + d_delete(rdentry); + } @@ -339,11 +335,11 @@ + return err; +} + -+static int symlink_raw(struct dentry *dentry, char *fname, int flen, -+ char *path) ++static int symlink_raw(struct dentry *dentry, char *fname, int flen, ++ char *path) +{ + int err; -+ struct qstr last = { .name = fname, .len = flen }; ++ struct qstr last = { .name = fname, .len = flen }; + struct nameidata nd = { .dentry = dentry, .last = last }; + struct inode_operations *op = nd.dentry->d_inode->i_op; + err = op->symlink_raw(&nd, path); @@ -354,7 +350,7 @@ +static int mkdir_raw(struct dentry *dentry, char *fname, int flen, int mode) +{ + int err; -+ struct qstr last = { .name = fname, .len = flen }; ++ struct qstr last = { .name = fname, .len = flen }; + struct nameidata nd = { .dentry = dentry, .last = last }; + struct inode_operations *op = nd.dentry->d_inode->i_op; + err = op->mkdir_raw(&nd, mode); @@ -363,19 +359,19 @@ +} + +static int mknod_raw(struct dentry *dentry, char *fname, int flen, int mode, -+ dev_t dev) ++ dev_t dev) +{ + int err; -+ struct qstr last = { .name = fname, .len = flen }; ++ struct qstr last = { .name = fname, .len = flen }; + struct nameidata nd = { .dentry = dentry, .last = last }; + struct inode_operations *op = nd.dentry->d_inode->i_op; + err = op->mknod_raw(&nd, mode, dev); + + return err; -+} ++} + +static int rename_raw(struct dentry *fdentry, struct dentry *tdentry, -+ struct dentry *odentry, struct dentry *ndentry) ++ struct dentry *odentry, struct dentry *ndentry) +{ + int err; + @@ -421,7 +417,7 @@ err = nfserr_notsync; if (!check_guard || guardtime == inode->i_ctime) { - err = notify_change(dentry, iap); -+ if ( dentry->d_inode->i_op && dentry->d_inode->i_op->setattr_raw) ++ if (dentry->d_inode->i_op && dentry->d_inode->i_op->setattr_raw) + err = setattr_raw(dentry->d_inode, iap); + else + err = notify_change(dentry, iap); @@ -436,26 +432,28 @@ int err; /* If we get here, then the client has already done an "open", and (hopefully) -@@ -473,6 +599,14 @@ nfsd_open(struct svc_rqst *rqstp, struct +@@ -473,6 +599,18 @@ nfsd_open(struct svc_rqst *rqstp, struct filp->f_mode = FMODE_READ; } -+ intent_init(&it, IT_OPEN, (filp->f_flags & ~O_ACCMODE) | filp->f_mode); ++#ifndef O_OWNER_OVERRIDE ++#define O_OWNER_OVERRIDE 0200000000 ++#endif ++ intent_init(&it, IT_OPEN, (filp->f_flags & ~O_ACCMODE) | filp->f_mode | ++ O_OWNER_OVERRIDE); + + err = revalidate_it(dentry, &it); + if (err) + goto out_nfserr; -+ ++ + filp->f_it = ⁢ -+ ++ err = 0; if (filp->f_op && filp->f_op->open) { err = filp->f_op->open(inode, filp); -@@ -487,7 +621,11 @@ nfsd_open(struct svc_rqst *rqstp, struct - atomic_dec(&filp->f_count); +@@ -487,6 +621,9 @@ nfsd_open(struct svc_rqst *rqstp, struct } } -+ out_nfserr: + if (it.it_op_release) + intent_release(&it); @@ -472,33 +470,37 @@ err = nfserr_perm; if (!flen) -@@ -834,20 +972,44 @@ nfsd_create(struct svc_rqst *rqstp, stru +@@ -834,20 +972,47 @@ nfsd_create(struct svc_rqst *rqstp, stru dentry = fhp->fh_dentry; dirp = dentry->d_inode; + switch (type) { -+ case S_IFDIR: -+ if (dirp->i_op->mkdir_raw) -+ error = mkdir_raw(dentry, fname, flen, iap->ia_mode); -+ break; -+ case S_IFCHR: -+ case S_IFBLK: -+ case S_IFIFO: -+ case S_IFSOCK: -+ case S_IFREG: -+ if (dirp->i_op->mknod_raw) { -+ if (type == S_IFREG) -+ rdev = 0; -+ error = mknod_raw(dentry, fname, flen, iap->ia_mode, rdev); -+ } -+ break; -+ default: -+ printk("nfsd: bad file type %o in nfsd_create\n", type); ++ case S_IFDIR: ++ if (dirp->i_op->mkdir_raw) ++ error = mkdir_raw(dentry, fname, flen, iap->ia_mode); ++ break; ++ case S_IFCHR: ++ case S_IFBLK: ++ case S_IFIFO: ++ case S_IFSOCK: ++ case S_IFREG: ++ if (dirp->i_op->mknod_raw) { ++ if (type == S_IFREG) ++ rdev = 0; ++ error = mknod_raw(dentry, fname,flen,iap->ia_mode,rdev); ++ } ++ break; ++ default: ++ printk("nfsd: bad file type %o in nfsd_create\n", type); ++ } ++ if (error && error != -EOPNOTSUPP) { ++ err = error; ++ goto out_nfserr; + } + err = nfserr_notdir; - if(!dirp->i_op || !dirp->i_op->lookup) -+ if(!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it)) ++ if (!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it)) goto out; /* * Check whether the response file handle has been verified yet. @@ -509,8 +511,7 @@ - fh_lock(fhp); + if (!resfhp->fh_dentry || dirp->i_op->lookup_it) { + /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create -+ and nfsd_proc_create in case of lustre -+ */ ++ * and nfsd_proc_create in case of lustre */ + if (!resfhp->fh_dentry) + fh_lock(fhp); dchild = lookup_one_len(fname, dentry, flen); @@ -529,11 +530,11 @@ - dprintk("nfsd_create: dentry %s/%s not negative!\n", - dentry->d_name.name, dchild->d_name.name); - goto out; -+ if ( error == -EOPNOTSUPP) { ++ if (error == -EOPNOTSUPP) { + if (dchild->d_inode) { + dprintk("nfsd_create: dentry %s/%s not negative!\n", + dentry->d_name.name, dchild->d_name.name); -+ goto out; ++ goto out; + } } @@ -556,7 +557,7 @@ case S_IFIFO: case S_IFSOCK: - err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); -+ if (error == -EOPNOTSUPP) ++ if (error == -EOPNOTSUPP) + err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); break; default: @@ -569,10 +570,10 @@ + if (dirp->i_op->mknod_raw) { + err = mknod_raw(dentry, fname, flen, iap->ia_mode, 0); + if (err && err != -EOPNOTSUPP) -+ goto out; ++ goto out_nfserr; + } + -+ if(!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it)) ++ if (!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it)) goto out; fh_lock(fhp); @@ -580,7 +581,7 @@ case NFS3_CREATE_GUARDED: err = nfserr_exist; } -+ if(dirp->i_op->mknod_raw) ++ if (dirp->i_op->mknod_raw) + err = 0; goto out; } @@ -598,7 +599,7 @@ goto out; fh_lock(fhp); dentry = fhp->fh_dentry; -+ ++ + if (dentry->d_inode->i_op->symlink_raw) + error = symlink_raw(dentry, fname, flen, path); + @@ -643,7 +644,7 @@ } else #endif - err = vfs_rename(fdir, odentry, tdir, ndentry); -+ if(fdir->i_op->rename_raw) ++ if (fdir->i_op->rename_raw) + err = rename_raw(fdentry, tdentry, odentry, ndentry); + else + err = vfs_rename(fdir, odentry, tdir, ndentry); @@ -679,13 +680,12 @@ dput(rdentry); --- linux-2.4.20-hp4-pnnl13/include/linux/fs.h~nfs_export_kernel-2.4.20-hp 2003-09-14 17:34:24.000000000 +0400 +++ linux-2.4.20-hp4-pnnl13-alexey/include/linux/fs.h 2003-10-08 11:39:07.000000000 +0400 -@@ -93,6 +93,9 @@ extern int leases_enable, dir_notify_ena +@@ -93,6 +93,8 @@ extern int leases_enable, dir_notify_ena #define FS_SINGLE 8 /* Filesystem that can have only one superblock */ #define FS_NOMOUNT 16 /* Never mount from userland */ #define FS_LITTER 32 /* Keeps the tree in dcache */ -+#define FS_NFSEXP_FSID 64 /* Use file system specific fsid for -+ * exporting non device filesystems. -+ */ ++#define FS_NFSEXP_FSID 64 /* Use file system specific fsid for ++ * exporting non device filesystems. */ #define FS_ODD_RENAME 32768 /* Temporary stuff; will go away as soon * as nfs_rename() will be cleaned up */ @@ -695,7 +695,7 @@ int flags, struct lookup_intent *it); +extern int revalidate_it(struct dentry *dentry, struct lookup_intent *it); +extern int init_private_file_it(struct file *, struct dentry *dentry, int mode, -+ struct lookup_intent *it); ++ struct lookup_intent *it); extern int filp_close(struct file *, fl_owner_t id); extern char * getname(const char *); @@ -704,7 +704,7 @@ extern int follow_up(struct vfsmount **, struct dentry **); extern struct dentry * lookup_one_len(const char *, struct dentry *, int); +extern struct dentry * lookup_one_len_it(const char *, struct dentry *, int, -+ struct lookup_intent *); ++ struct lookup_intent *); extern struct dentry * lookup_hash(struct qstr *, struct dentry *); #define user_path_walk(name,nd) __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd) #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd) @@ -713,7 +713,7 @@ extern struct inode * iget4_locked(struct super_block *, unsigned long, find_inode_t, void *); +extern struct inode * ilookup4(struct super_block *, unsigned long, -+ find_inode_t, void *); ++ find_inode_t, void *); static inline struct inode *iget4(struct super_block *sb, unsigned long ino, find_inode_t find_actor, void *opaque) @@ -735,5 +735,3 @@ EXPORT_SYMBOL(lookup_hash); EXPORT_SYMBOL(sys_close); EXPORT_SYMBOL(dcache_lock); - -_ diff --git a/lustre/kernel_patches/patches/nfs_export_kernel-2.4.20-rh.patch b/lustre/kernel_patches/patches/nfs_export_kernel-2.4.20-rh.patch index 50988be..2f7f190 100644 --- a/lustre/kernel_patches/patches/nfs_export_kernel-2.4.20-rh.patch +++ b/lustre/kernel_patches/patches/nfs_export_kernel-2.4.20-rh.patch @@ -17,7 +17,7 @@ */ -int init_private_file(struct file *filp, struct dentry *dentry, int mode) +int init_private_file_it(struct file *filp, struct dentry *dentry, int mode, -+ struct lookup_intent *it) ++ struct lookup_intent *it) { memset(filp, 0, sizeof(*filp)); filp->f_mode = mode; @@ -50,8 +50,8 @@ -struct inode *iget4(struct super_block *sb, unsigned long ino, find_inode_t find_actor, void *opaque) +static inline struct inode *ifind(struct super_block *sb, unsigned long ino, -+ struct list_head *head, -+ find_inode_t find_actor, void *opaque) ++ struct list_head *head, ++ find_inode_t find_actor, void *opaque) { - struct list_head * head = inode_hashtable + hash(sb,ino); struct inode * inode; @@ -65,14 +65,14 @@ +} + +struct inode *ilookup4(struct super_block *sb, unsigned long ino, -+ find_inode_t find_actor, void *opaque) ++ find_inode_t find_actor, void *opaque) +{ + struct list_head * head = inode_hashtable + hash(sb,ino); + return ifind(sb, ino, head, find_actor, opaque); +} + +struct inode *iget4(struct super_block *sb, unsigned long ino, -+ find_inode_t find_actor, void *opaque) ++ find_inode_t find_actor, void *opaque) +{ + struct list_head * head = inode_hashtable + hash(sb,ino); + struct inode *inode = ifind(sb, ino, head, find_actor, opaque); @@ -118,7 +118,7 @@ /* SMP-safe */ -struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) +struct dentry * lookup_one_len_it(const char * name, struct dentry * base, -+ int len, struct lookup_intent *it) ++ int len, struct lookup_intent *it) { unsigned long hash; struct qstr this; @@ -148,25 +148,23 @@ ino = inode->i_ino; + if ((inode->i_sb->s_type->fs_flags & FS_NFSEXP_FSID) && + !(nxp->ex_flags & NFSEXP_FSID)) { -+ nxp->ex_dev = inode->i_sb->s_dev; -+ nxp->ex_flags |= NFSEXP_FSID; ++ nxp->ex_dev = inode->i_sb->s_dev; ++ nxp->ex_flags |= NFSEXP_FSID; + } err = -EINVAL; exp = exp_get(clp, dev, ino); --- linux-2.4.20-rh-20.9/fs/nfsd/nfsfh.c~nfs_export_kernel-2.4.20-rh 2003-09-13 19:34:15.000000000 +0400 +++ linux-2.4.20-rh-20.9-alexey/fs/nfsd/nfsfh.c 2003-10-08 10:48:38.000000000 +0400 -@@ -36,6 +36,15 @@ struct nfsd_getdents_callback { +@@ -36,6 +36,13 @@ struct nfsd_getdents_callback { int sequence; /* sequence counter */ }; +static struct dentry *lookup_it(struct inode *inode, struct dentry * dentry) +{ + if (inode->i_op->lookup_it) -+ return inode->i_op->lookup_it(inode, dentry, NULL, 0); -+ else -+ return inode->i_op->lookup(inode, dentry); -+ ++ return inode->i_op->lookup_it(inode, dentry, NULL, 0); ++ return inode->i_op->lookup(inode, dentry); +} + /* @@ -191,10 +189,10 @@ + if ((dentry->d_flags & DCACHE_NFSD_DISCONNECTED) && + (dentry->d_parent == dentry) ) { + it.it_op_release = NULL; -+ /* -+ * XXX Temporary Hack: Simulating init_private_file without -+ * f_op->open for disconnected dentry Since we don't have actual -+ * dentry->d_name to revalidate in revalidate_it() ++ /* ++ * XXX Temporary Hack: Simulate init_private_file without ++ * f_op->open for disconnected dentry as we don't have ++ * actual dentry->d_name to revalidate in revalidate_it() + */ + filp = &file; + memset(filp, 0, sizeof(*filp)); @@ -215,13 +213,13 @@ + } else { + error = init_private_file_it(&file, dentry, FMODE_READ, NULL); + } -+ if (error) ++ if (error) goto out; + error = -EINVAL; if (!file.f_op->readdir) goto out_close; -@@ -113,9 +152,13 @@ static int nfsd_get_name(struct dentry * +@@ -113,9 +152,12 @@ static int nfsd_get_name(struct dentry * } out_close: @@ -229,8 +227,7 @@ + if (file.f_op->release && !filp) file.f_op->release(dir, &file); out: -+ if (dentry->d_op && -+ dentry->d_op->d_revalidate_it && ++ if (dentry->d_op && dentry->d_op->d_revalidate_it && + it.it_op_release && !filp) + intent_release(&it); return error; @@ -263,14 +260,13 @@ pdentry = nfsd_findparent(dentry); err = PTR_ERR(pdentry); if (IS_ERR(pdentry)) -@@ -669,6 +716,11 @@ fh_verify(struct svc_rqst *rqstp, struct +@@ -669,6 +716,10 @@ fh_verify(struct svc_rqst *rqstp, struct inode = dentry->d_inode; + /* cache coherency for non-device filesystems */ -+ if (inode->i_op && inode->i_op->revalidate_it) { -+ inode->i_op->revalidate_it(dentry, NULL); -+ } ++ if (inode->i_op && inode->i_op->revalidate_it) ++ inode->i_op->revalidate_it(dentry, NULL); + /* Type check. The correct error return for type mismatches * does not seem to be generally agreed upon. SunOS seems to @@ -281,9 +277,9 @@ out_uptodate: - printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n", - dentry->d_parent->d_name.name, dentry->d_name.name); -+ if(!dentry->d_parent->d_inode->i_op->mkdir_raw) ++ if (!dentry->d_parent->d_inode->i_op->mkdir_raw) + printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n", -+ dentry->d_parent->d_name.name, dentry->d_name.name); ++ dentry->d_parent->d_name.name, dentry->d_name.name); goto out; } @@ -294,7 +290,7 @@ static struct raparms * raparm_cache; +static int link_raw(struct dentry *dold, struct dentry *ddir, -+ struct dentry *dnew) ++ struct dentry *dnew) +{ + int err; + @@ -303,17 +299,17 @@ + struct inode_operations *op = nd.dentry->d_inode->i_op; + err = op->link_raw(&old_nd, &nd); + d_instantiate(dnew, dold->d_inode); -+ if(dold->d_inode->i_op && dold->d_inode->i_op->revalidate_it) ++ if (dold->d_inode->i_op && dold->d_inode->i_op->revalidate_it) + dold->d_inode->i_op->revalidate_it(dnew, NULL); + + return err; +} + +static int unlink_raw(struct dentry *dentry, char *fname, int flen, -+ struct dentry *rdentry) ++ struct dentry *rdentry) +{ + int err; -+ struct qstr last = { .name = fname, .len = flen }; ++ struct qstr last = { .name = fname, .len = flen }; + struct nameidata nd = { .dentry = dentry, .last = last }; + struct inode_operations *op = nd.dentry->d_inode->i_op; + err = op->unlink_raw(&nd); @@ -324,14 +320,14 @@ +} + +static int rmdir_raw(struct dentry *dentry, char *fname, int flen, -+ struct dentry *rdentry) ++ struct dentry *rdentry) +{ + int err; -+ struct qstr last = { .name = fname, .len = flen }; ++ struct qstr last = { .name = fname, .len = flen }; + struct nameidata nd = { .dentry = dentry, .last = last }; + struct inode_operations *op = nd.dentry->d_inode->i_op; + err = op->rmdir_raw(&nd); -+ if(!err) { ++ if (!err) { + rdentry->d_inode->i_flags |= S_DEAD; + d_delete(rdentry); + } @@ -339,11 +335,11 @@ + return err; +} + -+static int symlink_raw(struct dentry *dentry, char *fname, int flen, -+ char *path) ++static int symlink_raw(struct dentry *dentry, char *fname, int flen, ++ char *path) +{ + int err; -+ struct qstr last = { .name = fname, .len = flen }; ++ struct qstr last = { .name = fname, .len = flen }; + struct nameidata nd = { .dentry = dentry, .last = last }; + struct inode_operations *op = nd.dentry->d_inode->i_op; + err = op->symlink_raw(&nd, path); @@ -354,7 +350,7 @@ +static int mkdir_raw(struct dentry *dentry, char *fname, int flen, int mode) +{ + int err; -+ struct qstr last = { .name = fname, .len = flen }; ++ struct qstr last = { .name = fname, .len = flen }; + struct nameidata nd = { .dentry = dentry, .last = last }; + struct inode_operations *op = nd.dentry->d_inode->i_op; + err = op->mkdir_raw(&nd, mode); @@ -363,19 +359,19 @@ +} + +static int mknod_raw(struct dentry *dentry, char *fname, int flen, int mode, -+ dev_t dev) ++ dev_t dev) +{ + int err; -+ struct qstr last = { .name = fname, .len = flen }; ++ struct qstr last = { .name = fname, .len = flen }; + struct nameidata nd = { .dentry = dentry, .last = last }; + struct inode_operations *op = nd.dentry->d_inode->i_op; + err = op->mknod_raw(&nd, mode, dev); + + return err; -+} ++} + +static int rename_raw(struct dentry *fdentry, struct dentry *tdentry, -+ struct dentry *odentry, struct dentry *ndentry) ++ struct dentry *odentry, struct dentry *ndentry) +{ + int err; + @@ -421,7 +417,7 @@ err = nfserr_notsync; if (!check_guard || guardtime == inode->i_ctime) { - err = notify_change(dentry, iap); -+ if ( dentry->d_inode->i_op && dentry->d_inode->i_op->setattr_raw) ++ if (dentry->d_inode->i_op && dentry->d_inode->i_op->setattr_raw) + err = setattr_raw(dentry->d_inode, iap); + else + err = notify_change(dentry, iap); @@ -436,26 +432,28 @@ int err; /* If we get here, then the client has already done an "open", and (hopefully) -@@ -475,6 +601,14 @@ nfsd_open(struct svc_rqst *rqstp, struct +@@ -475,6 +601,18 @@ nfsd_open(struct svc_rqst *rqstp, struct filp->f_mode = FMODE_READ; } -+ intent_init(&it, IT_OPEN, (filp->f_flags & ~O_ACCMODE) | filp->f_mode); ++#ifndef O_OWNER_OVERRIDE ++#define O_OWNER_OVERRIDE 0200000000 ++#endif ++ intent_init(&it, IT_OPEN, (filp->f_flags & ~O_ACCMODE) | filp->f_mode | ++ O_OWNER_OVERRIDE); + + err = revalidate_it(dentry, &it); + if (err) + goto out_nfserr; -+ ++ + filp->f_it = ⁢ -+ ++ err = 0; if (filp->f_op && filp->f_op->open) { err = filp->f_op->open(inode, filp); -@@ -489,7 +623,11 @@ nfsd_open(struct svc_rqst *rqstp, struct - atomic_dec(&filp->f_count); +@@ -489,6 +623,9 @@ nfsd_open(struct svc_rqst *rqstp, struct } } -+ out_nfserr: + if (it.it_op_release) + intent_release(&it); @@ -472,33 +470,37 @@ err = nfserr_perm; if (!flen) -@@ -836,20 +974,44 @@ nfsd_create(struct svc_rqst *rqstp, stru +@@ -836,20 +974,47 @@ nfsd_create(struct svc_rqst *rqstp, stru dentry = fhp->fh_dentry; dirp = dentry->d_inode; + switch (type) { -+ case S_IFDIR: -+ if (dirp->i_op->mkdir_raw) -+ error = mkdir_raw(dentry, fname, flen, iap->ia_mode); -+ break; -+ case S_IFCHR: -+ case S_IFBLK: -+ case S_IFIFO: -+ case S_IFSOCK: -+ case S_IFREG: -+ if (dirp->i_op->mknod_raw) { -+ if (type == S_IFREG) -+ rdev = 0; -+ error = mknod_raw(dentry, fname, flen, iap->ia_mode, rdev); -+ } -+ break; -+ default: -+ printk("nfsd: bad file type %o in nfsd_create\n", type); ++ case S_IFDIR: ++ if (dirp->i_op->mkdir_raw) ++ error = mkdir_raw(dentry, fname, flen, iap->ia_mode); ++ break; ++ case S_IFCHR: ++ case S_IFBLK: ++ case S_IFIFO: ++ case S_IFSOCK: ++ case S_IFREG: ++ if (dirp->i_op->mknod_raw) { ++ if (type == S_IFREG) ++ rdev = 0; ++ error = mknod_raw(dentry, fname,flen,iap->ia_mode,rdev); ++ } ++ break; ++ default: ++ printk("nfsd: bad file type %o in nfsd_create\n", type); ++ } ++ if (error && error != -EOPNOTSUPP) { ++ err = error; ++ goto out_nfserr; + } + err = nfserr_notdir; - if(!dirp->i_op || !dirp->i_op->lookup) -+ if(!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it)) ++ if (!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it)) goto out; /* * Check whether the response file handle has been verified yet. @@ -509,8 +511,7 @@ - fh_lock(fhp); + if (!resfhp->fh_dentry || dirp->i_op->lookup_it) { + /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create -+ and nfsd_proc_create in case of lustre -+ */ ++ * and nfsd_proc_create in case of lustre */ + if (!resfhp->fh_dentry) + fh_lock(fhp); dchild = lookup_one_len(fname, dentry, flen); @@ -529,11 +530,11 @@ - dprintk("nfsd_create: dentry %s/%s not negative!\n", - dentry->d_name.name, dchild->d_name.name); - goto out; -+ if ( error == -EOPNOTSUPP) { ++ if (error == -EOPNOTSUPP) { + if (dchild->d_inode) { + dprintk("nfsd_create: dentry %s/%s not negative!\n", + dentry->d_name.name, dchild->d_name.name); -+ goto out; ++ goto out; + } } @@ -556,7 +557,7 @@ case S_IFIFO: case S_IFSOCK: - err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); -+ if (error == -EOPNOTSUPP) ++ if (error == -EOPNOTSUPP) + err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); break; default: @@ -569,10 +570,10 @@ + if (dirp->i_op->mknod_raw) { + err = mknod_raw(dentry, fname, flen, iap->ia_mode, 0); + if (err && err != -EOPNOTSUPP) -+ goto out; ++ goto out_nfserr; + } + -+ if(!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it)) ++ if (!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it)) goto out; fh_lock(fhp); @@ -580,7 +581,7 @@ case NFS3_CREATE_GUARDED: err = nfserr_exist; } -+ if(dirp->i_op->mknod_raw) ++ if (dirp->i_op->mknod_raw) + err = 0; goto out; } @@ -598,7 +599,7 @@ goto out; fh_lock(fhp); dentry = fhp->fh_dentry; -+ ++ + if (dentry->d_inode->i_op->symlink_raw) + error = symlink_raw(dentry, fname, flen, path); + @@ -643,7 +644,7 @@ } else #endif - err = vfs_rename(fdir, odentry, tdir, ndentry); -+ if(fdir->i_op->rename_raw) ++ if (fdir->i_op->rename_raw) + err = rename_raw(fdentry, tdentry, odentry, ndentry); + else + err = vfs_rename(fdir, odentry, tdir, ndentry); @@ -679,13 +680,12 @@ dput(rdentry); --- linux-2.4.20-rh-20.9/include/linux/fs.h~nfs_export_kernel-2.4.20-rh 2003-09-14 17:35:22.000000000 +0400 +++ linux-2.4.20-rh-20.9-alexey/include/linux/fs.h 2003-10-08 10:48:38.000000000 +0400 -@@ -94,6 +94,9 @@ extern int leases_enable, dir_notify_ena +@@ -94,6 +94,8 @@ extern int leases_enable, dir_notify_ena #define FS_SINGLE 8 /* Filesystem that can have only one superblock */ #define FS_NOMOUNT 16 /* Never mount from userland */ #define FS_LITTER 32 /* Keeps the tree in dcache */ -+#define FS_NFSEXP_FSID 64 /* Use file system specific fsid for -+ * exporting non device filesystems. -+ */ ++#define FS_NFSEXP_FSID 64 /* Use file system specific fsid for ++ * exporting non device filesystems. */ #define FS_ODD_RENAME 32768 /* Temporary stuff; will go away as soon * as nfs_rename() will be cleaned up */ @@ -695,7 +695,7 @@ int flags, struct lookup_intent *it); +extern int revalidate_it(struct dentry *dentry, struct lookup_intent *it); +extern int init_private_file_it(struct file *, struct dentry *dentry, int mode, -+ struct lookup_intent *it); ++ struct lookup_intent *it); extern int filp_close(struct file *, fl_owner_t id); extern char * getname(const char *); @@ -704,7 +704,7 @@ extern int follow_up(struct vfsmount **, struct dentry **); extern struct dentry * lookup_one_len(const char *, struct dentry *, int); +extern struct dentry * lookup_one_len_it(const char *, struct dentry *, int, -+ struct lookup_intent *); ++ struct lookup_intent *); extern struct dentry * lookup_hash(struct qstr *, struct dentry *); #define user_path_walk(name,nd) __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd) #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd) @@ -713,7 +713,7 @@ typedef int (*find_inode_t)(struct inode *, unsigned long, void *); extern struct inode * iget4(struct super_block *, unsigned long, find_inode_t, void *); +extern struct inode * ilookup4(struct super_block *, unsigned long, -+ find_inode_t, void *); ++ find_inode_t, void *); static inline struct inode *iget(struct super_block *sb, unsigned long ino) { return iget4(sb, ino, NULL, NULL); diff --git a/lustre/kernel_patches/patches/nfs_export_kernel-2.4.20.patch b/lustre/kernel_patches/patches/nfs_export_kernel-2.4.20.patch index 0a0f958..ba6fa2b 100644 --- a/lustre/kernel_patches/patches/nfs_export_kernel-2.4.20.patch +++ b/lustre/kernel_patches/patches/nfs_export_kernel-2.4.20.patch @@ -20,7 +20,7 @@ diff -uprN linux/fs/file_table.c linux-2.4.20/fs/file_table.c */ -int init_private_file(struct file *filp, struct dentry *dentry, int mode) +int init_private_file_it(struct file *filp, struct dentry *dentry, int mode, -+ struct lookup_intent *it) ++ struct lookup_intent *it) { memset(filp, 0, sizeof(*filp)); filp->f_mode = mode; @@ -54,8 +54,8 @@ diff -uprN linux/fs/inode.c linux-2.4.20/fs/inode.c -struct inode *iget4(struct super_block *sb, unsigned long ino, find_inode_t find_actor, void *opaque) +static inline struct inode *ifind(struct super_block *sb, unsigned long ino, -+ struct list_head *head, -+ find_inode_t find_actor, void *opaque) ++ struct list_head *head, ++ find_inode_t find_actor, void *opaque) { - struct list_head * head = inode_hashtable + hash(sb,ino); struct inode * inode; @@ -69,14 +69,14 @@ diff -uprN linux/fs/inode.c linux-2.4.20/fs/inode.c +} + +struct inode *ilookup4(struct super_block *sb, unsigned long ino, -+ find_inode_t find_actor, void *opaque) ++ find_inode_t find_actor, void *opaque) +{ + struct list_head * head = inode_hashtable + hash(sb,ino); + return ifind(sb, ino, head, find_actor, opaque); +} + +struct inode *iget4(struct super_block *sb, unsigned long ino, -+ find_inode_t find_actor, void *opaque) ++ find_inode_t find_actor, void *opaque) +{ + struct list_head * head = inode_hashtable + hash(sb,ino); + struct inode *inode = ifind(sb, ino, head, find_actor, opaque); @@ -111,7 +111,7 @@ diff -uprN linux/fs/namei.c linux-2.4.20/fs/namei.c /* SMP-safe */ -struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) +struct dentry * lookup_one_len_it(const char * name, struct dentry * base, -+ int len, struct lookup_intent *it) ++ int len, struct lookup_intent *it) { unsigned long hash; struct qstr this; @@ -142,8 +142,8 @@ diff -uprN linux/fs/nfsd/export.c linux-2.4.20/fs/nfsd/export.c ino = inode->i_ino; + if ((inode->i_sb->s_type->fs_flags & FS_NFSEXP_FSID) && + !(nxp->ex_flags & NFSEXP_FSID)) { -+ nxp->ex_dev = inode->i_sb->s_dev; -+ nxp->ex_flags |= NFSEXP_FSID; ++ nxp->ex_dev = inode->i_sb->s_dev; ++ nxp->ex_flags |= NFSEXP_FSID; + } err = -EINVAL; @@ -151,17 +151,15 @@ diff -uprN linux/fs/nfsd/export.c linux-2.4.20/fs/nfsd/export.c diff -uprN linux/fs/nfsd/nfsfh.c linux-2.4.20/fs/nfsd/nfsfh.c --- linux/fs/nfsd/nfsfh.c Fri Nov 29 05:23:15 2002 +++ linux-2.4.20/fs/nfsd/nfsfh.c Sun Oct 5 21:47:45 2003 -@@ -36,6 +36,15 @@ struct nfsd_getdents_callback { +@@ -36,6 +36,13 @@ struct nfsd_getdents_callback { int sequence; /* sequence counter */ }; +static struct dentry *lookup_it(struct inode *inode, struct dentry * dentry) +{ + if (inode->i_op->lookup_it) -+ return inode->i_op->lookup_it(inode, dentry, NULL, 0); -+ else -+ return inode->i_op->lookup(inode, dentry); -+ ++ return inode->i_op->lookup_it(inode, dentry, NULL, 0); ++ return inode->i_op->lookup(inode, dentry); +} + /* @@ -186,10 +184,10 @@ diff -uprN linux/fs/nfsd/nfsfh.c linux-2.4.20/fs/nfsd/nfsfh.c + if ((dentry->d_flags & DCACHE_NFSD_DISCONNECTED) && + (dentry->d_parent == dentry) ) { + it.it_op_release = NULL; -+ /* -+ * XXX Temporary Hack: Simulating init_private_file without -+ * f_op->open for disconnected dentry Since we don't have actual -+ * dentry->d_name to revalidate in revalidate_it() ++ /* ++ * XXX Temporary Hack: Simulate init_private_file without ++ * f_op->open for disconnected dentry as we don't have ++ * actual dentry->d_name to revalidate in revalidate_it() + */ + filp = &file; + memset(filp, 0, sizeof(*filp)); @@ -210,13 +208,13 @@ diff -uprN linux/fs/nfsd/nfsfh.c linux-2.4.20/fs/nfsd/nfsfh.c + } else { + error = init_private_file_it(&file, dentry, FMODE_READ, NULL); + } -+ if (error) ++ if (error) goto out; + error = -EINVAL; if (!file.f_op->readdir) goto out_close; -@@ -113,9 +152,13 @@ static int nfsd_get_name(struct dentry * +@@ -113,9 +152,12 @@ static int nfsd_get_name(struct dentry * } out_close: @@ -224,8 +222,7 @@ diff -uprN linux/fs/nfsd/nfsfh.c linux-2.4.20/fs/nfsd/nfsfh.c + if (file.f_op->release && !filp) file.f_op->release(dir, &file); out: -+ if (dentry->d_op && -+ dentry->d_op->d_revalidate_it && ++ if (dentry->d_op && dentry->d_op->d_revalidate_it && + it.it_op_release && !filp) + intent_release(&it); return error; @@ -258,14 +255,13 @@ diff -uprN linux/fs/nfsd/nfsfh.c linux-2.4.20/fs/nfsd/nfsfh.c pdentry = nfsd_findparent(dentry); err = PTR_ERR(pdentry); if (IS_ERR(pdentry)) -@@ -662,6 +709,11 @@ fh_verify(struct svc_rqst *rqstp, struct +@@ -662,6 +709,10 @@ fh_verify(struct svc_rqst *rqstp, struct inode = dentry->d_inode; + /* cache coherency for non-device filesystems */ -+ if (inode->i_op && inode->i_op->revalidate_it) { -+ inode->i_op->revalidate_it(dentry, NULL); -+ } ++ if (inode->i_op && inode->i_op->revalidate_it) ++ inode->i_op->revalidate_it(dentry, NULL); + /* Type check. The correct error return for type mismatches * does not seem to be generally agreed upon. SunOS seems to @@ -276,9 +272,9 @@ diff -uprN linux/fs/nfsd/nfsfh.c linux-2.4.20/fs/nfsd/nfsfh.c out_uptodate: - printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n", - dentry->d_parent->d_name.name, dentry->d_name.name); -+ if(!dentry->d_parent->d_inode->i_op->mkdir_raw) ++ if (!dentry->d_parent->d_inode->i_op->mkdir_raw) + printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n", -+ dentry->d_parent->d_name.name, dentry->d_name.name); ++ dentry->d_parent->d_name.name, dentry->d_name.name); goto out; } @@ -290,7 +286,7 @@ diff -uprN linux/fs/nfsd/vfs.c linux-2.4.20/fs/nfsd/vfs.c static struct raparms * raparm_cache; +static int link_raw(struct dentry *dold, struct dentry *ddir, -+ struct dentry *dnew) ++ struct dentry *dnew) +{ + int err; + @@ -299,17 +295,17 @@ diff -uprN linux/fs/nfsd/vfs.c linux-2.4.20/fs/nfsd/vfs.c + struct inode_operations *op = nd.dentry->d_inode->i_op; + err = op->link_raw(&old_nd, &nd); + d_instantiate(dnew, dold->d_inode); -+ if(dold->d_inode->i_op && dold->d_inode->i_op->revalidate_it) ++ if (dold->d_inode->i_op && dold->d_inode->i_op->revalidate_it) + dold->d_inode->i_op->revalidate_it(dnew, NULL); + + return err; +} + +static int unlink_raw(struct dentry *dentry, char *fname, int flen, -+ struct dentry *rdentry) ++ struct dentry *rdentry) +{ + int err; -+ struct qstr last = { .name = fname, .len = flen }; ++ struct qstr last = { .name = fname, .len = flen }; + struct nameidata nd = { .dentry = dentry, .last = last }; + struct inode_operations *op = nd.dentry->d_inode->i_op; + err = op->unlink_raw(&nd); @@ -320,14 +316,14 @@ diff -uprN linux/fs/nfsd/vfs.c linux-2.4.20/fs/nfsd/vfs.c +} + +static int rmdir_raw(struct dentry *dentry, char *fname, int flen, -+ struct dentry *rdentry) ++ struct dentry *rdentry) +{ + int err; -+ struct qstr last = { .name = fname, .len = flen }; ++ struct qstr last = { .name = fname, .len = flen }; + struct nameidata nd = { .dentry = dentry, .last = last }; + struct inode_operations *op = nd.dentry->d_inode->i_op; + err = op->rmdir_raw(&nd); -+ if(!err) { ++ if (!err) { + rdentry->d_inode->i_flags |= S_DEAD; + d_delete(rdentry); + } @@ -335,11 +331,11 @@ diff -uprN linux/fs/nfsd/vfs.c linux-2.4.20/fs/nfsd/vfs.c + return err; +} + -+static int symlink_raw(struct dentry *dentry, char *fname, int flen, -+ char *path) ++static int symlink_raw(struct dentry *dentry, char *fname, int flen, ++ char *path) +{ + int err; -+ struct qstr last = { .name = fname, .len = flen }; ++ struct qstr last = { .name = fname, .len = flen }; + struct nameidata nd = { .dentry = dentry, .last = last }; + struct inode_operations *op = nd.dentry->d_inode->i_op; + err = op->symlink_raw(&nd, path); @@ -350,7 +346,7 @@ diff -uprN linux/fs/nfsd/vfs.c linux-2.4.20/fs/nfsd/vfs.c +static int mkdir_raw(struct dentry *dentry, char *fname, int flen, int mode) +{ + int err; -+ struct qstr last = { .name = fname, .len = flen }; ++ struct qstr last = { .name = fname, .len = flen }; + struct nameidata nd = { .dentry = dentry, .last = last }; + struct inode_operations *op = nd.dentry->d_inode->i_op; + err = op->mkdir_raw(&nd, mode); @@ -359,19 +355,19 @@ diff -uprN linux/fs/nfsd/vfs.c linux-2.4.20/fs/nfsd/vfs.c +} + +static int mknod_raw(struct dentry *dentry, char *fname, int flen, int mode, -+ dev_t dev) ++ dev_t dev) +{ + int err; -+ struct qstr last = { .name = fname, .len = flen }; ++ struct qstr last = { .name = fname, .len = flen }; + struct nameidata nd = { .dentry = dentry, .last = last }; + struct inode_operations *op = nd.dentry->d_inode->i_op; + err = op->mknod_raw(&nd, mode, dev); + + return err; -+} ++} + +static int rename_raw(struct dentry *fdentry, struct dentry *tdentry, -+ struct dentry *odentry, struct dentry *ndentry) ++ struct dentry *odentry, struct dentry *ndentry) +{ + int err; + @@ -417,7 +413,7 @@ diff -uprN linux/fs/nfsd/vfs.c linux-2.4.20/fs/nfsd/vfs.c err = nfserr_notsync; if (!check_guard || guardtime == inode->i_ctime) { - err = notify_change(dentry, iap); -+ if ( dentry->d_inode->i_op && dentry->d_inode->i_op->setattr_raw) ++ if (dentry->d_inode->i_op && dentry->d_inode->i_op->setattr_raw) + err = setattr_raw(dentry->d_inode, iap); + else + err = notify_change(dentry, iap); @@ -432,26 +428,28 @@ diff -uprN linux/fs/nfsd/vfs.c linux-2.4.20/fs/nfsd/vfs.c int err; /* If we get here, then the client has already done an "open", and (hopefully) -@@ -473,6 +599,14 @@ nfsd_open(struct svc_rqst *rqstp, struct +@@ -473,6 +599,18 @@ nfsd_open(struct svc_rqst *rqstp, struct filp->f_mode = FMODE_READ; } -+ intent_init(&it, IT_OPEN, (filp->f_flags & ~O_ACCMODE) | filp->f_mode); ++#ifndef O_OWNER_OVERRIDE ++#define O_OWNER_OVERRIDE 0200000000 ++#endif ++ intent_init(&it, IT_OPEN, (filp->f_flags & ~O_ACCMODE) | filp->f_mode | ++ O_OWNER_OVERRIDE); + + err = revalidate_it(dentry, &it); + if (err) + goto out_nfserr; -+ ++ + filp->f_it = ⁢ -+ ++ err = 0; if (filp->f_op && filp->f_op->open) { err = filp->f_op->open(inode, filp); -@@ -487,7 +621,11 @@ nfsd_open(struct svc_rqst *rqstp, struct - atomic_dec(&filp->f_count); +@@ -487,6 +621,9 @@ nfsd_open(struct svc_rqst *rqstp, struct } } -+ out_nfserr: + if (it.it_op_release) + intent_release(&it); @@ -468,33 +466,37 @@ diff -uprN linux/fs/nfsd/vfs.c linux-2.4.20/fs/nfsd/vfs.c err = nfserr_perm; if (!flen) -@@ -834,20 +972,44 @@ nfsd_create(struct svc_rqst *rqstp, stru +@@ -834,20 +972,47 @@ nfsd_create(struct svc_rqst *rqstp, stru dentry = fhp->fh_dentry; dirp = dentry->d_inode; + switch (type) { -+ case S_IFDIR: -+ if (dirp->i_op->mkdir_raw) -+ error = mkdir_raw(dentry, fname, flen, iap->ia_mode); -+ break; -+ case S_IFCHR: -+ case S_IFBLK: -+ case S_IFIFO: -+ case S_IFSOCK: -+ case S_IFREG: -+ if (dirp->i_op->mknod_raw) { -+ if (type == S_IFREG) -+ rdev = 0; -+ error = mknod_raw(dentry, fname, flen, iap->ia_mode, rdev); -+ } -+ break; -+ default: -+ printk("nfsd: bad file type %o in nfsd_create\n", type); ++ case S_IFDIR: ++ if (dirp->i_op->mkdir_raw) ++ error = mkdir_raw(dentry, fname, flen, iap->ia_mode); ++ break; ++ case S_IFCHR: ++ case S_IFBLK: ++ case S_IFIFO: ++ case S_IFSOCK: ++ case S_IFREG: ++ if (dirp->i_op->mknod_raw) { ++ if (type == S_IFREG) ++ rdev = 0; ++ error = mknod_raw(dentry, fname,flen,iap->ia_mode,rdev); ++ } ++ break; ++ default: ++ printk("nfsd: bad file type %o in nfsd_create\n", type); ++ } ++ if (error && error != -EOPNOTSUPP) { ++ err = error; ++ goto out_nfserr; + } + err = nfserr_notdir; - if(!dirp->i_op || !dirp->i_op->lookup) -+ if(!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it)) ++ if (!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it)) goto out; /* * Check whether the response file handle has been verified yet. @@ -505,8 +507,7 @@ diff -uprN linux/fs/nfsd/vfs.c linux-2.4.20/fs/nfsd/vfs.c - fh_lock(fhp); + if (!resfhp->fh_dentry || dirp->i_op->lookup_it) { + /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create -+ and nfsd_proc_create in case of lustre -+ */ ++ * and nfsd_proc_create in case of lustre */ + if (!resfhp->fh_dentry) + fh_lock(fhp); dchild = lookup_one_len(fname, dentry, flen); @@ -525,11 +526,11 @@ diff -uprN linux/fs/nfsd/vfs.c linux-2.4.20/fs/nfsd/vfs.c - dprintk("nfsd_create: dentry %s/%s not negative!\n", - dentry->d_name.name, dchild->d_name.name); - goto out; -+ if ( error == -EOPNOTSUPP) { ++ if (error == -EOPNOTSUPP) { + if (dchild->d_inode) { + dprintk("nfsd_create: dentry %s/%s not negative!\n", + dentry->d_name.name, dchild->d_name.name); -+ goto out; ++ goto out; + } } @@ -552,7 +553,7 @@ diff -uprN linux/fs/nfsd/vfs.c linux-2.4.20/fs/nfsd/vfs.c case S_IFIFO: case S_IFSOCK: - err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); -+ if (error == -EOPNOTSUPP) ++ if (error == -EOPNOTSUPP) + err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); break; default: @@ -565,10 +566,10 @@ diff -uprN linux/fs/nfsd/vfs.c linux-2.4.20/fs/nfsd/vfs.c + if (dirp->i_op->mknod_raw) { + err = mknod_raw(dentry, fname, flen, iap->ia_mode, 0); + if (err && err != -EOPNOTSUPP) -+ goto out; ++ goto out_nfserr; + } + -+ if(!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it)) ++ if (!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it)) goto out; fh_lock(fhp); @@ -576,7 +577,7 @@ diff -uprN linux/fs/nfsd/vfs.c linux-2.4.20/fs/nfsd/vfs.c case NFS3_CREATE_GUARDED: err = nfserr_exist; } -+ if(dirp->i_op->mknod_raw) ++ if (dirp->i_op->mknod_raw) + err = 0; goto out; } @@ -594,7 +595,7 @@ diff -uprN linux/fs/nfsd/vfs.c linux-2.4.20/fs/nfsd/vfs.c goto out; fh_lock(fhp); dentry = fhp->fh_dentry; -+ ++ + if (dentry->d_inode->i_op->symlink_raw) + error = symlink_raw(dentry, fname, flen, path); + @@ -639,7 +640,7 @@ diff -uprN linux/fs/nfsd/vfs.c linux-2.4.20/fs/nfsd/vfs.c } else #endif - err = vfs_rename(fdir, odentry, tdir, ndentry); -+ if(fdir->i_op->rename_raw) ++ if (fdir->i_op->rename_raw) + err = rename_raw(fdentry, tdentry, odentry, ndentry); + else + err = vfs_rename(fdir, odentry, tdir, ndentry); @@ -676,13 +677,12 @@ diff -uprN linux/fs/nfsd/vfs.c linux-2.4.20/fs/nfsd/vfs.c diff -uprN linux/include/linux/fs.h linux-2.4.20/include/linux/fs.h --- linux/include/linux/fs.h Sun Oct 5 21:52:56 2003 +++ linux-2.4.20/include/linux/fs.h Sun Oct 5 22:25:20 2003 -@@ -93,6 +93,9 @@ extern int leases_enable, dir_notify_ena +@@ -93,6 +93,8 @@ extern int leases_enable, dir_notify_ena #define FS_SINGLE 8 /* Filesystem that can have only one superblock */ #define FS_NOMOUNT 16 /* Never mount from userland */ #define FS_LITTER 32 /* Keeps the tree in dcache */ -+#define FS_NFSEXP_FSID 64 /* Use file system specific fsid for -+ * exporting non device filesystems. -+ */ ++#define FS_NFSEXP_FSID 64 /* Use file system specific fsid for ++ * exporting non device filesystems. */ #define FS_ODD_RENAME 32768 /* Temporary stuff; will go away as soon * as nfs_rename() will be cleaned up */ @@ -692,7 +692,7 @@ diff -uprN linux/include/linux/fs.h linux-2.4.20/include/linux/fs.h int flags, struct lookup_intent *it); +extern int revalidate_it(struct dentry *dentry, struct lookup_intent *it); +extern int init_private_file_it(struct file *, struct dentry *dentry, int mode, -+ struct lookup_intent *it); ++ struct lookup_intent *it); extern int filp_close(struct file *, fl_owner_t id); extern char * getname(const char *); @@ -701,7 +701,7 @@ diff -uprN linux/include/linux/fs.h linux-2.4.20/include/linux/fs.h extern int follow_up(struct vfsmount **, struct dentry **); extern struct dentry * lookup_one_len(const char *, struct dentry *, int); +extern struct dentry * lookup_one_len_it(const char *, struct dentry *, int, -+ struct lookup_intent *); ++ struct lookup_intent *); extern struct dentry * lookup_hash(struct qstr *, struct dentry *); #define user_path_walk(name,nd) __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd) #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd) @@ -710,7 +710,7 @@ diff -uprN linux/include/linux/fs.h linux-2.4.20/include/linux/fs.h typedef int (*find_inode_t)(struct inode *, unsigned long, void *); extern struct inode * iget4(struct super_block *, unsigned long, find_inode_t, void *); +extern struct inode * ilookup4(struct super_block *, unsigned long, -+ find_inode_t, void *); ++ find_inode_t, void *); static inline struct inode *iget(struct super_block *sb, unsigned long ino) { return iget4(sb, ino, NULL, NULL); diff --git a/lustre/kernel_patches/patches/nfs_export_kernel-2.4.21-chaos.patch b/lustre/kernel_patches/patches/nfs_export_kernel-2.4.21-chaos.patch index 52529e2..70c2e99 100644 --- a/lustre/kernel_patches/patches/nfs_export_kernel-2.4.21-chaos.patch +++ b/lustre/kernel_patches/patches/nfs_export_kernel-2.4.21-chaos.patch @@ -13,17 +13,17 @@ Index: linux-2.4.21-chaos/fs/file_table.c =================================================================== --- linux-2.4.21-chaos.orig/fs/file_table.c 2003-07-15 04:41:00.000000000 +0400 +++ linux-2.4.21-chaos/fs/file_table.c 2003-12-12 16:19:25.000000000 +0300 -@@ -82,7 +82,8 @@ +@@ -82,7 +82,8 @@ struct file * get_empty_filp(void) * and call the open function (if any). The caller must verify that * inode->i_fop is not NULL. */ -int init_private_file(struct file *filp, struct dentry *dentry, int mode) +int init_private_file_it(struct file *filp, struct dentry *dentry, int mode, -+ struct lookup_intent *it) ++ struct lookup_intent *it) { memset(filp, 0, sizeof(*filp)); filp->f_mode = mode; -@@ -90,12 +91,20 @@ +@@ -90,12 +91,20 @@ int init_private_file(struct file *filp, filp->f_dentry = dentry; filp->f_uid = current->fsuid; filp->f_gid = current->fsgid; @@ -48,20 +48,20 @@ Index: linux-2.4.21-chaos/fs/inode.c =================================================================== --- linux-2.4.21-chaos.orig/fs/inode.c 2003-12-12 16:18:15.000000000 +0300 +++ linux-2.4.21-chaos/fs/inode.c 2003-12-12 16:19:25.000000000 +0300 -@@ -1054,9 +1054,10 @@ +@@ -1054,9 +1054,10 @@ struct inode *igrab(struct inode *inode) return inode; } -struct inode *iget4_locked(struct super_block *sb, unsigned long ino, find_inode_t find_actor, void *opaque) +struct inode *ifind(struct super_block *sb, unsigned long ino, -+ struct list_head *head, -+ find_inode_t find_actor, void *opaque) ++ struct list_head *head, ++ find_inode_t find_actor, void *opaque) { - struct list_head * head = inode_hashtable + hash(sb,ino); struct inode * inode; spin_lock(&inode_lock); -@@ -1069,6 +1070,24 @@ +@@ -1069,6 +1070,24 @@ struct inode *iget4_locked(struct super_ } spin_unlock(&inode_lock); @@ -69,14 +69,14 @@ Index: linux-2.4.21-chaos/fs/inode.c +} + +struct inode *ilookup4(struct super_block *sb, unsigned long ino, -+ find_inode_t find_actor, void *opaque) ++ find_inode_t find_actor, void *opaque) +{ + struct list_head * head = inode_hashtable + hash(sb,ino); + return ifind(sb, ino, head, find_actor, opaque); +} + +struct inode *iget4_locked(struct super_block *sb, unsigned long ino, -+ find_inode_t find_actor, void *opaque) ++ find_inode_t find_actor, void *opaque) +{ + struct list_head * head = inode_hashtable + hash(sb,ino); + struct inode *inode = ifind(sb, ino, head, find_actor, opaque); @@ -112,7 +112,7 @@ Index: linux-2.4.21-chaos/fs/namei.c #include #include -@@ -100,6 +101,7 @@ +@@ -100,6 +101,7 @@ void intent_release(struct lookup_intent it->it_op_release(it); } @@ -120,17 +120,17 @@ Index: linux-2.4.21-chaos/fs/namei.c /* In order to reduce some races, while at the same time doing additional * checking and hopefully speeding things up, we copy filenames to the -@@ -910,7 +912,8 @@ +@@ -910,7 +912,8 @@ struct dentry * lookup_hash(struct qstr /* SMP-safe */ -struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) +struct dentry * lookup_one_len_it(const char * name, struct dentry * base, -+ int len, struct lookup_intent *it) ++ int len, struct lookup_intent *it) { unsigned long hash; struct qstr this; -@@ -930,11 +933,16 @@ +@@ -930,11 +933,16 @@ struct dentry * lookup_one_len(const cha } this.hash = end_name_hash(hash); @@ -152,14 +152,14 @@ Index: linux-2.4.21-chaos/fs/nfsd/export.c =================================================================== --- linux-2.4.21-chaos.orig/fs/nfsd/export.c 2003-09-19 03:49:54.000000000 +0400 +++ linux-2.4.21-chaos/fs/nfsd/export.c 2003-12-12 16:19:25.000000000 +0300 -@@ -223,6 +223,11 @@ +@@ -223,6 +223,11 @@ exp_export(struct nfsctl_export *nxp) inode = nd.dentry->d_inode; dev = inode->i_dev; ino = inode->i_ino; + if ((inode->i_sb->s_type->fs_flags & FS_NFSEXP_FSID) && + !(nxp->ex_flags & NFSEXP_FSID)) { -+ nxp->ex_dev = inode->i_sb->s_dev; -+ nxp->ex_flags |= NFSEXP_FSID; ++ nxp->ex_dev = inode->i_sb->s_dev; ++ nxp->ex_flags |= NFSEXP_FSID; + } err = -EINVAL; @@ -168,23 +168,21 @@ Index: linux-2.4.21-chaos/fs/nfsd/nfsfh.c =================================================================== --- linux-2.4.21-chaos.orig/fs/nfsd/nfsfh.c 2003-09-19 03:49:54.000000000 +0400 +++ linux-2.4.21-chaos/fs/nfsd/nfsfh.c 2003-12-12 16:19:25.000000000 +0300 -@@ -36,6 +36,15 @@ +@@ -36,6 +36,13 @@ struct nfsd_getdents_callback { int sequence; /* sequence counter */ }; +static struct dentry *lookup_it(struct inode *inode, struct dentry * dentry) +{ + if (inode->i_op->lookup_it) -+ return inode->i_op->lookup_it(inode, dentry, NULL, 0); -+ else -+ return inode->i_op->lookup(inode, dentry); -+ ++ return inode->i_op->lookup_it(inode, dentry, NULL, 0); ++ return inode->i_op->lookup(inode, dentry); +} + /* * A rather strange filldir function to capture * the name matching the specified inode number. -@@ -75,6 +84,8 @@ +@@ -75,6 +84,8 @@ static int nfsd_get_name(struct dentry * int error; struct file file; struct nfsd_getdents_callback buffer; @@ -193,7 +191,7 @@ Index: linux-2.4.21-chaos/fs/nfsd/nfsfh.c error = -ENOTDIR; if (!dir || !S_ISDIR(dir->i_mode)) -@@ -85,9 +96,37 @@ +@@ -85,9 +96,37 @@ static int nfsd_get_name(struct dentry * /* * Open the directory ... */ @@ -203,10 +201,10 @@ Index: linux-2.4.21-chaos/fs/nfsd/nfsfh.c + if ((dentry->d_flags & DCACHE_NFSD_DISCONNECTED) && + (dentry->d_parent == dentry) ) { + it.it_op_release = NULL; -+ /* -+ * XXX Temporary Hack: Simulating init_private_file without -+ * f_op->open for disconnected dentry Since we don't have actual -+ * dentry->d_name to revalidate in revalidate_it() ++ /* ++ * XXX Temporary Hack: Simulate init_private_file without ++ * f_op->open for disconnected dentry as we don't have ++ * actual dentry->d_name to revalidate in revalidate_it() + */ + filp = &file; + memset(filp, 0, sizeof(*filp)); @@ -227,13 +225,13 @@ Index: linux-2.4.21-chaos/fs/nfsd/nfsfh.c + } else { + error = init_private_file_it(&file, dentry, FMODE_READ, NULL); + } -+ if (error) ++ if (error) goto out; + error = -EINVAL; if (!file.f_op->readdir) goto out_close; -@@ -113,9 +152,13 @@ +@@ -113,9 +152,12 @@ static int nfsd_get_name(struct dentry * } out_close: @@ -241,14 +239,13 @@ Index: linux-2.4.21-chaos/fs/nfsd/nfsfh.c + if (file.f_op->release && !filp) file.f_op->release(dir, &file); out: -+ if (dentry->d_op && -+ dentry->d_op->d_revalidate_it && ++ if (dentry->d_op && dentry->d_op->d_revalidate_it && + it.it_op_release && !filp) + intent_release(&it); return error; } -@@ -274,7 +317,7 @@ +@@ -274,7 +317,7 @@ struct dentry *nfsd_findparent(struct de * it is well connected. But nobody returns different dentrys do they? */ down(&child->d_inode->i_sem); @@ -257,7 +254,7 @@ Index: linux-2.4.21-chaos/fs/nfsd/nfsfh.c up(&child->d_inode->i_sem); d_drop(tdentry); /* we never want ".." hashed */ if (!pdentry && tdentry->d_inode == NULL) { -@@ -307,6 +350,8 @@ +@@ -306,6 +350,8 @@ struct dentry *nfsd_findparent(struct de pdentry->d_flags |= DCACHE_NFSD_DISCONNECTED; pdentry->d_op = child->d_op; } @@ -266,7 +263,7 @@ Index: linux-2.4.21-chaos/fs/nfsd/nfsfh.c } if (pdentry == NULL) pdentry = ERR_PTR(-ENOMEM); -@@ -464,6 +509,8 @@ +@@ -464,6 +509,8 @@ find_fh_dentry(struct super_block *sb, _ struct dentry *pdentry; struct inode *parent; @@ -275,27 +272,26 @@ Index: linux-2.4.21-chaos/fs/nfsd/nfsfh.c pdentry = nfsd_findparent(dentry); err = PTR_ERR(pdentry); if (IS_ERR(pdentry)) -@@ -672,6 +719,11 @@ +@@ -672,6 +719,10 @@ fh_verify(struct svc_rqst *rqstp, struct inode = dentry->d_inode; + /* cache coherency for non-device filesystems */ -+ if (inode->i_op && inode->i_op->revalidate_it) { -+ inode->i_op->revalidate_it(dentry, NULL); -+ } ++ if (inode->i_op && inode->i_op->revalidate_it) ++ inode->i_op->revalidate_it(dentry, NULL); + /* Type check. The correct error return for type mismatches * does not seem to be generally agreed upon. SunOS seems to * use EISDIR if file isn't S_IFREG; a comment in the NFSv3 -@@ -905,8 +957,9 @@ +@@ -905,8 +957,9 @@ out_negative: dentry->d_parent->d_name.name, dentry->d_name.name); goto out; out_uptodate: - printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n", - dentry->d_parent->d_name.name, dentry->d_name.name); -+ if(!dentry->d_parent->d_inode->i_op->mkdir_raw) ++ if (!dentry->d_parent->d_inode->i_op->mkdir_raw) + printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n", -+ dentry->d_parent->d_name.name, dentry->d_name.name); ++ dentry->d_parent->d_name.name, dentry->d_name.name); goto out; } @@ -308,7 +304,7 @@ Index: linux-2.4.21-chaos/fs/nfsd/vfs.c static struct raparms * raparm_cache; +static int link_raw(struct dentry *dold, struct dentry *ddir, -+ struct dentry *dnew) ++ struct dentry *dnew) +{ + int err; + @@ -317,17 +313,17 @@ Index: linux-2.4.21-chaos/fs/nfsd/vfs.c + struct inode_operations *op = nd.dentry->d_inode->i_op; + err = op->link_raw(&old_nd, &nd); + d_instantiate(dnew, dold->d_inode); -+ if(dold->d_inode->i_op && dold->d_inode->i_op->revalidate_it) ++ if (dold->d_inode->i_op && dold->d_inode->i_op->revalidate_it) + dold->d_inode->i_op->revalidate_it(dnew, NULL); + + return err; +} + +static int unlink_raw(struct dentry *dentry, char *fname, int flen, -+ struct dentry *rdentry) ++ struct dentry *rdentry) +{ + int err; -+ struct qstr last = { .name = fname, .len = flen }; ++ struct qstr last = { .name = fname, .len = flen }; + struct nameidata nd = { .dentry = dentry, .last = last }; + struct inode_operations *op = nd.dentry->d_inode->i_op; + err = op->unlink_raw(&nd); @@ -338,14 +334,14 @@ Index: linux-2.4.21-chaos/fs/nfsd/vfs.c +} + +static int rmdir_raw(struct dentry *dentry, char *fname, int flen, -+ struct dentry *rdentry) ++ struct dentry *rdentry) +{ + int err; -+ struct qstr last = { .name = fname, .len = flen }; ++ struct qstr last = { .name = fname, .len = flen }; + struct nameidata nd = { .dentry = dentry, .last = last }; + struct inode_operations *op = nd.dentry->d_inode->i_op; + err = op->rmdir_raw(&nd); -+ if(!err) { ++ if (!err) { + rdentry->d_inode->i_flags |= S_DEAD; + d_delete(rdentry); + } @@ -353,11 +349,11 @@ Index: linux-2.4.21-chaos/fs/nfsd/vfs.c + return err; +} + -+static int symlink_raw(struct dentry *dentry, char *fname, int flen, -+ char *path) ++static int symlink_raw(struct dentry *dentry, char *fname, int flen, ++ char *path) +{ + int err; -+ struct qstr last = { .name = fname, .len = flen }; ++ struct qstr last = { .name = fname, .len = flen }; + struct nameidata nd = { .dentry = dentry, .last = last }; + struct inode_operations *op = nd.dentry->d_inode->i_op; + err = op->symlink_raw(&nd, path); @@ -368,7 +364,7 @@ Index: linux-2.4.21-chaos/fs/nfsd/vfs.c +static int mkdir_raw(struct dentry *dentry, char *fname, int flen, int mode) +{ + int err; -+ struct qstr last = { .name = fname, .len = flen }; ++ struct qstr last = { .name = fname, .len = flen }; + struct nameidata nd = { .dentry = dentry, .last = last }; + struct inode_operations *op = nd.dentry->d_inode->i_op; + err = op->mkdir_raw(&nd, mode); @@ -377,19 +373,19 @@ Index: linux-2.4.21-chaos/fs/nfsd/vfs.c +} + +static int mknod_raw(struct dentry *dentry, char *fname, int flen, int mode, -+ dev_t dev) ++ dev_t dev) +{ + int err; -+ struct qstr last = { .name = fname, .len = flen }; ++ struct qstr last = { .name = fname, .len = flen }; + struct nameidata nd = { .dentry = dentry, .last = last }; + struct inode_operations *op = nd.dentry->d_inode->i_op; + err = op->mknod_raw(&nd, mode, dev); + + return err; -+} ++} + +static int rename_raw(struct dentry *fdentry, struct dentry *tdentry, -+ struct dentry *odentry, struct dentry *ndentry) ++ struct dentry *odentry, struct dentry *ndentry) +{ + int err; + @@ -430,19 +426,19 @@ Index: linux-2.4.21-chaos/fs/nfsd/vfs.c /* * Look up one component of a pathname. * N.B. After this call _both_ fhp and resfh need an fh_put -@@ -303,7 +425,10 @@ +@@ -303,7 +425,10 @@ nfsd_setattr(struct svc_rqst *rqstp, str } err = nfserr_notsync; if (!check_guard || guardtime == inode->i_ctime) { - err = notify_change(dentry, iap); -+ if ( dentry->d_inode->i_op && dentry->d_inode->i_op->setattr_raw) ++ if (dentry->d_inode->i_op && dentry->d_inode->i_op->setattr_raw) + err = setattr_raw(dentry->d_inode, iap); + else + err = notify_change(dentry, iap); err = nfserrno(err); } if (size_change) { -@@ -430,6 +555,7 @@ +@@ -430,6 +555,7 @@ nfsd_open(struct svc_rqst *rqstp, struct { struct dentry *dentry; struct inode *inode; @@ -450,26 +446,28 @@ Index: linux-2.4.21-chaos/fs/nfsd/vfs.c int err; /* If we get here, then the client has already done an "open", and (hopefully) -@@ -476,6 +602,14 @@ +@@ -476,6 +602,18 @@ nfsd_open(struct svc_rqst *rqstp, struct filp->f_mode = FMODE_READ; } -+ intent_init(&it, IT_OPEN, (filp->f_flags & ~O_ACCMODE) | filp->f_mode); ++#ifndef O_OWNER_OVERRIDE ++#define O_OWNER_OVERRIDE 0200000000 ++#endif ++ intent_init(&it, IT_OPEN, (filp->f_flags & ~O_ACCMODE) | filp->f_mode | ++ O_OWNER_OVERRIDE); + + err = revalidate_it(dentry, &it); + if (err) + goto out_nfserr; -+ ++ + filp->f_it = ⁢ -+ ++ err = 0; if (filp->f_op && filp->f_op->open) { err = filp->f_op->open(inode, filp); -@@ -490,7 +624,11 @@ - atomic_dec(&filp->f_count); +@@ -490,6 +624,9 @@ nfsd_open(struct svc_rqst *rqstp, struct } } -+ out_nfserr: + if (it.it_op_release) + intent_release(&it); @@ -477,7 +475,7 @@ Index: linux-2.4.21-chaos/fs/nfsd/vfs.c if (err) err = nfserrno(err); out: -@@ -821,7 +959,7 @@ +@@ -821,7 +959,7 @@ nfsd_create(struct svc_rqst *rqstp, stru { struct dentry *dentry, *dchild; struct inode *dirp; @@ -486,33 +484,37 @@ Index: linux-2.4.21-chaos/fs/nfsd/vfs.c err = nfserr_perm; if (!flen) -@@ -837,20 +975,44 @@ +@@ -837,20 +975,47 @@ nfsd_create(struct svc_rqst *rqstp, stru dentry = fhp->fh_dentry; dirp = dentry->d_inode; + switch (type) { -+ case S_IFDIR: -+ if (dirp->i_op->mkdir_raw) -+ error = mkdir_raw(dentry, fname, flen, iap->ia_mode); -+ break; -+ case S_IFCHR: -+ case S_IFBLK: -+ case S_IFIFO: -+ case S_IFSOCK: -+ case S_IFREG: -+ if (dirp->i_op->mknod_raw) { -+ if (type == S_IFREG) -+ rdev = 0; -+ error = mknod_raw(dentry, fname, flen, iap->ia_mode, rdev); -+ } -+ break; -+ default: -+ printk("nfsd: bad file type %o in nfsd_create\n", type); ++ case S_IFDIR: ++ if (dirp->i_op->mkdir_raw) ++ error = mkdir_raw(dentry, fname, flen, iap->ia_mode); ++ break; ++ case S_IFCHR: ++ case S_IFBLK: ++ case S_IFIFO: ++ case S_IFSOCK: ++ case S_IFREG: ++ if (dirp->i_op->mknod_raw) { ++ if (type == S_IFREG) ++ rdev = 0; ++ error = mknod_raw(dentry, fname,flen,iap->ia_mode,rdev); ++ } ++ break; ++ default: ++ printk("nfsd: bad file type %o in nfsd_create\n", type); ++ } ++ if (error && error != -EOPNOTSUPP) { ++ err = error; ++ goto out_nfserr; + } + err = nfserr_notdir; - if(!dirp->i_op || !dirp->i_op->lookup) -+ if(!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it)) ++ if (!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it)) goto out; /* * Check whether the response file handle has been verified yet. @@ -523,8 +525,7 @@ Index: linux-2.4.21-chaos/fs/nfsd/vfs.c - fh_lock(fhp); + if (!resfhp->fh_dentry || dirp->i_op->lookup_it) { + /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create -+ and nfsd_proc_create in case of lustre -+ */ ++ * and nfsd_proc_create in case of lustre */ + if (!resfhp->fh_dentry) + fh_lock(fhp); dchild = lookup_one_len(fname, dentry, flen); @@ -535,7 +536,7 @@ Index: linux-2.4.21-chaos/fs/nfsd/vfs.c err = fh_compose(resfhp, fhp->fh_export, dchild, fhp); if (err) goto out; -@@ -871,10 +1033,12 @@ +@@ -871,10 +1033,12 @@ nfsd_create(struct svc_rqst *rqstp, stru * Make sure the child dentry is still negative ... */ err = nfserr_exist; @@ -543,16 +544,16 @@ Index: linux-2.4.21-chaos/fs/nfsd/vfs.c - dprintk("nfsd_create: dentry %s/%s not negative!\n", - dentry->d_name.name, dchild->d_name.name); - goto out; -+ if ( error == -EOPNOTSUPP) { ++ if (error == -EOPNOTSUPP) { + if (dchild->d_inode) { + dprintk("nfsd_create: dentry %s/%s not negative!\n", + dentry->d_name.name, dchild->d_name.name); -+ goto out; ++ goto out; + } } if (!(iap->ia_valid & ATTR_MODE)) -@@ -887,16 +1051,19 @@ +@@ -887,16 +1051,19 @@ nfsd_create(struct svc_rqst *rqstp, stru err = nfserr_perm; switch (type) { case S_IFREG: @@ -570,12 +571,12 @@ Index: linux-2.4.21-chaos/fs/nfsd/vfs.c case S_IFIFO: case S_IFSOCK: - err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); -+ if (error == -EOPNOTSUPP) ++ if (error == -EOPNOTSUPP) + err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); break; default: printk("nfsd: bad file type %o in nfsd_create\n", type); -@@ -965,7 +1132,13 @@ +@@ -965,7 +1132,13 @@ nfsd_create_v3(struct svc_rqst *rqstp, s /* Get all the sanity checks out of the way before * we lock the parent. */ err = nfserr_notdir; @@ -583,23 +584,23 @@ Index: linux-2.4.21-chaos/fs/nfsd/vfs.c + if (dirp->i_op->mknod_raw) { + err = mknod_raw(dentry, fname, flen, iap->ia_mode, 0); + if (err && err != -EOPNOTSUPP) -+ goto out; ++ goto out_nfserr; + } + -+ if(!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it)) ++ if (!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it)) goto out; fh_lock(fhp); -@@ -1016,6 +1189,8 @@ +@@ -1016,6 +1189,8 @@ nfsd_create_v3(struct svc_rqst *rqstp, s case NFS3_CREATE_GUARDED: err = nfserr_exist; } -+ if(dirp->i_op->mknod_raw) ++ if (dirp->i_op->mknod_raw) + err = 0; goto out; } -@@ -1122,7 +1297,7 @@ +@@ -1122,7 +1297,7 @@ nfsd_symlink(struct svc_rqst *rqstp, str struct iattr *iap) { struct dentry *dentry, *dnew; @@ -608,11 +609,11 @@ Index: linux-2.4.21-chaos/fs/nfsd/vfs.c err = nfserr_noent; if (!flen || !plen) -@@ -1136,12 +1311,18 @@ +@@ -1136,12 +1311,18 @@ nfsd_symlink(struct svc_rqst *rqstp, str goto out; fh_lock(fhp); dentry = fhp->fh_dentry; -+ ++ + if (dentry->d_inode->i_op->symlink_raw) + error = symlink_raw(dentry, fname, flen, path); + @@ -640,7 +641,7 @@ Index: linux-2.4.21-chaos/fs/nfsd/vfs.c if (err) err = nfserrno(err); else if (EX_ISSYNC(fhp->fh_export)) -@@ -1211,7 +1392,10 @@ +@@ -1211,7 +1392,10 @@ nfsd_link(struct svc_rqst *rqstp, struct dold = tfhp->fh_dentry; dest = dold->d_inode; @@ -652,19 +653,19 @@ Index: linux-2.4.21-chaos/fs/nfsd/vfs.c if (!err) { if (EX_ISSYNC(ffhp->fh_export)) { nfsd_sync_dir(ddir); -@@ -1296,7 +1480,10 @@ +@@ -1296,7 +1480,10 @@ nfsd_rename(struct svc_rqst *rqstp, stru err = nfserr_perm; } else #endif - err = vfs_rename(fdir, odentry, tdir, ndentry); -+ if(fdir->i_op->rename_raw) ++ if (fdir->i_op->rename_raw) + err = rename_raw(fdentry, tdentry, odentry, ndentry); + else + err = vfs_rename(fdir, odentry, tdir, ndentry); if (!err && EX_ISSYNC(tfhp->fh_export)) { nfsd_sync_dir(tdentry); nfsd_sync_dir(fdentry); -@@ -1317,7 +1504,7 @@ +@@ -1317,7 +1504,7 @@ nfsd_rename(struct svc_rqst *rqstp, stru fill_post_wcc(tfhp); double_up(&tdir->i_sem, &fdir->i_sem); ffhp->fh_locked = tfhp->fh_locked = 0; @@ -673,7 +674,7 @@ Index: linux-2.4.21-chaos/fs/nfsd/vfs.c out: return err; } -@@ -1363,9 +1550,15 @@ +@@ -1363,9 +1550,15 @@ nfsd_unlink(struct svc_rqst *rqstp, stru err = nfserr_perm; } else #endif @@ -695,50 +696,48 @@ Index: linux-2.4.21-chaos/include/linux/fs.h =================================================================== --- linux-2.4.21-chaos.orig/include/linux/fs.h 2003-12-12 16:19:23.000000000 +0300 +++ linux-2.4.21-chaos/include/linux/fs.h 2003-12-12 16:19:25.000000000 +0300 -@@ -93,6 +93,9 @@ +@@ -93,6 +93,8 @@ #define FS_SINGLE 8 /* Filesystem that can have only one superblock */ #define FS_NOMOUNT 16 /* Never mount from userland */ #define FS_LITTER 32 /* Keeps the tree in dcache */ -+#define FS_NFSEXP_FSID 64 /* Use file system specific fsid for -+ * exporting non device filesystems. -+ */ ++#define FS_NFSEXP_FSID 64 /* Use file system specific fsid for ++ * exporting non device filesystems. */ #define FS_ODD_RENAME 32768 /* Temporary stuff; will go away as soon * as nfs_rename() will be cleaned up */ -@@ -1159,6 +1162,9 @@ +@@ -1159,6 +1162,9 @@ extern int open_namei_it(const char *fil struct nameidata *nd, struct lookup_intent *it); extern struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt, int flags, struct lookup_intent *it); +extern int revalidate_it(struct dentry *dentry, struct lookup_intent *it); +extern int init_private_file_it(struct file *, struct dentry *dentry, int mode, -+ struct lookup_intent *it); ++ struct lookup_intent *it); extern int filp_close(struct file *, fl_owner_t id); extern char * getname(const char *); -@@ -1458,6 +1464,8 @@ +@@ -1458,6 +1464,8 @@ extern void path_release(struct nameidat extern int follow_down(struct vfsmount **, struct dentry **); extern int follow_up(struct vfsmount **, struct dentry **); extern struct dentry * lookup_one_len(const char *, struct dentry *, int); +extern struct dentry * lookup_one_len_it(const char *, struct dentry *, int, -+ struct lookup_intent *); ++ struct lookup_intent *); extern struct dentry * lookup_hash(struct qstr *, struct dentry *); #define user_path_walk(name,nd) __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd) #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd) -@@ -1477,7 +1485,8 @@ +@@ -1477,6 +1485,8 @@ typedef int (*find_inode_t)(struct inode extern struct inode * iget4_locked(struct super_block *, unsigned long, find_inode_t, void *); -- +extern struct inode * ilookup4(struct super_block *, unsigned long, -+ find_inode_t, void *); ++ find_inode_t, void *); + static inline struct inode *iget4(struct super_block *sb, unsigned long ino, find_inode_t find_actor, void *opaque) - { Index: linux-2.4.21-chaos/kernel/ksyms.c =================================================================== --- linux-2.4.21-chaos.orig/kernel/ksyms.c 2003-12-12 16:18:36.000000000 +0300 +++ linux-2.4.21-chaos/kernel/ksyms.c 2003-12-12 16:19:25.000000000 +0300 -@@ -178,6 +178,7 @@ +@@ -178,6 +178,7 @@ EXPORT_SYMBOL(fget); EXPORT_SYMBOL(igrab); EXPORT_SYMBOL(iunique); EXPORT_SYMBOL(iget4_locked); @@ -746,7 +745,7 @@ Index: linux-2.4.21-chaos/kernel/ksyms.c EXPORT_SYMBOL(unlock_new_inode); EXPORT_SYMBOL(iput); EXPORT_SYMBOL(inode_init_once); -@@ -191,6 +192,7 @@ +@@ -191,6 +192,7 @@ EXPORT_SYMBOL(path_walk); EXPORT_SYMBOL(path_release); EXPORT_SYMBOL(__user_walk); EXPORT_SYMBOL(lookup_one_len); diff --git a/lustre/kernel_patches/patches/nfs_export_kernel-2.4.21-suse2.patch b/lustre/kernel_patches/patches/nfs_export_kernel-2.4.21-suse2.patch index 88810bf..3da14fe 100644 --- a/lustre/kernel_patches/patches/nfs_export_kernel-2.4.21-suse2.patch +++ b/lustre/kernel_patches/patches/nfs_export_kernel-2.4.21-suse2.patch @@ -19,7 +19,7 @@ Index: linux-2.4.21-chaos/fs/file_table.c */ -int init_private_file(struct file *filp, struct dentry *dentry, int mode) +int init_private_file_it(struct file *filp, struct dentry *dentry, int mode, -+ struct lookup_intent *it) ++ struct lookup_intent *it) { memset(filp, 0, sizeof(*filp)); filp->f_mode = mode; @@ -54,8 +54,8 @@ Index: linux-2.4.21-chaos/fs/inode.c -struct inode *iget4_locked(struct super_block *sb, unsigned long ino, find_inode_t find_actor, void *opaque) +struct inode *ifind(struct super_block *sb, unsigned long ino, -+ struct list_head *head, -+ find_inode_t find_actor, void *opaque) ++ struct list_head *head, ++ find_inode_t find_actor, void *opaque) { - struct list_head * head = inode_hashtable + hash(sb,ino); struct inode * inode; @@ -69,14 +69,14 @@ Index: linux-2.4.21-chaos/fs/inode.c +} + +struct inode *ilookup4(struct super_block *sb, unsigned long ino, -+ find_inode_t find_actor, void *opaque) ++ find_inode_t find_actor, void *opaque) +{ + struct list_head * head = inode_hashtable + hash(sb,ino); + return ifind(sb, ino, head, find_actor, opaque); +} + +struct inode *iget4_locked(struct super_block *sb, unsigned long ino, -+ find_inode_t find_actor, void *opaque) ++ find_inode_t find_actor, void *opaque) +{ + struct list_head * head = inode_hashtable + hash(sb,ino); + struct inode *inode = ifind(sb, ino, head, find_actor, opaque); @@ -126,7 +126,7 @@ Index: linux-2.4.21-chaos/fs/namei.c /* SMP-safe */ -struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) +struct dentry * lookup_one_len_it(const char * name, struct dentry * base, -+ int len, struct lookup_intent *it) ++ int len, struct lookup_intent *it) { unsigned long hash; struct qstr this; @@ -158,8 +158,8 @@ Index: linux-2.4.21-chaos/fs/nfsd/export.c ino = inode->i_ino; + if ((inode->i_sb->s_type->fs_flags & FS_NFSEXP_FSID) && + !(nxp->ex_flags & NFSEXP_FSID)) { -+ nxp->ex_dev = inode->i_sb->s_dev; -+ nxp->ex_flags |= NFSEXP_FSID; ++ nxp->ex_dev = inode->i_sb->s_dev; ++ nxp->ex_flags |= NFSEXP_FSID; + } err = -EINVAL; @@ -168,17 +168,15 @@ Index: linux-2.4.21-chaos/fs/nfsd/nfsfh.c =================================================================== --- linux-2.4.21-chaos.orig/fs/nfsd/nfsfh.c 2003-09-19 03:49:54.000000000 +0400 +++ linux-2.4.21-chaos/fs/nfsd/nfsfh.c 2003-12-12 16:19:25.000000000 +0300 -@@ -36,6 +36,15 @@ +@@ -36,6 +36,13 @@ int sequence; /* sequence counter */ }; +static struct dentry *lookup_it(struct inode *inode, struct dentry * dentry) +{ + if (inode->i_op->lookup_it) -+ return inode->i_op->lookup_it(inode, dentry, NULL, 0); -+ else -+ return inode->i_op->lookup(inode, dentry); -+ ++ return inode->i_op->lookup_it(inode, dentry, NULL, 0); ++ return inode->i_op->lookup(inode, dentry); +} + /* @@ -203,10 +201,10 @@ Index: linux-2.4.21-chaos/fs/nfsd/nfsfh.c + if ((dentry->d_flags & DCACHE_NFSD_DISCONNECTED) && + (dentry->d_parent == dentry) ) { + it.it_op_release = NULL; -+ /* -+ * XXX Temporary Hack: Simulating init_private_file without -+ * f_op->open for disconnected dentry Since we don't have actual -+ * dentry->d_name to revalidate in revalidate_it() ++ /* ++ * XXX Temporary Hack: Simulate init_private_file without ++ * f_op->open for disconnected dentry as we don't have ++ * actual dentry->d_name to revalidate in revalidate_it() + */ + filp = &file; + memset(filp, 0, sizeof(*filp)); @@ -227,13 +225,13 @@ Index: linux-2.4.21-chaos/fs/nfsd/nfsfh.c + } else { + error = init_private_file_it(&file, dentry, FMODE_READ, NULL); + } -+ if (error) ++ if (error) goto out; + error = -EINVAL; if (!file.f_op->readdir) goto out_close; -@@ -113,9 +152,13 @@ +@@ -113,9 +152,12 @@ } out_close: @@ -241,8 +239,7 @@ Index: linux-2.4.21-chaos/fs/nfsd/nfsfh.c + if (file.f_op->release && !filp) file.f_op->release(dir, &file); out: -+ if (dentry->d_op && -+ dentry->d_op->d_revalidate_it && ++ if (dentry->d_op && dentry->d_op->d_revalidate_it && + it.it_op_release && !filp) + intent_release(&it); return error; @@ -275,14 +272,13 @@ Index: linux-2.4.21-chaos/fs/nfsd/nfsfh.c pdentry = nfsd_findparent(dentry); err = PTR_ERR(pdentry); if (IS_ERR(pdentry)) -@@ -672,6 +719,11 @@ +@@ -672,6 +719,10 @@ inode = dentry->d_inode; + /* cache coherency for non-device filesystems */ -+ if (inode->i_op && inode->i_op->revalidate_it) { -+ inode->i_op->revalidate_it(dentry, NULL); -+ } ++ if (inode->i_op && inode->i_op->revalidate_it) ++ inode->i_op->revalidate_it(dentry, NULL); + /* Type check. The correct error return for type mismatches * does not seem to be generally agreed upon. SunOS seems to @@ -293,9 +289,9 @@ Index: linux-2.4.21-chaos/fs/nfsd/nfsfh.c out_uptodate: - printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n", - dentry->d_parent->d_name.name, dentry->d_name.name); -+ if(!dentry->d_parent->d_inode->i_op->mkdir_raw) ++ if (!dentry->d_parent->d_inode->i_op->mkdir_raw) + printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n", -+ dentry->d_parent->d_name.name, dentry->d_name.name); ++ dentry->d_parent->d_name.name, dentry->d_name.name); goto out; } @@ -308,7 +304,7 @@ Index: linux-2.4.21-chaos/fs/nfsd/vfs.c static struct raparms * raparm_cache; +static int link_raw(struct dentry *dold, struct dentry *ddir, -+ struct dentry *dnew) ++ struct dentry *dnew) +{ + int err; + @@ -317,17 +313,17 @@ Index: linux-2.4.21-chaos/fs/nfsd/vfs.c + struct inode_operations *op = nd.dentry->d_inode->i_op; + err = op->link_raw(&old_nd, &nd); + d_instantiate(dnew, dold->d_inode); -+ if(dold->d_inode->i_op && dold->d_inode->i_op->revalidate_it) ++ if (dold->d_inode->i_op && dold->d_inode->i_op->revalidate_it) + dold->d_inode->i_op->revalidate_it(dnew, NULL); + + return err; +} + +static int unlink_raw(struct dentry *dentry, char *fname, int flen, -+ struct dentry *rdentry) ++ struct dentry *rdentry) +{ + int err; -+ struct qstr last = { .name = fname, .len = flen }; ++ struct qstr last = { .name = fname, .len = flen }; + struct nameidata nd = { .dentry = dentry, .last = last }; + struct inode_operations *op = nd.dentry->d_inode->i_op; + err = op->unlink_raw(&nd); @@ -338,14 +334,14 @@ Index: linux-2.4.21-chaos/fs/nfsd/vfs.c +} + +static int rmdir_raw(struct dentry *dentry, char *fname, int flen, -+ struct dentry *rdentry) ++ struct dentry *rdentry) +{ + int err; -+ struct qstr last = { .name = fname, .len = flen }; ++ struct qstr last = { .name = fname, .len = flen }; + struct nameidata nd = { .dentry = dentry, .last = last }; + struct inode_operations *op = nd.dentry->d_inode->i_op; + err = op->rmdir_raw(&nd); -+ if(!err) { ++ if (!err) { + rdentry->d_inode->i_flags |= S_DEAD; + d_delete(rdentry); + } @@ -353,11 +349,11 @@ Index: linux-2.4.21-chaos/fs/nfsd/vfs.c + return err; +} + -+static int symlink_raw(struct dentry *dentry, char *fname, int flen, -+ char *path) ++static int symlink_raw(struct dentry *dentry, char *fname, int flen, ++ char *path) +{ + int err; -+ struct qstr last = { .name = fname, .len = flen }; ++ struct qstr last = { .name = fname, .len = flen }; + struct nameidata nd = { .dentry = dentry, .last = last }; + struct inode_operations *op = nd.dentry->d_inode->i_op; + err = op->symlink_raw(&nd, path); @@ -368,7 +364,7 @@ Index: linux-2.4.21-chaos/fs/nfsd/vfs.c +static int mkdir_raw(struct dentry *dentry, char *fname, int flen, int mode) +{ + int err; -+ struct qstr last = { .name = fname, .len = flen }; ++ struct qstr last = { .name = fname, .len = flen }; + struct nameidata nd = { .dentry = dentry, .last = last }; + struct inode_operations *op = nd.dentry->d_inode->i_op; + err = op->mkdir_raw(&nd, mode); @@ -377,19 +373,19 @@ Index: linux-2.4.21-chaos/fs/nfsd/vfs.c +} + +static int mknod_raw(struct dentry *dentry, char *fname, int flen, int mode, -+ dev_t dev) ++ dev_t dev) +{ + int err; -+ struct qstr last = { .name = fname, .len = flen }; ++ struct qstr last = { .name = fname, .len = flen }; + struct nameidata nd = { .dentry = dentry, .last = last }; + struct inode_operations *op = nd.dentry->d_inode->i_op; + err = op->mknod_raw(&nd, mode, dev); + + return err; -+} ++} + +static int rename_raw(struct dentry *fdentry, struct dentry *tdentry, -+ struct dentry *odentry, struct dentry *ndentry) ++ struct dentry *odentry, struct dentry *ndentry) +{ + int err; + @@ -435,7 +431,7 @@ Index: linux-2.4.21-chaos/fs/nfsd/vfs.c err = nfserr_notsync; if (!check_guard || guardtime == inode->i_ctime) { - err = notify_change(dentry, iap); -+ if ( dentry->d_inode->i_op && dentry->d_inode->i_op->setattr_raw) ++ if (dentry->d_inode->i_op && dentry->d_inode->i_op->setattr_raw) + err = setattr_raw(dentry->d_inode, iap); + else + err = notify_change(dentry, iap); @@ -450,26 +446,28 @@ Index: linux-2.4.21-chaos/fs/nfsd/vfs.c int err; /* If we get here, then the client has already done an "open", and (hopefully) -@@ -476,6 +602,14 @@ +@@ -476,6 +602,18 @@ filp->f_mode = FMODE_READ; } -+ intent_init(&it, IT_OPEN, (filp->f_flags & ~O_ACCMODE) | filp->f_mode); ++#ifndef O_OWNER_OVERRIDE ++#define O_OWNER_OVERRIDE 0200000000 ++#endif ++ intent_init(&it, IT_OPEN, (filp->f_flags & ~O_ACCMODE) | filp->f_mode | ++ O_OWNER_OVERRIDE); + + err = revalidate_it(dentry, &it); + if (err) + goto out_nfserr; -+ ++ + filp->f_it = ⁢ -+ ++ err = 0; if (filp->f_op && filp->f_op->open) { err = filp->f_op->open(inode, filp); -@@ -490,7 +624,11 @@ - atomic_dec(&filp->f_count); +@@ -490,6 +624,9 @@ } } -+ out_nfserr: + if (it.it_op_release) + intent_release(&it); @@ -486,33 +484,37 @@ Index: linux-2.4.21-chaos/fs/nfsd/vfs.c err = nfserr_perm; if (!flen) -@@ -837,20 +975,44 @@ +@@ -837,20 +975,47 @@ dentry = fhp->fh_dentry; dirp = dentry->d_inode; + switch (type) { -+ case S_IFDIR: -+ if (dirp->i_op->mkdir_raw) -+ error = mkdir_raw(dentry, fname, flen, iap->ia_mode); -+ break; -+ case S_IFCHR: -+ case S_IFBLK: -+ case S_IFIFO: -+ case S_IFSOCK: -+ case S_IFREG: -+ if (dirp->i_op->mknod_raw) { -+ if (type == S_IFREG) -+ rdev = 0; -+ error = mknod_raw(dentry, fname, flen, iap->ia_mode, rdev); -+ } -+ break; -+ default: -+ printk("nfsd: bad file type %o in nfsd_create\n", type); ++ case S_IFDIR: ++ if (dirp->i_op->mkdir_raw) ++ error = mkdir_raw(dentry, fname, flen, iap->ia_mode); ++ break; ++ case S_IFCHR: ++ case S_IFBLK: ++ case S_IFIFO: ++ case S_IFSOCK: ++ case S_IFREG: ++ if (dirp->i_op->mknod_raw) { ++ if (type == S_IFREG) ++ rdev = 0; ++ error = mknod_raw(dentry, fname,flen,iap->ia_mode,rdev); ++ } ++ break; ++ default: ++ printk("nfsd: bad file type %o in nfsd_create\n", type); ++ } ++ if (error && error != -EOPNOTSUPP) { ++ err = error; ++ goto out_nfserr; + } + err = nfserr_notdir; - if(!dirp->i_op || !dirp->i_op->lookup) -+ if(!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it)) ++ if (!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it)) goto out; /* * Check whether the response file handle has been verified yet. @@ -523,8 +525,7 @@ Index: linux-2.4.21-chaos/fs/nfsd/vfs.c - fh_lock(fhp); + if (!resfhp->fh_dentry || dirp->i_op->lookup_it) { + /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create -+ and nfsd_proc_create in case of lustre -+ */ ++ * and nfsd_proc_create in case of lustre */ + if (!resfhp->fh_dentry) + fh_lock(fhp); dchild = lookup_one_len(fname, dentry, flen); @@ -543,11 +544,11 @@ Index: linux-2.4.21-chaos/fs/nfsd/vfs.c - dprintk("nfsd_create: dentry %s/%s not negative!\n", - dentry->d_name.name, dchild->d_name.name); - goto out; -+ if ( error == -EOPNOTSUPP) { ++ if (error == -EOPNOTSUPP) { + if (dchild->d_inode) { + dprintk("nfsd_create: dentry %s/%s not negative!\n", + dentry->d_name.name, dchild->d_name.name); -+ goto out; ++ goto out; + } } @@ -570,7 +571,7 @@ Index: linux-2.4.21-chaos/fs/nfsd/vfs.c case S_IFIFO: case S_IFSOCK: - err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); -+ if (error == -EOPNOTSUPP) ++ if (error == -EOPNOTSUPP) + err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); break; default: @@ -583,10 +584,10 @@ Index: linux-2.4.21-chaos/fs/nfsd/vfs.c + if (dirp->i_op->mknod_raw) { + err = mknod_raw(dentry, fname, flen, iap->ia_mode, 0); + if (err && err != -EOPNOTSUPP) -+ goto out; ++ goto out_nfserr; + } + -+ if(!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it)) ++ if (!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it)) goto out; fh_lock(fhp); @@ -594,7 +595,7 @@ Index: linux-2.4.21-chaos/fs/nfsd/vfs.c case NFS3_CREATE_GUARDED: err = nfserr_exist; } -+ if(dirp->i_op->mknod_raw) ++ if (dirp->i_op->mknod_raw) + err = 0; goto out; } @@ -612,7 +613,7 @@ Index: linux-2.4.21-chaos/fs/nfsd/vfs.c goto out; fh_lock(fhp); dentry = fhp->fh_dentry; -+ ++ + if (dentry->d_inode->i_op->symlink_raw) + error = symlink_raw(dentry, fname, flen, path); + @@ -657,7 +658,7 @@ Index: linux-2.4.21-chaos/fs/nfsd/vfs.c } else #endif - err = vfs_rename(fdir, odentry, tdir, ndentry); -+ if(fdir->i_op->rename_raw) ++ if (fdir->i_op->rename_raw) + err = rename_raw(fdentry, tdentry, odentry, ndentry); + else + err = vfs_rename(fdir, odentry, tdir, ndentry); @@ -695,13 +696,12 @@ Index: linux-2.4.21-chaos/include/linux/fs.h =================================================================== --- linux-2.4.21-chaos.orig/include/linux/fs.h 2003-12-12 16:19:23.000000000 +0300 +++ linux-2.4.21-chaos/include/linux/fs.h 2003-12-12 16:19:25.000000000 +0300 -@@ -93,6 +93,9 @@ +@@ -93,6 +93,8 @@ #define FS_SINGLE 8 /* Filesystem that can have only one superblock */ #define FS_NOMOUNT 16 /* Never mount from userland */ #define FS_LITTER 32 /* Keeps the tree in dcache */ -+#define FS_NFSEXP_FSID 64 /* Use file system specific fsid for -+ * exporting non device filesystems. -+ */ ++#define FS_NFSEXP_FSID 64 /* Use file system specific fsid for ++ * exporting non device filesystems. */ #define FS_ODD_RENAME 32768 /* Temporary stuff; will go away as soon * as nfs_rename() will be cleaned up */ @@ -711,7 +711,7 @@ Index: linux-2.4.21-chaos/include/linux/fs.h int flags, struct lookup_intent *it); +extern int revalidate_it(struct dentry *dentry, struct lookup_intent *it); +extern int init_private_file_it(struct file *, struct dentry *dentry, int mode, -+ struct lookup_intent *it); ++ struct lookup_intent *it); extern int filp_close(struct file *, fl_owner_t id); extern char * getname(const char *); @@ -720,20 +720,19 @@ Index: linux-2.4.21-chaos/include/linux/fs.h extern int follow_up(struct vfsmount **, struct dentry **); extern struct dentry * lookup_one_len(const char *, struct dentry *, int); +extern struct dentry * lookup_one_len_it(const char *, struct dentry *, int, -+ struct lookup_intent *); ++ struct lookup_intent *); extern struct dentry * __lookup_hash(struct qstr *, struct dentry *); extern struct dentry * lookup_hash(struct qstr *, struct dentry *); #define user_path_walk(name,nd) __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd) -@@ -1477,7 +1485,8 @@ +@@ -1477,6 +1485,8 @@ extern struct inode * iget4_locked(struct super_block *, unsigned long, find_inode_t, void *); -- +extern struct inode * ilookup4(struct super_block *, unsigned long, -+ find_inode_t, void *); ++ find_inode_t, void *); + static inline struct inode *iget4(struct super_block *sb, unsigned long ino, find_inode_t find_actor, void *opaque) - { Index: linux-2.4.21-chaos/kernel/ksyms.c =================================================================== --- linux-2.4.21-chaos.orig/kernel/ksyms.c 2003-12-12 16:18:36.000000000 +0300 diff --git a/lustre/kernel_patches/patches/nfs_export_kernel-2.4.22-rh.patch b/lustre/kernel_patches/patches/nfs_export_kernel-2.4.22-rh.patch index 12f757a..436d99b 100644 --- a/lustre/kernel_patches/patches/nfs_export_kernel-2.4.22-rh.patch +++ b/lustre/kernel_patches/patches/nfs_export_kernel-2.4.22-rh.patch @@ -17,7 +17,7 @@ */ -int init_private_file(struct file *filp, struct dentry *dentry, int mode) +int init_private_file_it(struct file *filp, struct dentry *dentry, int mode, -+ struct lookup_intent *it) ++ struct lookup_intent *it) { memset(filp, 0, sizeof(*filp)); filp->f_mode = mode; @@ -50,8 +50,8 @@ -struct inode *iget4_locked(struct super_block *sb, unsigned long ino, find_inode_t find_actor, void *opaque) +struct inode *ifind(struct super_block *sb, unsigned long ino, -+ struct list_head *head, -+ find_inode_t find_actor, void *opaque) ++ struct list_head *head, ++ find_inode_t find_actor, void *opaque) { - struct list_head * head = inode_hashtable + hash(sb,ino); struct inode * inode; @@ -65,14 +65,14 @@ +} + +struct inode *ilookup4(struct super_block *sb, unsigned long ino, -+ find_inode_t find_actor, void *opaque) ++ find_inode_t find_actor, void *opaque) +{ + struct list_head * head = inode_hashtable + hash(sb,ino); + return ifind(sb, ino, head, find_actor, opaque); +} + +struct inode *iget4_locked(struct super_block *sb, unsigned long ino, -+ find_inode_t find_actor, void *opaque) ++ find_inode_t find_actor, void *opaque) +{ + struct list_head * head = inode_hashtable + hash(sb,ino); + struct inode *inode = ifind(sb, ino, head, find_actor, opaque); @@ -118,7 +118,7 @@ /* SMP-safe */ -struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) +struct dentry * lookup_one_len_it(const char * name, struct dentry * base, -+ int len, struct lookup_intent *it) ++ int len, struct lookup_intent *it) { unsigned long hash; struct qstr this; @@ -148,25 +148,23 @@ ino = inode->i_ino; + if ((inode->i_sb->s_type->fs_flags & FS_NFSEXP_FSID) && + !(nxp->ex_flags & NFSEXP_FSID)) { -+ nxp->ex_dev = inode->i_sb->s_dev; -+ nxp->ex_flags |= NFSEXP_FSID; ++ nxp->ex_dev = inode->i_sb->s_dev; ++ nxp->ex_flags |= NFSEXP_FSID; + } err = -EINVAL; exp = exp_get(clp, dev, ino); --- linux-2.4.22-ac1/fs/nfsd/nfsfh.c~nfs_export_kernel-2.4.22-rh 2003-08-25 15:44:43.000000000 +0400 +++ linux-2.4.22-ac1-alexey/fs/nfsd/nfsfh.c 2003-10-08 13:41:27.000000000 +0400 -@@ -36,6 +36,15 @@ struct nfsd_getdents_callback { +@@ -36,6 +36,13 @@ struct nfsd_getdents_callback { int sequence; /* sequence counter */ }; +static struct dentry *lookup_it(struct inode *inode, struct dentry * dentry) +{ + if (inode->i_op->lookup_it) -+ return inode->i_op->lookup_it(inode, dentry, NULL, 0); -+ else -+ return inode->i_op->lookup(inode, dentry); -+ ++ return inode->i_op->lookup_it(inode, dentry, NULL, 0); ++ return inode->i_op->lookup(inode, dentry); +} + /* @@ -191,10 +189,10 @@ + if ((dentry->d_flags & DCACHE_NFSD_DISCONNECTED) && + (dentry->d_parent == dentry) ) { + it.it_op_release = NULL; -+ /* -+ * XXX Temporary Hack: Simulating init_private_file without -+ * f_op->open for disconnected dentry Since we don't have actual -+ * dentry->d_name to revalidate in revalidate_it() ++ /* ++ * XXX Temporary Hack: Simulate init_private_file without ++ * f_op->open for disconnected dentry as we don't have ++ * actual dentry->d_name to revalidate in revalidate_it() + */ + filp = &file; + memset(filp, 0, sizeof(*filp)); @@ -215,13 +213,13 @@ + } else { + error = init_private_file_it(&file, dentry, FMODE_READ, NULL); + } -+ if (error) ++ if (error) goto out; + error = -EINVAL; if (!file.f_op->readdir) goto out_close; -@@ -113,9 +152,13 @@ static int nfsd_get_name(struct dentry * +@@ -113,9 +152,12 @@ static int nfsd_get_name(struct dentry * } out_close: @@ -229,8 +227,7 @@ + if (file.f_op->release && !filp) file.f_op->release(dir, &file); out: -+ if (dentry->d_op && -+ dentry->d_op->d_revalidate_it && ++ if (dentry->d_op && dentry->d_op->d_revalidate_it && + it.it_op_release && !filp) + intent_release(&it); return error; @@ -263,14 +260,13 @@ pdentry = nfsd_findparent(dentry); err = PTR_ERR(pdentry); if (IS_ERR(pdentry)) -@@ -669,6 +716,11 @@ fh_verify(struct svc_rqst *rqstp, struct +@@ -669,6 +716,10 @@ fh_verify(struct svc_rqst *rqstp, struct inode = dentry->d_inode; + /* cache coherency for non-device filesystems */ -+ if (inode->i_op && inode->i_op->revalidate_it) { -+ inode->i_op->revalidate_it(dentry, NULL); -+ } ++ if (inode->i_op && inode->i_op->revalidate_it) ++ inode->i_op->revalidate_it(dentry, NULL); + /* Type check. The correct error return for type mismatches * does not seem to be generally agreed upon. SunOS seems to @@ -281,9 +277,9 @@ out_uptodate: - printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n", - dentry->d_parent->d_name.name, dentry->d_name.name); -+ if(!dentry->d_parent->d_inode->i_op->mkdir_raw) ++ if (!dentry->d_parent->d_inode->i_op->mkdir_raw) + printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n", -+ dentry->d_parent->d_name.name, dentry->d_name.name); ++ dentry->d_parent->d_name.name, dentry->d_name.name); goto out; } @@ -294,7 +290,7 @@ static struct raparms * raparm_cache; +static int link_raw(struct dentry *dold, struct dentry *ddir, -+ struct dentry *dnew) ++ struct dentry *dnew) +{ + int err; + @@ -303,17 +299,17 @@ + struct inode_operations *op = nd.dentry->d_inode->i_op; + err = op->link_raw(&old_nd, &nd); + d_instantiate(dnew, dold->d_inode); -+ if(dold->d_inode->i_op && dold->d_inode->i_op->revalidate_it) ++ if (dold->d_inode->i_op && dold->d_inode->i_op->revalidate_it) + dold->d_inode->i_op->revalidate_it(dnew, NULL); + + return err; +} + +static int unlink_raw(struct dentry *dentry, char *fname, int flen, -+ struct dentry *rdentry) ++ struct dentry *rdentry) +{ + int err; -+ struct qstr last = { .name = fname, .len = flen }; ++ struct qstr last = { .name = fname, .len = flen }; + struct nameidata nd = { .dentry = dentry, .last = last }; + struct inode_operations *op = nd.dentry->d_inode->i_op; + err = op->unlink_raw(&nd); @@ -324,14 +320,14 @@ +} + +static int rmdir_raw(struct dentry *dentry, char *fname, int flen, -+ struct dentry *rdentry) ++ struct dentry *rdentry) +{ + int err; -+ struct qstr last = { .name = fname, .len = flen }; ++ struct qstr last = { .name = fname, .len = flen }; + struct nameidata nd = { .dentry = dentry, .last = last }; + struct inode_operations *op = nd.dentry->d_inode->i_op; + err = op->rmdir_raw(&nd); -+ if(!err) { ++ if (!err) { + rdentry->d_inode->i_flags |= S_DEAD; + d_delete(rdentry); + } @@ -339,11 +335,11 @@ + return err; +} + -+static int symlink_raw(struct dentry *dentry, char *fname, int flen, -+ char *path) ++static int symlink_raw(struct dentry *dentry, char *fname, int flen, ++ char *path) +{ + int err; -+ struct qstr last = { .name = fname, .len = flen }; ++ struct qstr last = { .name = fname, .len = flen }; + struct nameidata nd = { .dentry = dentry, .last = last }; + struct inode_operations *op = nd.dentry->d_inode->i_op; + err = op->symlink_raw(&nd, path); @@ -354,7 +350,7 @@ +static int mkdir_raw(struct dentry *dentry, char *fname, int flen, int mode) +{ + int err; -+ struct qstr last = { .name = fname, .len = flen }; ++ struct qstr last = { .name = fname, .len = flen }; + struct nameidata nd = { .dentry = dentry, .last = last }; + struct inode_operations *op = nd.dentry->d_inode->i_op; + err = op->mkdir_raw(&nd, mode); @@ -363,19 +359,19 @@ +} + +static int mknod_raw(struct dentry *dentry, char *fname, int flen, int mode, -+ dev_t dev) ++ dev_t dev) +{ + int err; -+ struct qstr last = { .name = fname, .len = flen }; ++ struct qstr last = { .name = fname, .len = flen }; + struct nameidata nd = { .dentry = dentry, .last = last }; + struct inode_operations *op = nd.dentry->d_inode->i_op; + err = op->mknod_raw(&nd, mode, dev); + + return err; -+} ++} + +static int rename_raw(struct dentry *fdentry, struct dentry *tdentry, -+ struct dentry *odentry, struct dentry *ndentry) ++ struct dentry *odentry, struct dentry *ndentry) +{ + int err; + @@ -421,7 +417,7 @@ err = nfserr_notsync; if (!check_guard || guardtime == inode->i_ctime) { - err = notify_change(dentry, iap); -+ if ( dentry->d_inode->i_op && dentry->d_inode->i_op->setattr_raw) ++ if (dentry->d_inode->i_op && dentry->d_inode->i_op->setattr_raw) + err = setattr_raw(dentry->d_inode, iap); + else + err = notify_change(dentry, iap); @@ -436,26 +432,28 @@ int err; /* If we get here, then the client has already done an "open", and (hopefully) -@@ -475,6 +601,14 @@ nfsd_open(struct svc_rqst *rqstp, struct +@@ -475,6 +601,18 @@ nfsd_open(struct svc_rqst *rqstp, struct filp->f_mode = FMODE_READ; } -+ intent_init(&it, IT_OPEN, (filp->f_flags & ~O_ACCMODE) | filp->f_mode); ++#ifndef O_OWNER_OVERRIDE ++#define O_OWNER_OVERRIDE 0200000000 ++#endif ++ intent_init(&it, IT_OPEN, (filp->f_flags & ~O_ACCMODE) | filp->f_mode | ++ O_OWNER_OVERRIDE); + + err = revalidate_it(dentry, &it); + if (err) + goto out_nfserr; -+ ++ + filp->f_it = ⁢ -+ ++ err = 0; if (filp->f_op && filp->f_op->open) { err = filp->f_op->open(inode, filp); -@@ -489,7 +623,11 @@ nfsd_open(struct svc_rqst *rqstp, struct - atomic_dec(&filp->f_count); +@@ -489,6 +623,9 @@ nfsd_open(struct svc_rqst *rqstp, struct } } -+ out_nfserr: + if (it.it_op_release) + intent_release(&it); @@ -472,33 +470,37 @@ err = nfserr_perm; if (!flen) -@@ -836,20 +974,44 @@ nfsd_create(struct svc_rqst *rqstp, stru +@@ -836,20 +974,47 @@ nfsd_create(struct svc_rqst *rqstp, stru dentry = fhp->fh_dentry; dirp = dentry->d_inode; + switch (type) { -+ case S_IFDIR: -+ if (dirp->i_op->mkdir_raw) -+ error = mkdir_raw(dentry, fname, flen, iap->ia_mode); -+ break; -+ case S_IFCHR: -+ case S_IFBLK: -+ case S_IFIFO: -+ case S_IFSOCK: -+ case S_IFREG: -+ if (dirp->i_op->mknod_raw) { -+ if (type == S_IFREG) -+ rdev = 0; -+ error = mknod_raw(dentry, fname, flen, iap->ia_mode, rdev); -+ } -+ break; -+ default: -+ printk("nfsd: bad file type %o in nfsd_create\n", type); ++ case S_IFDIR: ++ if (dirp->i_op->mkdir_raw) ++ error = mkdir_raw(dentry, fname, flen, iap->ia_mode); ++ break; ++ case S_IFCHR: ++ case S_IFBLK: ++ case S_IFIFO: ++ case S_IFSOCK: ++ case S_IFREG: ++ if (dirp->i_op->mknod_raw) { ++ if (type == S_IFREG) ++ rdev = 0; ++ error = mknod_raw(dentry, fname,flen,iap->ia_mode,rdev); ++ } ++ break; ++ default: ++ printk("nfsd: bad file type %o in nfsd_create\n", type); ++ } ++ if (error && error != -EOPNOTSUPP) { ++ err = error; ++ goto out_nfserr; + } + err = nfserr_notdir; - if(!dirp->i_op || !dirp->i_op->lookup) -+ if(!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it)) ++ if (!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it)) goto out; /* * Check whether the response file handle has been verified yet. @@ -509,8 +511,7 @@ - fh_lock(fhp); + if (!resfhp->fh_dentry || dirp->i_op->lookup_it) { + /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create -+ and nfsd_proc_create in case of lustre -+ */ ++ * and nfsd_proc_create in case of lustre */ + if (!resfhp->fh_dentry) + fh_lock(fhp); dchild = lookup_one_len(fname, dentry, flen); @@ -529,11 +530,11 @@ - dprintk("nfsd_create: dentry %s/%s not negative!\n", - dentry->d_name.name, dchild->d_name.name); - goto out; -+ if ( error == -EOPNOTSUPP) { ++ if (error == -EOPNOTSUPP) { + if (dchild->d_inode) { + dprintk("nfsd_create: dentry %s/%s not negative!\n", + dentry->d_name.name, dchild->d_name.name); -+ goto out; ++ goto out; + } } @@ -556,7 +557,7 @@ case S_IFIFO: case S_IFSOCK: - err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); -+ if (error == -EOPNOTSUPP) ++ if (error == -EOPNOTSUPP) + err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); break; default: @@ -569,10 +570,10 @@ + if (dirp->i_op->mknod_raw) { + err = mknod_raw(dentry, fname, flen, iap->ia_mode, 0); + if (err && err != -EOPNOTSUPP) -+ goto out; ++ goto out_nfserr; + } + -+ if(!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it)) ++ if (!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it)) goto out; fh_lock(fhp); @@ -580,7 +581,7 @@ case NFS3_CREATE_GUARDED: err = nfserr_exist; } -+ if(dirp->i_op->mknod_raw) ++ if (dirp->i_op->mknod_raw) + err = 0; goto out; } @@ -598,7 +599,7 @@ goto out; fh_lock(fhp); dentry = fhp->fh_dentry; -+ ++ + if (dentry->d_inode->i_op->symlink_raw) + error = symlink_raw(dentry, fname, flen, path); + @@ -643,7 +644,7 @@ } else #endif - err = vfs_rename(fdir, odentry, tdir, ndentry); -+ if(fdir->i_op->rename_raw) ++ if (fdir->i_op->rename_raw) + err = rename_raw(fdentry, tdentry, odentry, ndentry); + else + err = vfs_rename(fdir, odentry, tdir, ndentry); @@ -679,13 +680,12 @@ dput(rdentry); --- linux-2.4.22-ac1/include/linux/fs.h~nfs_export_kernel-2.4.22-rh 2003-09-26 01:00:26.000000000 +0400 +++ linux-2.4.22-ac1-alexey/include/linux/fs.h 2003-10-08 13:44:53.000000000 +0400 -@@ -93,6 +93,9 @@ extern int leases_enable, dir_notify_ena +@@ -93,6 +93,8 @@ extern int leases_enable, dir_notify_ena #define FS_SINGLE 8 /* Filesystem that can have only one superblock */ #define FS_NOMOUNT 16 /* Never mount from userland */ #define FS_LITTER 32 /* Keeps the tree in dcache */ -+#define FS_NFSEXP_FSID 64 /* Use file system specific fsid for -+ * exporting non device filesystems. -+ */ ++#define FS_NFSEXP_FSID 64 /* Use file system specific fsid for ++ * exporting non device filesystems. */ #define FS_ALWAYS_REVAL 16384 /* Always revalidate dentries returned by link_path_walk */ #define FS_ODD_RENAME 32768 /* Temporary stuff; will go away as soon @@ -695,7 +695,7 @@ int flags, struct lookup_intent *it); +extern int revalidate_it(struct dentry *dentry, struct lookup_intent *it); +extern int init_private_file_it(struct file *, struct dentry *dentry, int mode, -+ struct lookup_intent *it); ++ struct lookup_intent *it); extern int filp_close(struct file *, fl_owner_t id); extern char * getname(const char *); @@ -704,20 +704,19 @@ extern int follow_up(struct vfsmount **, struct dentry **); extern struct dentry * lookup_one_len(const char *, struct dentry *, int); +extern struct dentry * lookup_one_len_it(const char *, struct dentry *, int, -+ struct lookup_intent *); ++ struct lookup_intent *); extern struct dentry * lookup_hash(struct qstr *, struct dentry *); #define user_path_walk(name,nd) __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd) #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd) -@@ -1439,7 +1447,8 @@ typedef int (*find_inode_t)(struct inode +@@ -1439,6 +1447,8 @@ typedef int (*find_inode_t)(struct inode extern struct inode * iget4_locked(struct super_block *, unsigned long, find_inode_t, void *); -- +extern struct inode * ilookup4(struct super_block *, unsigned long, -+ find_inode_t, void *); ++ find_inode_t, void *); + static inline struct inode *iget4(struct super_block *sb, unsigned long ino, find_inode_t find_actor, void *opaque) - { --- linux-2.4.22-ac1/kernel/ksyms.c~nfs_export_kernel-2.4.22-rh 2003-09-26 00:57:28.000000000 +0400 +++ linux-2.4.22-ac1-alexey/kernel/ksyms.c 2003-10-08 13:45:20.000000000 +0400 @@ -165,6 +165,7 @@ EXPORT_SYMBOL(fget); @@ -736,5 +735,3 @@ EXPORT_SYMBOL(lookup_hash); EXPORT_SYMBOL(sys_close); EXPORT_SYMBOL(dcache_lock); - -_ diff --git a/lustre/kernel_patches/patches/nfs_export_kernel-2.4.22.patch b/lustre/kernel_patches/patches/nfs_export_kernel-2.4.22.patch index 4a1ba23..e573457 100644 --- a/lustre/kernel_patches/patches/nfs_export_kernel-2.4.22.patch +++ b/lustre/kernel_patches/patches/nfs_export_kernel-2.4.22.patch @@ -22,7 +22,7 @@ Index: linux-2.4.22-vanilla/fs/file_table.c */ -int init_private_file(struct file *filp, struct dentry *dentry, int mode) +int init_private_file_it(struct file *filp, struct dentry *dentry, int mode, -+ struct lookup_intent *it) ++ struct lookup_intent *it) { memset(filp, 0, sizeof(*filp)); filp->f_mode = mode; @@ -57,8 +57,8 @@ Index: linux-2.4.22-vanilla/fs/inode.c -struct inode *iget4(struct super_block *sb, unsigned long ino, find_inode_t find_actor, void *opaque) +static inline struct inode *ifind(struct super_block *sb, unsigned long ino, -+ struct list_head *head, -+ find_inode_t find_actor, void *opaque) ++ struct list_head *head, ++ find_inode_t find_actor, void *opaque) { - struct list_head * head = inode_hashtable + hash(sb,ino); struct inode * inode; @@ -72,14 +72,14 @@ Index: linux-2.4.22-vanilla/fs/inode.c +} + +struct inode *ilookup4(struct super_block *sb, unsigned long ino, -+ find_inode_t find_actor, void *opaque) ++ find_inode_t find_actor, void *opaque) +{ + struct list_head * head = inode_hashtable + hash(sb,ino); + return ifind(sb, ino, head, find_actor, opaque); +} + +struct inode *iget4(struct super_block *sb, unsigned long ino, -+ find_inode_t find_actor, void *opaque) ++ find_inode_t find_actor, void *opaque) +{ + struct list_head * head = inode_hashtable + hash(sb,ino); + struct inode *inode = ifind(sb, ino, head, find_actor, opaque); @@ -115,7 +115,7 @@ Index: linux-2.4.22-vanilla/fs/namei.c /* SMP-safe */ -struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) +struct dentry * lookup_one_len_it(const char * name, struct dentry * base, -+ int len, struct lookup_intent *it) ++ int len, struct lookup_intent *it) { unsigned long hash; struct qstr this; @@ -147,8 +147,8 @@ Index: linux-2.4.22-vanilla/fs/nfsd/export.c ino = inode->i_ino; + if ((inode->i_sb->s_type->fs_flags & FS_NFSEXP_FSID) && + !(nxp->ex_flags & NFSEXP_FSID)) { -+ nxp->ex_dev = inode->i_sb->s_dev; -+ nxp->ex_flags |= NFSEXP_FSID; ++ nxp->ex_dev = inode->i_sb->s_dev; ++ nxp->ex_flags |= NFSEXP_FSID; + } err = -EINVAL; @@ -157,17 +157,15 @@ Index: linux-2.4.22-vanilla/fs/nfsd/nfsfh.c =================================================================== --- linux-2.4.22-vanilla.orig/fs/nfsd/nfsfh.c 2003-11-03 23:22:11.000000000 +0300 +++ linux-2.4.22-vanilla/fs/nfsd/nfsfh.c 2003-11-03 23:44:38.000000000 +0300 -@@ -36,6 +36,15 @@ +@@ -36,6 +36,13 @@ int sequence; /* sequence counter */ }; +static struct dentry *lookup_it(struct inode *inode, struct dentry * dentry) +{ + if (inode->i_op->lookup_it) -+ return inode->i_op->lookup_it(inode, dentry, NULL, 0); -+ else -+ return inode->i_op->lookup(inode, dentry); -+ ++ return inode->i_op->lookup_it(inode, dentry, NULL, 0); ++ return inode->i_op->lookup(inode, dentry); +} + /* @@ -192,10 +190,10 @@ Index: linux-2.4.22-vanilla/fs/nfsd/nfsfh.c + if ((dentry->d_flags & DCACHE_NFSD_DISCONNECTED) && + (dentry->d_parent == dentry) ) { + it.it_op_release = NULL; -+ /* -+ * XXX Temporary Hack: Simulating init_private_file without -+ * f_op->open for disconnected dentry Since we don't have actual -+ * dentry->d_name to revalidate in revalidate_it() ++ /* ++ * XXX Temporary Hack: Simulate init_private_file without ++ * f_op->open for disconnected dentry as we don't have ++ * actual dentry->d_name to revalidate in revalidate_it() + */ + filp = &file; + memset(filp, 0, sizeof(*filp)); @@ -216,13 +214,13 @@ Index: linux-2.4.22-vanilla/fs/nfsd/nfsfh.c + } else { + error = init_private_file_it(&file, dentry, FMODE_READ, NULL); + } -+ if (error) ++ if (error) goto out; + error = -EINVAL; if (!file.f_op->readdir) goto out_close; -@@ -113,9 +152,13 @@ +@@ -113,9 +152,12 @@ } out_close: @@ -230,8 +228,7 @@ Index: linux-2.4.22-vanilla/fs/nfsd/nfsfh.c + if (file.f_op->release && !filp) file.f_op->release(dir, &file); out: -+ if (dentry->d_op && -+ dentry->d_op->d_revalidate_it && ++ if (dentry->d_op && dentry->d_op->d_revalidate_it && + it.it_op_release && !filp) + intent_release(&it); return error; @@ -264,14 +261,13 @@ Index: linux-2.4.22-vanilla/fs/nfsd/nfsfh.c pdentry = nfsd_findparent(dentry); err = PTR_ERR(pdentry); if (IS_ERR(pdentry)) -@@ -669,6 +716,11 @@ +@@ -669,6 +716,10 @@ inode = dentry->d_inode; + /* cache coherency for non-device filesystems */ -+ if (inode->i_op && inode->i_op->revalidate_it) { -+ inode->i_op->revalidate_it(dentry, NULL); -+ } ++ if (inode->i_op && inode->i_op->revalidate_it) ++ inode->i_op->revalidate_it(dentry, NULL); + /* Type check. The correct error return for type mismatches * does not seem to be generally agreed upon. SunOS seems to @@ -282,9 +278,9 @@ Index: linux-2.4.22-vanilla/fs/nfsd/nfsfh.c out_uptodate: - printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n", - dentry->d_parent->d_name.name, dentry->d_name.name); -+ if(!dentry->d_parent->d_inode->i_op->mkdir_raw) ++ if (!dentry->d_parent->d_inode->i_op->mkdir_raw) + printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n", -+ dentry->d_parent->d_name.name, dentry->d_name.name); ++ dentry->d_parent->d_name.name, dentry->d_name.name); goto out; } @@ -297,7 +293,7 @@ Index: linux-2.4.22-vanilla/fs/nfsd/vfs.c static struct raparms * raparm_cache; +static int link_raw(struct dentry *dold, struct dentry *ddir, -+ struct dentry *dnew) ++ struct dentry *dnew) +{ + int err; + @@ -306,17 +302,17 @@ Index: linux-2.4.22-vanilla/fs/nfsd/vfs.c + struct inode_operations *op = nd.dentry->d_inode->i_op; + err = op->link_raw(&old_nd, &nd); + d_instantiate(dnew, dold->d_inode); -+ if(dold->d_inode->i_op && dold->d_inode->i_op->revalidate_it) ++ if (dold->d_inode->i_op && dold->d_inode->i_op->revalidate_it) + dold->d_inode->i_op->revalidate_it(dnew, NULL); + + return err; +} + +static int unlink_raw(struct dentry *dentry, char *fname, int flen, -+ struct dentry *rdentry) ++ struct dentry *rdentry) +{ + int err; -+ struct qstr last = { .name = fname, .len = flen }; ++ struct qstr last = { .name = fname, .len = flen }; + struct nameidata nd = { .dentry = dentry, .last = last }; + struct inode_operations *op = nd.dentry->d_inode->i_op; + err = op->unlink_raw(&nd); @@ -327,14 +323,14 @@ Index: linux-2.4.22-vanilla/fs/nfsd/vfs.c +} + +static int rmdir_raw(struct dentry *dentry, char *fname, int flen, -+ struct dentry *rdentry) ++ struct dentry *rdentry) +{ + int err; -+ struct qstr last = { .name = fname, .len = flen }; ++ struct qstr last = { .name = fname, .len = flen }; + struct nameidata nd = { .dentry = dentry, .last = last }; + struct inode_operations *op = nd.dentry->d_inode->i_op; + err = op->rmdir_raw(&nd); -+ if(!err) { ++ if (!err) { + rdentry->d_inode->i_flags |= S_DEAD; + d_delete(rdentry); + } @@ -342,11 +338,11 @@ Index: linux-2.4.22-vanilla/fs/nfsd/vfs.c + return err; +} + -+static int symlink_raw(struct dentry *dentry, char *fname, int flen, -+ char *path) ++static int symlink_raw(struct dentry *dentry, char *fname, int flen, ++ char *path) +{ + int err; -+ struct qstr last = { .name = fname, .len = flen }; ++ struct qstr last = { .name = fname, .len = flen }; + struct nameidata nd = { .dentry = dentry, .last = last }; + struct inode_operations *op = nd.dentry->d_inode->i_op; + err = op->symlink_raw(&nd, path); @@ -357,7 +353,7 @@ Index: linux-2.4.22-vanilla/fs/nfsd/vfs.c +static int mkdir_raw(struct dentry *dentry, char *fname, int flen, int mode) +{ + int err; -+ struct qstr last = { .name = fname, .len = flen }; ++ struct qstr last = { .name = fname, .len = flen }; + struct nameidata nd = { .dentry = dentry, .last = last }; + struct inode_operations *op = nd.dentry->d_inode->i_op; + err = op->mkdir_raw(&nd, mode); @@ -366,19 +362,19 @@ Index: linux-2.4.22-vanilla/fs/nfsd/vfs.c +} + +static int mknod_raw(struct dentry *dentry, char *fname, int flen, int mode, -+ dev_t dev) ++ dev_t dev) +{ + int err; -+ struct qstr last = { .name = fname, .len = flen }; ++ struct qstr last = { .name = fname, .len = flen }; + struct nameidata nd = { .dentry = dentry, .last = last }; + struct inode_operations *op = nd.dentry->d_inode->i_op; + err = op->mknod_raw(&nd, mode, dev); + + return err; -+} ++} + +static int rename_raw(struct dentry *fdentry, struct dentry *tdentry, -+ struct dentry *odentry, struct dentry *ndentry) ++ struct dentry *odentry, struct dentry *ndentry) +{ + int err; + @@ -424,7 +420,7 @@ Index: linux-2.4.22-vanilla/fs/nfsd/vfs.c err = nfserr_notsync; if (!check_guard || guardtime == inode->i_ctime) { - err = notify_change(dentry, iap); -+ if ( dentry->d_inode->i_op && dentry->d_inode->i_op->setattr_raw) ++ if (dentry->d_inode->i_op && dentry->d_inode->i_op->setattr_raw) + err = setattr_raw(dentry->d_inode, iap); + else + err = notify_change(dentry, iap); @@ -439,26 +435,28 @@ Index: linux-2.4.22-vanilla/fs/nfsd/vfs.c int err; /* If we get here, then the client has already done an "open", and (hopefully) -@@ -475,6 +601,14 @@ +@@ -475,6 +601,18 @@ filp->f_mode = FMODE_READ; } -+ intent_init(&it, IT_OPEN, (filp->f_flags & ~O_ACCMODE) | filp->f_mode); ++#ifndef O_OWNER_OVERRIDE ++#define O_OWNER_OVERRIDE 0200000000 ++#endif ++ intent_init(&it, IT_OPEN, (filp->f_flags & ~O_ACCMODE) | filp->f_mode | ++ O_OWNER_OVERRIDE); + + err = revalidate_it(dentry, &it); + if (err) + goto out_nfserr; -+ ++ + filp->f_it = ⁢ -+ ++ err = 0; if (filp->f_op && filp->f_op->open) { err = filp->f_op->open(inode, filp); -@@ -489,7 +623,11 @@ - atomic_dec(&filp->f_count); +@@ -489,6 +623,9 @@ } } -+ out_nfserr: + if (it.it_op_release) + intent_release(&it); @@ -475,33 +473,37 @@ Index: linux-2.4.22-vanilla/fs/nfsd/vfs.c err = nfserr_perm; if (!flen) -@@ -836,20 +974,44 @@ +@@ -836,20 +974,47 @@ dentry = fhp->fh_dentry; dirp = dentry->d_inode; + switch (type) { -+ case S_IFDIR: -+ if (dirp->i_op->mkdir_raw) -+ error = mkdir_raw(dentry, fname, flen, iap->ia_mode); -+ break; -+ case S_IFCHR: -+ case S_IFBLK: -+ case S_IFIFO: -+ case S_IFSOCK: -+ case S_IFREG: -+ if (dirp->i_op->mknod_raw) { -+ if (type == S_IFREG) -+ rdev = 0; -+ error = mknod_raw(dentry, fname, flen, iap->ia_mode, rdev); -+ } -+ break; -+ default: -+ printk("nfsd: bad file type %o in nfsd_create\n", type); ++ case S_IFDIR: ++ if (dirp->i_op->mkdir_raw) ++ error = mkdir_raw(dentry, fname, flen, iap->ia_mode); ++ break; ++ case S_IFCHR: ++ case S_IFBLK: ++ case S_IFIFO: ++ case S_IFSOCK: ++ case S_IFREG: ++ if (dirp->i_op->mknod_raw) { ++ if (type == S_IFREG) ++ rdev = 0; ++ error = mknod_raw(dentry, fname,flen,iap->ia_mode,rdev); ++ } ++ break; ++ default: ++ printk("nfsd: bad file type %o in nfsd_create\n", type); ++ } ++ if (error && error != -EOPNOTSUPP) { ++ err = error; ++ goto out_nfserr; + } + err = nfserr_notdir; - if(!dirp->i_op || !dirp->i_op->lookup) -+ if(!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it)) ++ if (!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it)) goto out; /* * Check whether the response file handle has been verified yet. @@ -512,8 +514,7 @@ Index: linux-2.4.22-vanilla/fs/nfsd/vfs.c - fh_lock(fhp); + if (!resfhp->fh_dentry || dirp->i_op->lookup_it) { + /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create -+ and nfsd_proc_create in case of lustre -+ */ ++ * and nfsd_proc_create in case of lustre */ + if (!resfhp->fh_dentry) + fh_lock(fhp); dchild = lookup_one_len(fname, dentry, flen); @@ -532,11 +533,11 @@ Index: linux-2.4.22-vanilla/fs/nfsd/vfs.c - dprintk("nfsd_create: dentry %s/%s not negative!\n", - dentry->d_name.name, dchild->d_name.name); - goto out; -+ if ( error == -EOPNOTSUPP) { ++ if (error == -EOPNOTSUPP) { + if (dchild->d_inode) { + dprintk("nfsd_create: dentry %s/%s not negative!\n", + dentry->d_name.name, dchild->d_name.name); -+ goto out; ++ goto out; + } } @@ -559,7 +560,7 @@ Index: linux-2.4.22-vanilla/fs/nfsd/vfs.c case S_IFIFO: case S_IFSOCK: - err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); -+ if (error == -EOPNOTSUPP) ++ if (error == -EOPNOTSUPP) + err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); break; default: @@ -572,10 +573,10 @@ Index: linux-2.4.22-vanilla/fs/nfsd/vfs.c + if (dirp->i_op->mknod_raw) { + err = mknod_raw(dentry, fname, flen, iap->ia_mode, 0); + if (err && err != -EOPNOTSUPP) -+ goto out; ++ goto out_nfserr; + } + -+ if(!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it)) ++ if (!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it)) goto out; fh_lock(fhp); @@ -583,7 +584,7 @@ Index: linux-2.4.22-vanilla/fs/nfsd/vfs.c case NFS3_CREATE_GUARDED: err = nfserr_exist; } -+ if(dirp->i_op->mknod_raw) ++ if (dirp->i_op->mknod_raw) + err = 0; goto out; } @@ -601,7 +602,7 @@ Index: linux-2.4.22-vanilla/fs/nfsd/vfs.c goto out; fh_lock(fhp); dentry = fhp->fh_dentry; -+ ++ + if (dentry->d_inode->i_op->symlink_raw) + error = symlink_raw(dentry, fname, flen, path); + @@ -624,7 +625,7 @@ Index: linux-2.4.22-vanilla/fs/nfsd/vfs.c - err = notify_change(dnew, iap); + if (dnew->d_inode->i_op && dnew->d_inode->i_op->setattr_raw) + err = setattr_raw(dnew->d_inode, iap); -+ else ++ else + err = notify_change(dnew, iap); if (err) err = nfserrno(err); @@ -646,7 +647,7 @@ Index: linux-2.4.22-vanilla/fs/nfsd/vfs.c } else #endif - err = vfs_rename(fdir, odentry, tdir, ndentry); -+ if(fdir->i_op->rename_raw) ++ if (fdir->i_op->rename_raw) + err = rename_raw(fdentry, tdentry, odentry, ndentry); + else + err = vfs_rename(fdir, odentry, tdir, ndentry); @@ -684,13 +685,12 @@ Index: linux-2.4.22-vanilla/include/linux/fs.h =================================================================== --- linux-2.4.22-vanilla.orig/include/linux/fs.h 2003-11-03 23:41:40.000000000 +0300 +++ linux-2.4.22-vanilla/include/linux/fs.h 2003-11-03 23:44:38.000000000 +0300 -@@ -93,6 +93,9 @@ +@@ -93,6 +93,8 @@ #define FS_SINGLE 8 /* Filesystem that can have only one superblock */ #define FS_NOMOUNT 16 /* Never mount from userland */ #define FS_LITTER 32 /* Keeps the tree in dcache */ -+#define FS_NFSEXP_FSID 64 /* Use file system specific fsid for -+ * exporting non device filesystems. -+ */ ++#define FS_NFSEXP_FSID 64 /* Use file system specific fsid for ++ * exporting non device filesystems. */ #define FS_ODD_RENAME 32768 /* Temporary stuff; will go away as soon * as nfs_rename() will be cleaned up */ @@ -700,7 +700,7 @@ Index: linux-2.4.22-vanilla/include/linux/fs.h int flags, struct lookup_intent *it); +extern int revalidate_it(struct dentry *dentry, struct lookup_intent *it); +extern int init_private_file_it(struct file *, struct dentry *dentry, int mode, -+ struct lookup_intent *it); ++ struct lookup_intent *it); extern int filp_close(struct file *, fl_owner_t id); extern char * getname(const char *); @@ -709,7 +709,7 @@ Index: linux-2.4.22-vanilla/include/linux/fs.h extern int follow_up(struct vfsmount **, struct dentry **); extern struct dentry * lookup_one_len(const char *, struct dentry *, int); +extern struct dentry * lookup_one_len_it(const char *, struct dentry *, int, -+ struct lookup_intent *); ++ struct lookup_intent *); extern struct dentry * lookup_hash(struct qstr *, struct dentry *); #define user_path_walk(name,nd) __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd) #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd) @@ -718,7 +718,7 @@ Index: linux-2.4.22-vanilla/include/linux/fs.h typedef int (*find_inode_t)(struct inode *, unsigned long, void *); extern struct inode * iget4(struct super_block *, unsigned long, find_inode_t, void *); +extern struct inode * ilookup4(struct super_block *, unsigned long, -+ find_inode_t, void *); ++ find_inode_t, void *); static inline struct inode *iget(struct super_block *sb, unsigned long ino) { return iget4(sb, ino, NULL, NULL); diff --git a/lustre/mdc/mdc_lib.c b/lustre/mdc/mdc_lib.c index e2dc251..85ce60a 100644 --- a/lustre/mdc/mdc_lib.c +++ b/lustre/mdc/mdc_lib.c @@ -100,7 +100,7 @@ static __u32 mds_pack_open_flags(__u32 flags) return (flags & (FMODE_READ | FMODE_WRITE | FMODE_EXEC | MDS_OPEN_DELAY_CREATE | MDS_OPEN_HAS_EA | - MDS_OPEN_HAS_OBJS)) | + MDS_OPEN_HAS_OBJS | MDS_OPEN_OWNEROVERRIDE)) | ((flags & O_CREAT) ? MDS_OPEN_CREAT : 0) | ((flags & O_EXCL) ? MDS_OPEN_EXCL : 0) | ((flags & O_TRUNC) ? MDS_OPEN_TRUNC : 0) | diff --git a/lustre/mds/mds_open.c b/lustre/mds/mds_open.c index 194bbb5..3f4e67e 100644 --- a/lustre/mds/mds_open.c +++ b/lustre/mds/mds_open.c @@ -594,10 +594,18 @@ static void reconstruct_open(struct mds_update_record *rec, int offset, } /* do NOT or the MAY_*'s, you'll get the weakest */ -static int accmode(int flags) +static int accmode(struct inode *inode, int flags) { int res = 0; + /* Sadly, NFSD reopens a file repeatedly during operation, so the + * "acc_mode = 0" allowance for newly-created files isn't honoured. + * NFSD uses the MDS_OPEN_OWNEROVERRIDE flag to say that a file + * owner can write to a file even if it is marked readonly to hide + * its brokenness. (bug 5781) */ + if (flags & MDS_OPEN_OWNEROVERRIDE && inode->i_uid == current->fsuid) + return 0; + if (flags & FMODE_READ) res = MAY_READ; if (flags & (FMODE_WRITE|MDS_OPEN_TRUNC)) @@ -813,9 +821,8 @@ int mds_open(struct mds_update_record *rec, int offset, LDLM_LOCK_PUT(lock); } DEBUG_REQ(D_ERROR, req, "fid2 not set on open replay"); + RETURN(-EFAULT); } - /* this LASSERT needs to go; handle more gracefully. */ - LASSERT(rec->ur_fid2->id); rc = mds_open_by_fid(req, rec->ur_fid2, body, rec->ur_flags, rec, rep); @@ -836,8 +843,6 @@ int mds_open(struct mds_update_record *rec, int offset, RETURN(-ENOMEM); } - acc_mode = accmode(rec->ur_flags); - /* Step 1: Find and lock the parent */ if (rec->ur_flags & MDS_OPEN_CREAT) parent_mode = LCK_PW; @@ -937,8 +942,11 @@ int mds_open(struct mds_update_record *rec, int offset, rc = fsfilt_commit(obd, dchild->d_inode, handle, 0); handle = NULL; acc_mode = 0; /* Don't check for permissions */ + } else { + acc_mode = accmode(dchild->d_inode, rec->ur_flags); } + LASSERTF(!mds_inode_is_orphan(dchild->d_inode), "dchild %.*s (%p) inode %p\n", dchild->d_name.len, dchild->d_name.name, dchild, dchild->d_inode); -- 1.8.3.1