From: girish_c Date: Wed, 18 Jun 2003 16:39:43 +0000 (+0000) Subject: NFS export patch for lustre X-Git-Tag: v1_7_100~1^91~112 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=2a2b7da26c937e69c725bc697bee84160f216366;p=fs%2Flustre-release.git NFS export patch for lustre 1) Patch is updated with review comments 2) All Connectathon tests passes except bigfile(30 MB)test --- diff --git a/lustre/kernel_patches/patches/nfs_export-2.4.18-18.patch b/lustre/kernel_patches/patches/nfs_export-2.4.18-18.patch new file mode 100644 index 0000000..01c2727 --- /dev/null +++ b/lustre/kernel_patches/patches/nfs_export-2.4.18-18.patch @@ -0,0 +1,514 @@ +diff -urN linux/fs/inode.c linux_n/fs/inode.c +--- linux/fs/inode.c 2003-06-18 21:39:14.000000000 +0530 ++++ linux_n/fs/inode.c 2003-06-18 21:39:53.000000000 +0530 +@@ -987,6 +987,24 @@ + } + + ++struct inode *search_icache_for_lustre(struct super_block *sb, unsigned long ino) ++{ ++ struct list_head * head = inode_hashtable + hash(sb,ino); ++ struct inode * inode; ++ ++ spin_lock(&inode_lock); ++ inode = find_inode(sb, ino, head, NULL, NULL); ++ if (inode) { ++ __iget(inode); ++ spin_unlock(&inode_lock); ++ wait_on_inode(inode); ++ return inode; ++ } ++ spin_unlock(&inode_lock); ++ ++ return NULL; ++} ++ + struct inode *iget4(struct super_block *sb, unsigned long ino, find_inode_t find_actor, void *opaque) + { + struct list_head * head = inode_hashtable + hash(sb,ino); +diff -urN linux/fs/namei.c linux_n/fs/namei.c +--- linux/fs/namei.c 2003-06-18 21:39:13.000000000 +0530 ++++ linux_n/fs/namei.c 2003-06-18 21:39:41.000000000 +0530 +@@ -918,8 +918,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) + { + unsigned long hash; + struct qstr this; +@@ -939,11 +938,17 @@ + } + this.hash = end_name_hash(hash); + +- return lookup_hash_it(&this, base, NULL); ++ return lookup_hash_it(&this, base, it); + access: + return ERR_PTR(-EACCES); + } + ++/* SMP-safe */ ++struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) ++{ ++ return lookup_one_len_it(name, base, len, NULL); ++} ++ + /* + * namei() + * +diff -urN linux/fs/nfsd/export.c linux_n/fs/nfsd/export.c +--- linux/fs/nfsd/export.c 2003-01-21 04:00:34.000000000 +0530 ++++ linux_n/fs/nfsd/export.c 2003-06-18 21:39:42.000000000 +0530 +@@ -289,6 +289,7 @@ + * either using fh_to_dentry (prefered) + * or using read_inode (the hack). + */ ++/* + if (!((inode->i_sb->s_type->fs_flags & FS_REQUIRES_DEV) + || (nxp->ex_flags & NFSEXP_FSID)) + || +@@ -297,7 +298,7 @@ + dprintk("exp_export: export of invalid fs type.\n"); + goto finish; + } +- ++*/ + if ((parent = exp_child(clp, dev, nd.dentry)) != NULL) { + dprintk("exp_export: export not valid (Rule 3).\n"); + goto finish; +diff -urN linux/fs/nfsd/nfsfh.c linux_n/fs/nfsd/nfsfh.c +--- linux/fs/nfsd/nfsfh.c 2003-01-21 04:00:34.000000000 +0530 ++++ linux_n/fs/nfsd/nfsfh.c 2003-06-18 21:39:42.000000000 +0530 +@@ -60,6 +60,11 @@ + return result; + } + ++static struct dentry * lookup2(struct inode *inode, struct dentry *dentry) ++{ ++ return inode->i_op->lookup2(inode, dentry, NULL); ++} ++ + /** + * nfsd_get_name - default nfsd_operations->get_name function + * @dentry: the directory in which to find a name +@@ -275,7 +280,10 @@ + * it is well connected. But nobody returns different dentrys do they? + */ + down(&child->d_inode->i_sem); +- pdentry = child->d_inode->i_op->lookup(child->d_inode, tdentry); ++ if (child->d_inode->i_op->lookup2) ++ pdentry = lookup2(child->d_inode, tdentry); ++ else ++ pdentry = child->d_inode->i_op->lookup(child->d_inode, tdentry); + up(&child->d_inode->i_sem); + d_drop(tdentry); /* we never want ".." hashed */ + if (!pdentry && tdentry->d_inode == NULL) { +@@ -666,6 +674,9 @@ + } + + inode = dentry->d_inode; ++ ++ if (inode->i_op && inode->i_op->revalidate) //girish:- to keep (lustre)cache coherency ++ inode->i_op->revalidate(dentry); + + /* Type check. The correct error return for type mismatches + * does not seem to be generally agreed upon. SunOS seems to +@@ -905,8 +916,9 @@ + 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->mkdir2) ++ printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n", ++ dentry->d_parent->d_name.name, dentry->d_name.name); + goto out; + } + +diff -urN linux/fs/nfsd/nfsproc.c linux_n/fs/nfsd/nfsproc.c +--- linux/fs/nfsd/nfsproc.c 2003-01-21 04:00:34.000000000 +0530 ++++ linux_n/fs/nfsd/nfsproc.c 2003-06-18 21:39:30.000000000 +0530 +@@ -199,6 +199,7 @@ + struct dentry *dchild; + int nfserr, type, mode; + dev_t rdev = NODEV; ++ struct lookup_intent it = { .it_op = IT_CREAT }; + + dprintk("nfsd: CREATE %s %.*s\n", + SVCFH_fmt(dirfhp), argp->len, argp->name); +@@ -217,7 +218,7 @@ + if (isdotent(argp->name, argp->len)) + goto done; + fh_lock(dirfhp); +- dchild = lookup_one_len(argp->name, dirfhp->fh_dentry, argp->len); ++ dchild = lookup_one_len_it(argp->name, dirfhp->fh_dentry, argp->len, &it); + if (IS_ERR(dchild)) { + nfserr = nfserrno(PTR_ERR(dchild)); + goto out_unlock; +diff -urN linux/fs/nfsd/vfs.c linux_n/fs/nfsd/vfs.c +--- linux/fs/nfsd/vfs.c 2003-06-18 21:39:13.000000000 +0530 ++++ linux_n/fs/nfsd/vfs.c 2003-06-18 21:41:40.000000000 +0530 +@@ -77,6 +77,75 @@ + static struct raparms * raparml; + static struct raparms * raparm_cache; + ++ ++static int link2(struct inode *src, struct inode *dir, const char *name, int len, struct dentry *dnew) ++{ ++ int error; ++ ++ error = dir->i_op->link2(src, dir, name, len); ++ d_instantiate(dnew, src); ++ if(src->i_op && src->i_op->revalidate) ++ src->i_op->revalidate(dnew); ++ ++ return error; ++} ++ ++static int unlink2(struct inode *dir, const char *name, int len) ++{ ++ return dir->i_op->unlink2(dir, name, len); ++} ++ ++static int symlink2(struct inode *dir, const char *name, int len, const char *tgt) ++{ ++ return dir->i_op->symlink2(dir, name, len, tgt); ++} ++ ++static int mkdir2(struct inode *dir, const char *name, int len, int mode) ++{ ++ return dir->i_op->mkdir2(dir, name, len, mode); ++} ++ ++static int rmdir2(struct inode *dir, const char *name, int len) ++{ ++ return dir->i_op->rmdir2(dir, name, len); ++} ++ ++static int mknod2(struct inode *dir, const char *name, int len, int mode, int rdev) ++{ ++ return dir->i_op->mknod(dir, name, len, mode); ++} ++ ++static int rename2(struct inode *src, struct inode *tgt, struct dentry *odentry, struct dentry *ndentry) ++{ ++ int err; ++ ++ err = src->i_op->rename2(src, ++ tgt, ++ odentry->d_name.name, ++ odentry->d_name.len, ++ ndentry->d_name.name, ++ ndentry->d_name.len); ++ d_move(odentry, ndentry); ++ ++ return err; ++} ++ ++static int open2(struct dentry *dentry, struct lookup_intent *it) ++{ ++ int err = 0; ++ ++ if (dentry && dentry->d_op && dentry->d_op->d_revalidate2) { ++ if (!dentry->d_op->d_revalidate2(dentry, 0, it) && !d_invalidate(dentry)) { ++ dput(dentry); ++ err = -EINVAL; ++ dentry = NULL; ++ return err; ++ } ++ } ++ ++ return err; ++} ++ + /* + * Look up one component of a pathname. + * N.B. After this call _both_ fhp and resfh need an fh_put +@@ -425,9 +494,11 @@ + nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, + int access, struct file *filp) + { +- struct dentry *dentry; +- struct inode *inode; +- int err; ++ struct dentry *dentry; ++ struct inode *inode; ++ int err; ++ ++ struct lookup_intent it = { .it_op = IT_OPEN }; + + /* If we get here, then the client has already done an "open", and (hopefully) + * checked permission - so allow OWNER_OVERRIDE in case a chmod has now revoked +@@ -472,7 +543,9 @@ + filp->f_flags = O_RDONLY|O_LARGEFILE; + filp->f_mode = FMODE_READ; + } +- ++ if(err = open2(dentry, &it)) ++ goto out_nfserr; ++ + err = 0; + if (filp->f_op && filp->f_op->open) { + err = filp->f_op->open(inode, filp); +@@ -487,6 +560,8 @@ + atomic_dec(&filp->f_count); + } + } ++ intent_release(dentry, &it); ++ + out_nfserr: + if (err) + err = nfserrno(err); +@@ -825,6 +900,7 @@ + struct dentry *dentry, *dchild; + struct inode *dirp; + int err; ++ int error = -EOPNOTSUPP; + + err = nfserr_perm; + if (!flen) +@@ -839,9 +915,25 @@ + + dentry = fhp->fh_dentry; + dirp = dentry->d_inode; ++ ++ switch (type) { ++ case S_IFDIR: ++ if (dirp->i_op->mkdir2) ++ error = mkdir2(dirp, fname, flen, iap->ia_mode); ++ break; ++ case S_IFCHR: ++ case S_IFBLK: ++ case S_IFIFO: ++ case S_IFSOCK: ++ if (dirp->i_op->mknod2) ++ error = mknod2(dirp, fname, flen, iap->ia_mode, rdev); ++ break; ++ default: ++ printk("nfsd: bad file type %o in nfsd_create\n", type); ++ } + + err = nfserr_notdir; +- if(!dirp->i_op || !dirp->i_op->lookup) ++ if(!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup2)) + goto out; + /* + * Check whether the response file handle has been verified yet. +@@ -874,11 +966,13 @@ + * Make sure the child dentry is still negative ... + */ + err = nfserr_exist; +- if (dchild->d_inode) { +- dprintk("nfsd_create: dentry %s/%s not negative!\n", +- dentry->d_name.name, dchild->d_name.name); +- goto out; +- } ++ 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; ++ } ++ } + + if (!(iap->ia_valid & ATTR_MODE)) + iap->ia_mode = 0; +@@ -893,13 +987,16 @@ + err = vfs_create(dirp, dchild, iap->ia_mode); + break; + case S_IFDIR: +- err = vfs_mkdir(dirp, dchild, iap->ia_mode); ++ if ( error == -EOPNOTSUPP) ++ err = vfs_mkdir(dirp, dchild, iap->ia_mode); + break; + case S_IFCHR: + case S_IFBLK: + case S_IFIFO: + case S_IFSOCK: +- err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); ++ err = error; ++ 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); +@@ -949,6 +1046,7 @@ + int err; + __u32 v_mtime=0, v_atime=0; + int v_mode=0; ++ struct lookup_intent it = { .it_op = IT_CREAT|IT_OPEN, .it_flags = 35137, .it_mode = iap->ia_mode }; + + err = nfserr_perm; + if (!flen) +@@ -968,17 +1066,22 @@ + /* Get all the sanity checks out of the way before + * we lock the parent. */ + err = nfserr_notdir; +- if(!dirp->i_op || !dirp->i_op->lookup) ++ if(!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup2)) + goto out; + fh_lock(fhp); + + /* + * Compose the response file handle. + */ +- dchild = lookup_one_len(fname, dentry, flen); ++ if (dirp->i_op->lookup2) { ++ dchild = lookup_one_len_it(fname, dentry, flen, &it); ++ } else ++ dchild = lookup_one_len(fname, dentry, flen); ++ + err = PTR_ERR(dchild); +- if (IS_ERR(dchild)) ++ if (IS_ERR(dchild)) { + goto out_nfserr; ++ } + + err = fh_compose(resfhp, fhp->fh_export, dchild, fhp); + if (err) +@@ -1023,6 +1126,7 @@ + } + + err = vfs_create(dirp, dchild, iap->ia_mode); ++ + if (err < 0) + goto out_nfserr; + +@@ -1047,6 +1151,8 @@ + iap->ia_atime = v_atime; + iap->ia_mode = v_mode; + } ++ ++ iap->ia_valid |= ATTR_FROM_OPEN; + + /* Set file attributes. + * Mode has already been set but we might need to reset it +@@ -1058,6 +1164,9 @@ + if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID)) != 0) + err = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0); + ++ if (dirp->i_op->lookup2) { ++ intent_release(dchild, &it); ++ } + out: + fh_unlock(fhp); + return err; +@@ -1125,7 +1234,7 @@ + struct iattr *iap) + { + struct dentry *dentry, *dnew; +- int err, cerr; ++ int err, cerr, error; + + err = nfserr_noent; + if (!flen || !plen) +@@ -1139,12 +1248,19 @@ + goto out; + fh_lock(fhp); + dentry = fhp->fh_dentry; ++ ++ if (dentry->d_inode->i_op->symlink2) ++ error = symlink2(dentry->d_inode, fname, flen, path); ++ + dnew = lookup_one_len(fname, dentry, flen); + err = PTR_ERR(dnew); + if (IS_ERR(dnew)) + goto out_nfserr; + +- err = vfs_symlink(dentry->d_inode, dnew, path); ++ err = error; ++ if (error == -EOPNOTSUPP || !dentry->d_inode->i_op->symlink2) ++ err = vfs_symlink(dentry->d_inode, dnew, path); ++ + if (!err) { + if (EX_ISSYNC(fhp->fh_export)) + nfsd_sync_dir(dentry); +@@ -1212,7 +1328,12 @@ + dold = tfhp->fh_dentry; + dest = dold->d_inode; + +- err = vfs_link(dold, dirp, dnew); ++ if (dirp->i_op->link2) ++ err = link2(dest, dirp, name, len, dnew); ++ ++ if (err == -EOPNOTSUPP || !dirp->i_op->link2) ++ err = vfs_link(dold, dirp, dnew); ++ + if (!err) { + if (EX_ISSYNC(ffhp->fh_export)) { + nfsd_sync_dir(ddir); +@@ -1298,8 +1419,13 @@ + err = nfserr_perm; + } else + #endif +- err = vfs_rename(fdir, odentry, tdir, ndentry, NULL); ++ if(fdir->i_op->rename2) ++ err = rename2(fdir, tdir, odentry, ndentry); ++ else ++ if(err == -EOPNOTSUPP || !fdir->i_op->rename2) ++ err = vfs_rename(fdir, odentry, tdir, ndentry, NULL); + unlock_kernel(); ++ + if (!err && EX_ISSYNC(tfhp->fh_export)) { + nfsd_sync_dir(tdentry); + nfsd_sync_dir(fdentry); +@@ -1366,9 +1492,17 @@ + err = nfserr_perm; + } else + #endif +- err = vfs_unlink(dirp, rdentry); ++ { ++ if (dirp->i_op->unlink2) ++ err = unlink2(dirp, fname, flen); ++ if( err == -EOPNOTSUPP || !dirp->i_op->unlink2) ++ err = vfs_unlink(dirp, rdentry); ++ } + } else { /* It's RMDIR */ +- err = vfs_rmdir(dirp, rdentry); ++ if (dirp->i_op->rmdir2) ++ err = rmdir2(dirp, fname, flen); ++ if( err == -EOPNOTSUPP || !dirp->i_op->rmdir2) ++ err = vfs_rmdir(dirp, rdentry); + } + + dput(rdentry); +diff -urN linux/include/linux/fs.h linux_n/include/linux/fs.h +--- linux/include/linux/fs.h 2003-06-18 21:39:14.000000000 +0530 ++++ linux_n/include/linux/fs.h 2003-06-18 21:39:53.000000000 +0530 +@@ -1407,6 +1407,7 @@ + extern void path_release(struct nameidata *); + extern int follow_down(struct vfsmount **, struct dentry **); + extern int follow_up(struct vfsmount **, struct dentry **); ++extern struct dentry * lookup_one_len_it(const char *, struct dentry *, int, struct lookup_intent *); + extern struct dentry * lookup_one_len(const char *, struct dentry *, int); + extern struct dentry * lookup_hash(struct qstr *, struct dentry *); + #define user_path_walk(name,nd) __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd) +@@ -1421,6 +1422,7 @@ + extern ino_t iunique(struct super_block *, ino_t); + + typedef int (*find_inode_t)(struct inode *, unsigned long, void *); ++extern struct inode * search_icache_for_lustre(struct super_block *, unsigned long); + extern struct inode * iget4(struct super_block *, unsigned long, find_inode_t, void *); + static inline struct inode *iget(struct super_block *sb, unsigned long ino) + { +diff -urN linux/kernel/ksyms.c linux_n/kernel/ksyms.c +--- linux/kernel/ksyms.c 2003-06-18 21:39:13.000000000 +0530 ++++ linux_n/kernel/ksyms.c 2003-06-18 21:39:53.000000000 +0530 +@@ -154,6 +154,7 @@ + EXPORT_SYMBOL(fget); + EXPORT_SYMBOL(igrab); + EXPORT_SYMBOL(iunique); ++EXPORT_SYMBOL(search_icache_for_lustre); + EXPORT_SYMBOL(iget4); + EXPORT_SYMBOL(iput); + EXPORT_SYMBOL(inode_init_once); +@@ -165,6 +166,7 @@ + EXPORT_SYMBOL(path_walk); + EXPORT_SYMBOL(path_release); + EXPORT_SYMBOL(__user_walk); ++EXPORT_SYMBOL(lookup_one_len_it); + EXPORT_SYMBOL(lookup_one_len); + EXPORT_SYMBOL(lookup_hash); + EXPORT_SYMBOL(sys_close);