From b191d0b1a44458bb3ecebb0096fb3d373c500e21 Mon Sep 17 00:00:00 2001 From: pschwan Date: Fri, 6 Dec 2002 10:11:13 +0000 Subject: [PATCH] merge b_md into HEAD: - lfind did not preserve OST order in output (443) - symlinks cause hung clients, incorrect data (439) - stop dereferencing request after dropping refcount (457) - don't LASSERT(spin_is_locked) on non-SMP (455) - fixes for many rename() bugs --- lustre/ChangeLog | 5 + lustre/include/linux/lustre_lite.h | 2 + lustre/include/linux/lustre_net.h | 10 +- lustre/llite/dcache.c | 21 +- lustre/llite/file.c | 45 +- lustre/llite/namei.c | 5 +- lustre/llite/rw.c | 2 +- lustre/llite/symlink.c | 2 +- lustre/mdc/mdc_request.c | 4 +- lustre/mds/handler.c | 19 +- lustre/mds/mds_ext3.c | 8 +- lustre/mds/mds_extN.c | 8 +- lustre/mds/mds_reint.c | 24 +- lustre/obdclass/class_obd.c | 2 +- lustre/obdfilter/filter.c | 19 +- lustre/osc/osc_request.c | 6 +- lustre/patches/patch-2.4.18-14 | 1496 ++++++++++---------- lustre/patches/patch-2.4.18-hp1_pnnl18.2.8qsnet | 1673 +++++++++++++++++++++++ lustre/patches/patch-2.4.18-um | 11 + lustre/ptlrpc/client.c | 7 +- lustre/ptlrpc/service.c | 1 + lustre/tests/Makefile.am | 4 +- lustre/tests/fsx.c | 88 +- lustre/tests/llmount2-hackcleanup.sh | 21 + lustre/tests/local.sh | 6 +- lustre/tests/local2-hack.xml | 43 + lustre/tests/multifstat.c | 62 + lustre/tests/sanity.sh | 105 +- lustre/tests/sanityN.sh | 63 + lustre/tests/setuid.c | 27 - lustre/utils/lconf | 9 +- lustre/utils/lfind.c | 36 +- 32 files changed, 2939 insertions(+), 895 deletions(-) create mode 100644 lustre/patches/patch-2.4.18-hp1_pnnl18.2.8qsnet create mode 100644 lustre/tests/llmount2-hackcleanup.sh create mode 100644 lustre/tests/local2-hack.xml create mode 100644 lustre/tests/multifstat.c create mode 100644 lustre/tests/sanityN.sh delete mode 100644 lustre/tests/setuid.c diff --git a/lustre/ChangeLog b/lustre/ChangeLog index 45d39ab..bbf73c2 100644 --- a/lustre/ChangeLog +++ b/lustre/ChangeLog @@ -4,6 +4,11 @@ TBA - garbage on read from stripes with failed OSTs (441) - mark OSCs as active before reconnecting during recovery (438) - lov_enqueue and lov_cancel need to handle inactive OSTs (403) + - lfind did not preserve OST order in output (443) + - symlinks cause hung clients, incorrect data (439) + - stop dereferencing request after dropping refcount (457) + - don't LASSERT(spin_is_locked) on non-SMP (455) + - fixes for many rename() bugs 2002-12-02 Andreas Dilger * version v0_5_18 diff --git a/lustre/include/linux/lustre_lite.h b/lustre/include/linux/lustre_lite.h index 4da319d..a965bcb 100644 --- a/lustre/include/linux/lustre_lite.h +++ b/lustre/include/linux/lustre_lite.h @@ -210,6 +210,8 @@ do { \ up(&ll_d2d(de)->lld_it_sem); \ } while(0) +/* dcache.c */ +int ll_have_md_lock(struct dentry *de); /* dir.c */ extern struct file_operations ll_dir_operations; diff --git a/lustre/include/linux/lustre_net.h b/lustre/include/linux/lustre_net.h index 5c2ba75..e539d8e 100644 --- a/lustre/include/linux/lustre_net.h +++ b/lustre/include/linux/lustre_net.h @@ -48,20 +48,20 @@ #define LDLM_NUM_THREADS 4 #define LDLM_NEVENTS 1024 -#define LDLM_NBUFS 10 -#define LDLM_BUFSIZE (64 * 1024) +#define LDLM_NBUFS 20 +#define LDLM_BUFSIZE (32 * 1024) #define LDLM_MAXREQSIZE 1024 #define MDT_NUM_THREADS 8 #define MDS_NEVENTS 1024 -#define MDS_NBUFS 10 -#define MDS_BUFSIZE (64 * 1024) +#define MDS_NBUFS 20 +#define MDS_BUFSIZE (32 * 1024) #define MDS_MAXREQSIZE 1024 #define OST_NUM_THREADS 6 #define OST_NEVENTS min(num_physpages / 16, 32768UL) #define OST_NBUFS min(OST_NEVENTS / 128, 256UL) -#define OST_BUFSIZE ((OST_NEVENTS > 4096UL ? 128 : 64) * 1024) +#define OST_BUFSIZE ((OST_NEVENTS > 4096UL ? 128 : 32) * 1024) #define OST_MAXREQSIZE (8 * 1024) #define CONN_INVALID 1 diff --git a/lustre/llite/dcache.c b/lustre/llite/dcache.c index 9a12fd5..a9d4aac 100644 --- a/lustre/llite/dcache.c +++ b/lustre/llite/dcache.c @@ -47,14 +47,6 @@ void ll_intent_release(struct dentry *de, struct lookup_intent *it) struct lustre_handle *handle; ENTRY; - /* XXX the check for RENAME2 is a workaround for old kernels - which call intent_release twice in rename - */ - if (it == NULL || it->it_op == IT_RENAME2) { - EXIT; - return; - } - LASSERT(ll_d2d(de) != NULL); if (it->it_lock_mode) { @@ -74,7 +66,7 @@ void ll_intent_release(struct dentry *de, struct lookup_intent *it) } if (!de->d_it || it->it_op == IT_RELEASED_MAGIC) { - EXIT; + EXIT; return; } @@ -86,9 +78,9 @@ void ll_intent_release(struct dentry *de, struct lookup_intent *it) extern struct dentry *ll_find_alias(struct inode *, struct dentry *); -static int revalidate2_finish(int flag, struct ptlrpc_request *request, +static int revalidate2_finish(int flag, struct ptlrpc_request *request, struct dentry **de, - struct lookup_intent *it, + struct lookup_intent *it, int offset, obd_id ino) { ldlm_lock_set_data((struct lustre_handle *)it->it_lock_handle, @@ -97,7 +89,7 @@ static int revalidate2_finish(int flag, struct ptlrpc_request *request, return 0; } -static int ll_have_lock(struct dentry *de) +int ll_have_md_lock(struct dentry *de) { struct ll_sb_info *sbi = ll_s2sbi(de->d_sb); struct lustre_handle lockh; @@ -141,15 +133,12 @@ int ll_revalidate2(struct dentry *de, int flags, struct lookup_intent *it) RETURN(0); } -// if (it == NULL && ll_have_lock(de)) -// RETURN(1); - rc = ll_intent_lock(de->d_parent->d_inode, &de, it, revalidate2_finish); if (rc < 0) { /* Something bad happened; overwrite it_status? */ CERROR("ll_intent_lock: %d\n", rc); } - /* unfortunately ll_intent_lock may cause a callback and revoke our + /* unfortunately ll_intent_lock may cause a callback and revoke our dentry */ spin_lock(&dcache_lock); list_del_init(&de->d_hash); diff --git a/lustre/llite/file.c b/lustre/llite/file.c index a67b023..3d343a0 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -419,7 +419,7 @@ int ll_lock_callback(struct ldlm_lock *lock, struct ldlm_lock_desc *new, CERROR("ldlm_cli_cancel failed: %d\n", rc); break; case LDLM_CB_CANCELING: - CDEBUG(D_INODE, "invalidating obdo/inode %ld\n", inode->i_ino); + CDEBUG(D_INODE, "invalidating obdo/inode %lu\n", inode->i_ino); /* FIXME: do something better than throwing away everything */ //down(&inode->i_sem); ll_invalidate_inode_pages(inode); @@ -462,7 +462,7 @@ static ssize_t ll_file_read(struct file *filp, char *buf, size_t count, extent.start = *ppos; extent.end = *ppos + count; - CDEBUG(D_INFO, "Locking inode %ld, start "LPU64" end "LPU64"\n", + CDEBUG(D_INFO, "Locking inode %lu, start "LPU64" end "LPU64"\n", inode->i_ino, extent.start, extent.end); err = obd_enqueue(&sbi->ll_osc_conn, lsm, NULL, LDLM_EXTENT, @@ -476,7 +476,7 @@ static ssize_t ll_file_read(struct file *filp, char *buf, size_t count, } } - CDEBUG(D_INFO, "Reading inode %ld, %d bytes, offset %Ld\n", + CDEBUG(D_INFO, "Reading inode %lu, %d bytes, offset %Ld\n", inode->i_ino, count, *ppos); retval = generic_file_read(filp, buf, count, ppos); @@ -550,7 +550,7 @@ ll_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos) GOTO(out_eof, retval = -ENOMEM); extent.start = *ppos; extent.end = *ppos + count; - CDEBUG(D_INFO, "Locking inode %ld, start "LPU64" end "LPU64"\n", + CDEBUG(D_INFO, "Locking inode %lu, start "LPU64" end "LPU64"\n", inode->i_ino, extent.start, extent.end); err = obd_enqueue(&sbi->ll_osc_conn, lsm, NULL, LDLM_EXTENT, @@ -563,7 +563,7 @@ ll_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos) } } - CDEBUG(D_INFO, "Writing inode %ld, %ld bytes, offset "LPD64"\n", + CDEBUG(D_INFO, "Writing inode %lu, %ld bytes, offset "LPD64"\n", inode->i_ino, (long)count, *ppos); retval = generic_file_write(file, buf, count, ppos); @@ -621,12 +621,12 @@ static int ll_lov_setstripe(struct inode *inode, struct file *file, down(&lli->lli_open_sem); if (lli->lli_smd) { - CERROR("striping data already set for %d\n", inode->i_ino); + CERROR("striping data already set for %lu\n", inode->i_ino); GOTO(out_lov_up, rc = -EPERM); } rc = obd_unpackmd(conn, &lli->lli_smd, lmm); if (rc < 0) { - CERROR("error setting LOV striping on %d: rc = %d\n", + CERROR("error setting LOV striping on %lu: rc = %d\n", inode->i_ino, rc); GOTO(out_lov_up, rc); } @@ -804,8 +804,37 @@ static int ll_inode_revalidate(struct dentry *dentry) struct lov_stripe_md *lsm; ENTRY; - if (!inode) + if (!inode) { + CERROR("REPORT THIS LINE TO PETER\n"); RETURN(0); + } + + if (! ll_have_md_lock(dentry)) { + struct ptlrpc_request *req; + struct ll_sb_info *sbi = ll_i2sbi(dentry->d_inode); + struct mds_body *body; + int rc, datalen, valid; + + if (S_ISREG(inode->i_mode)) { + datalen = obd_size_wiremd(&sbi->ll_osc_conn, NULL); + valid |= OBD_MD_FLEASIZE; + } + rc = mdc_getattr(&sbi->ll_mdc_conn, + inode->i_ino, + inode->i_mode, valid, + datalen, &req); + if (rc) { + CERROR("failure %d inode "LPX64"\n", rc, inode->i_ino); + ptlrpc_req_finished(req); + RETURN(-abs(rc)); + } + + body = lustre_msg_buf(req->rq_repmsg, 0); + ll_update_inode(inode, body); + ptlrpc_req_finished(req); + } + + lsm = ll_i2info(inode)->lli_smd; if (!lsm) /* object not yet allocated, don't validate size */ diff --git a/lustre/llite/namei.c b/lustre/llite/namei.c index 9670af0..00a6aac 100644 --- a/lustre/llite/namei.c +++ b/lustre/llite/namei.c @@ -357,7 +357,8 @@ int ll_intent_lock(struct inode *parent, struct dentry **de, * always needed... */ if ( // it->it_status == 0 && - it->it_op != IT_RENAME2 && + it->it_op != IT_RENAME && + it->it_op != IT_LINK && it->it_op != IT_SETATTR && it->it_op != IT_GETATTR && it->it_op != IT_READDIR && @@ -892,7 +893,7 @@ static int ll_rename(struct inode * old_dir, struct dentry * old_dentry, struct page * old_page; int err; - LL_GET_INTENT(old_dentry, it); + LL_GET_INTENT(new_dentry, it); if (it && it->it_disposition) { if (tgt_inode) { diff --git a/lustre/llite/rw.c b/lustre/llite/rw.c index 095c145..ee1631e 100644 --- a/lustre/llite/rw.c +++ b/lustre/llite/rw.c @@ -189,7 +189,7 @@ void ll_truncate(struct inode *inode) OBD_OBJECT_EOF); if (err) { LBUG(); - CERROR("obd_truncate fails (%d) ino %ld\n", err, + CERROR("obd_truncate fails (%d) ino %lu\n", err, inode->i_ino); } else obdo_to_inode(inode, &oa, oa.o_valid); diff --git a/lustre/llite/symlink.c b/lustre/llite/symlink.c index 93a4bdb..a89ca2a 100644 --- a/lustre/llite/symlink.c +++ b/lustre/llite/symlink.c @@ -46,7 +46,7 @@ static int ll_readlink_internal(struct inode *inode, rc = mdc_getattr(&sbi->ll_mdc_conn, inode->i_ino, S_IFLNK, OBD_MD_LINKNAME, symlen, request); if (rc) { - CERROR("inode "LPD64": rc = %d\n", inode->i_ino, rc); + CERROR("inode %lu: rc = %d\n", inode->i_ino, rc); RETURN(rc); } diff --git a/lustre/mdc/mdc_request.c b/lustre/mdc/mdc_request.c index 79b07ba..f8a5f0f 100644 --- a/lustre/mdc/mdc_request.c +++ b/lustre/mdc/mdc_request.c @@ -197,7 +197,7 @@ static int mdc_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc, LASSERT(data_len == sizeof(*inode)); if (S_ISDIR(inode->i_mode)) { - CDEBUG(D_INODE, "invalidating inode %ld\n", + CDEBUG(D_INODE, "invalidating inode %lu\n", inode->i_ino); ll_invalidate_inode_pages(inode); @@ -248,7 +248,7 @@ int mdc_enqueue(struct lustre_handle *conn, int lock_type, struct ldlm_request *lockreq; ENTRY; - LDLM_DEBUG_NOLOCK("mdsintent %s parent dir %ld", + LDLM_DEBUG_NOLOCK("mdsintent %s parent dir %lu", ldlm_it2str(it->it_op), dir->i_ino); if (it->it_op & (IT_MKDIR | IT_CREAT | IT_SYMLINK | IT_MKNOD)) { diff --git a/lustre/mds/handler.c b/lustre/mds/handler.c index ee12652..393b793 100644 --- a/lustre/mds/handler.c +++ b/lustre/mds/handler.c @@ -576,7 +576,7 @@ int mds_pack_md(struct mds_obd *mds, struct ptlrpc_request *req, int rc; if (lmm_size == 0) { - CDEBUG(D_INFO, "no space reserved for inode %u MD\n", inode->i_ino); + CDEBUG(D_INFO, "no space reserved for inode %lu MD\n", inode->i_ino); RETURN(0); } @@ -587,7 +587,7 @@ int mds_pack_md(struct mds_obd *mds, struct ptlrpc_request *req, * to reserve for the MD, this shouldn't be fatal either... */ if (lmm_size > mds->mds_max_mdsize) { - CERROR("Reading MD for inode %u of %d bytes > max %d\n", + CERROR("Reading MD for inode %lu of %d bytes > max %d\n", inode->i_ino, lmm_size, mds->mds_max_mdsize); // RETURN(-EINVAL); } @@ -597,7 +597,7 @@ int mds_pack_md(struct mds_obd *mds, struct ptlrpc_request *req, * size itself from the ost count. */ if ((rc = mds_fs_get_md(mds, inode, lmm, lmm_size)) < 0) { - CDEBUG(D_INFO, "No md for ino %u: rc = %d\n", inode->i_ino, rc); + CDEBUG(D_INFO, "No md for ino %lu: rc = %d\n", inode->i_ino, rc); } else if (rc > 0) { body->valid |= OBD_MD_FLEASIZE; rc = 0; @@ -635,6 +635,7 @@ static int mds_getattr_internal(struct mds_obd *mds, struct dentry *dentry, } else { CDEBUG(D_INODE, "read symlink dest %s\n", symname); body->valid |= OBD_MD_LINKNAME; + rc = 0; } } RETURN(rc); @@ -679,7 +680,7 @@ static int mds_getattr_name(int offset, struct ptlrpc_request *req) } dir = de->d_inode; - CDEBUG(D_INODE, "parent ino %ld, name %*s\n", dir->i_ino,namelen,name); + CDEBUG(D_INODE, "parent ino %lu, name %*s\n", dir->i_ino,namelen,name); lock_mode = LCK_PR; res_id[0] = dir->i_ino; @@ -748,11 +749,11 @@ static int mds_getattr(int offset, struct ptlrpc_request *req) inode = de->d_inode; if (S_ISREG(body->fid1.f_type)) { int rc = mds_fs_get_md(mds, inode, NULL, 0); - CDEBUG(D_INODE, "got %d bytes MD data for inode %u\n", + CDEBUG(D_INODE, "got %d bytes MD data for inode %lu\n", rc, inode->i_ino); if (rc < 0) { if (rc != -ENODATA) - CERROR("error getting inode %u MD: rc = %d\n", + CERROR("error getting inode %lu MD: rc = %d\n", inode->i_ino, rc); size[bufcount] = 0; } else if (rc > mds->mds_max_mdsize) { @@ -853,12 +854,12 @@ static int mds_store_md(struct mds_obd *mds, struct ptlrpc_request *req, * MD request. */ if (lmm_size > mds->mds_max_mdsize) { - CERROR("Saving MD for inode %u of %d bytes > max %d\n", + CERROR("Saving MD for inode %lu of %d bytes > max %d\n", inode->i_ino, lmm_size, mds->mds_max_mdsize); //RETURN(-EINVAL); } - CDEBUG(D_INODE, "storing %d bytes MD for inode %u\n", + CDEBUG(D_INODE, "storing %d bytes MD for inode %lu\n", lmm_size, inode->i_ino); uc.ouc_fsuid = body->fsuid; uc.ouc_fsgid = body->fsgid; @@ -1048,7 +1049,7 @@ static int mds_readpage(struct ptlrpc_request *req) if (IS_ERR(de)) GOTO(out_pop, rc = PTR_ERR(de)); - CDEBUG(D_INODE, "ino %ld\n", de->d_inode->i_ino); + CDEBUG(D_INODE, "ino %lu\n", de->d_inode->i_ino); file = dentry_open(de, mnt, O_RDONLY | O_LARGEFILE); /* note: in case of an error, dentry_open puts dentry */ diff --git a/lustre/mds/mds_ext3.c b/lustre/mds/mds_ext3.c index 4fb5756..7dede30 100644 --- a/lustre/mds/mds_ext3.c +++ b/lustre/mds/mds_ext3.c @@ -138,7 +138,7 @@ static int mds_ext3_set_md(struct inode *inode, void *handle, up(&inode->i_sem); if (rc) { - CERROR("error adding objectid "LPX64" to inode %ld: %d\n", + CERROR("error adding objectid "LPX64" to inode %lu: %d\n", lmm->lmm_object_id, inode->i_ino, rc); if (rc != -ENOSPC) LBUG(); } @@ -161,7 +161,7 @@ static int mds_ext3_get_md(struct inode *inode, struct lov_mds_md *lmm,int size) return (rc == -ENODATA) ? 0 : rc; if (rc < 0) { - CDEBUG(D_INFO, "error getting EA %s from MDS inode %ld: " + CDEBUG(D_INFO, "error getting EA %s from MDS inode %lu: " "rc = %d\n", XATTR_LUSTRE_MDS_OBJID, inode->i_ino, rc); memset(lmm, 0, size); return (rc == -ENODATA) ? 0 : rc; @@ -212,13 +212,13 @@ static void mds_ext3_delete_inode(struct inode *inode) return; } if (mds_ext3_set_md(inode, handle, NULL, 0)) - CERROR("error clearing objid on %ld\n", inode->i_ino); + CERROR("error clearing objid on %lu\n", inode->i_ino); if (mds_ext3_fs_ops.cl_delete_inode) mds_ext3_fs_ops.cl_delete_inode(inode); if (mds_ext3_commit(inode, handle)) - CERROR("error closing handle on %ld\n", inode->i_ino); + CERROR("error closing handle on %lu\n", inode->i_ino); } else mds_ext3_fs_ops.cl_delete_inode(inode); } diff --git a/lustre/mds/mds_extN.c b/lustre/mds/mds_extN.c index 8368573..4091f8d 100644 --- a/lustre/mds/mds_extN.c +++ b/lustre/mds/mds_extN.c @@ -137,7 +137,7 @@ static int mds_extN_set_md(struct inode *inode, void *handle, up(&inode->i_sem); if (rc) { - CERROR("error adding objectid "LPX64" to inode %ld: %d\n", + CERROR("error adding objectid "LPX64" to inode %lu: rc = %d\n", lmm->lmm_object_id, inode->i_ino, rc); if (rc != -ENOSPC) LBUG(); } @@ -160,7 +160,7 @@ static int mds_extN_get_md(struct inode *inode, struct lov_mds_md *lmm,int size) return (rc == -ENODATA) ? 0 : rc; if (rc < 0) { - CDEBUG(D_INFO, "error getting EA %s from MDS inode %ld: " + CDEBUG(D_INFO, "error getting EA %s from MDS inode %lu: " "rc = %d\n", XATTR_LUSTRE_MDS_OBJID, inode->i_ino, rc); memset(lmm, 0, size); return (rc == -ENODATA) ? 0 : rc; @@ -211,13 +211,13 @@ static void mds_extN_delete_inode(struct inode *inode) return; } if (mds_extN_set_md(inode, handle, NULL, 0)) - CERROR("error clearing objid on %ld\n", inode->i_ino); + CERROR("error clearing objid on %lu\n", inode->i_ino); if (mds_extN_fs_ops.cl_delete_inode) mds_extN_fs_ops.cl_delete_inode(inode); if (mds_extN_commit(inode, handle)) - CERROR("error closing handle on %ld\n", inode->i_ino); + CERROR("error closing handle on %lu\n", inode->i_ino); } else mds_extN_fs_ops.cl_delete_inode(inode); } diff --git a/lustre/mds/mds_reint.c b/lustre/mds/mds_reint.c index 5ac6e6e..ca34445 100644 --- a/lustre/mds/mds_reint.c +++ b/lustre/mds/mds_reint.c @@ -138,7 +138,7 @@ static int mds_reint_setattr(struct mds_update_record *rec, int offset, } } inode = de->d_inode; - CDEBUG(D_INODE, "ino %ld\n", inode->i_ino); + CDEBUG(D_INODE, "ino %lu\n", inode->i_ino); OBD_FAIL_WRITE(OBD_FAIL_MDS_REINT_SETATTR_WRITE, to_kdev_t(inode->i_sb->s_dev)); @@ -208,7 +208,7 @@ static int mds_reint_create(struct mds_update_record *rec, int offset, GOTO(out_create, rc); } dir = de->d_inode; - CDEBUG(D_INODE, "parent ino %ld name %s mode %o\n", + CDEBUG(D_INODE, "parent ino %lu name %s mode %o\n", dir->i_ino, rec->ur_name, rec->ur_mode); ldlm_lock_dump((void *)(unsigned long)lockh.addr); @@ -225,7 +225,7 @@ static int mds_reint_create(struct mds_update_record *rec, int offset, struct mds_body *body; struct inode *inode = dchild->d_inode; - CDEBUG(D_INODE, "child exists (dir %ld, name %s, ino %ld)\n", + CDEBUG(D_INODE, "child exists (dir %lu, name %s, ino %lu)\n", dir->i_ino, rec->ur_name, dchild->d_inode->i_ino); /* XXX check that mode is correct? */ @@ -283,7 +283,7 @@ static int mds_reint_create(struct mds_update_record *rec, int offset, handle = mds_fs_start(mds, dir, MDS_FSOP_SYMLINK); if (IS_ERR(handle)) GOTO(out_transno_dchild, rc = PTR_ERR(handle)); - rc = vfs_symlink(dir, dchild, rec->ur_name); + rc = vfs_symlink(dir, dchild, rec->ur_tgt); EXIT; break; } @@ -325,10 +325,10 @@ static int mds_reint_create(struct mds_update_record *rec, int offset, LASSERT(rec->ur_opcode & REINT_REPLAYING); inode->i_generation = rec->ur_fid2->generation; /* Dirtied and committed by the upcoming setattr. */ - CDEBUG(D_INODE, "recreated ino %ld with gen %ld\n", + CDEBUG(D_INODE, "recreated ino %lu with gen %lu\n", inode->i_ino, inode->i_generation); } else { - CDEBUG(D_INODE, "created ino %ld\n", inode->i_ino); + CDEBUG(D_INODE, "created ino %lu\n", inode->i_ino); } rc = mds_fs_setattr(mds, dchild, handle, &iattr); @@ -433,17 +433,17 @@ static int mds_reint_unlink(struct mds_update_record *rec, int offset, dir = de->d_inode; inode = dchild->d_inode; - CDEBUG(D_INODE, "parent ino %ld\n", dir->i_ino); + CDEBUG(D_INODE, "parent ino %lu\n", dir->i_ino); if (!inode) { if (rec->ur_opcode & REINT_REPLAYING) { CDEBUG(D_INODE, - "child missing (%ld/%s); OK for REPLAYING\n", + "child missing (%lu/%s); OK for REPLAYING\n", dir->i_ino, rec->ur_name); rc = 0; } else { CDEBUG(D_INODE, - "child doesn't exist (dir %ld, name %s)\n", + "child doesn't exist (dir %lu, name %s)\n", dir->i_ino, rec->ur_name); rc = -ENOENT; } @@ -612,11 +612,11 @@ static int mds_reint_link(struct mds_update_record *rec, int offset, /* XXX verify that the link is to the the right file? */ rc = 0; CDEBUG(D_INODE, - "child exists (dir %ld, name %s) (REPLAYING)\n", + "child exists (dir %lu, name %s) (REPLAYING)\n", de_tgt_dir->d_inode->i_ino, rec->ur_name); } else { rc = -EEXIST; - CERROR("child exists (dir %ld, name %s)\n", + CERROR("child exists (dir %lu, name %s)\n", de_tgt_dir->d_inode->i_ino, rec->ur_name); } GOTO(out_link_dchild, rc); @@ -799,7 +799,7 @@ out_rename_deold: mds_blocking_ast, NULL, 0, &oldhandle); if (rc) CERROR("failed to get child inode lock (child ino " - LPD64" dir ino %ld)\n", + LPD64" dir ino %lu)\n", res_id[0], de_old->d_inode->i_ino); } diff --git a/lustre/obdclass/class_obd.c b/lustre/obdclass/class_obd.c index 32e8c08..420a3fb 100644 --- a/lustre/obdclass/class_obd.c +++ b/lustre/obdclass/class_obd.c @@ -703,7 +703,7 @@ static void __exit cleanup_obdclass(void) /* Check that we're building against the appropriate version of the Lustre * kernel patch */ #include -#if (LUSTRE_KERNEL_VERSION != 3) +#if (LUSTRE_KERNEL_VERSION != 4) # error Cannot continue: Your Lustre kernel patch is out of date #endif diff --git a/lustre/obdfilter/filter.c b/lustre/obdfilter/filter.c index 76d21cc..31047b5 100644 --- a/lustre/obdfilter/filter.c +++ b/lustre/obdfilter/filter.c @@ -659,8 +659,8 @@ static void filter_from_inode(struct obdo *oa, struct inode *inode, int valid) int type = oa->o_mode & S_IFMT; ENTRY; - CDEBUG(D_INFO, "src inode %ld (%p), dst obdo %ld valid 0x%08x\n", - inode->i_ino, inode, (long)oa->o_id, valid); + CDEBUG(D_INFO, "src inode %lu (%p), dst obdo "LPX64" valid 0x%08x\n", + inode->i_ino, inode, oa->o_id, valid); /* Don't copy the inode number in place of the object ID */ obdo_from_inode(oa, inode, valid); oa->o_mode &= ~S_IFMT; @@ -998,9 +998,9 @@ static int filter_pgcache_brw(int cmd, struct lustre_handle *conn, /* count doubles as retval */ for (pg = 0; pg < oa_bufs; pg++) { - CDEBUG(D_INODE, "OP %d obdo pgno: (%d) (%ld,"LPU64 + CDEBUG(D_INODE, "OP %d inode %lu pgno: (%d) "LPU64 ") off count ("LPU64",%d)\n", - cmd, pnum, file->f_dentry->d_inode->i_ino, + cmd, file->f_dentry->d_inode->i_ino, pnum, pga[pnum].off >> PAGE_CACHE_SHIFT, pga[pnum].off, (int)pga[pnum].count); if (cmd & OBD_BRW_WRITE) { @@ -1354,7 +1354,7 @@ struct page *filter_get_page_write(struct inode *inode, */ if (!page) { unsigned long addr; - CDEBUG(D_PAGE, "ino %ld page %ld locked\n", inode->i_ino,index); + CDEBUG(D_PAGE, "ino %lu page %ld locked\n", inode->i_ino,index); addr = __get_free_pages(GFP_KERNEL, 0); /* locked page */ if (!addr) { CERROR("no memory for a temp page\n"); @@ -1418,8 +1418,8 @@ static int filter_commit_write(struct page *page, unsigned from, unsigned to, void *addr = page_address(page); /* debugging: just seeing if this ever happens */ - CERROR("called filter_commit_write for obj %ld:%ld on err %d\n", - page->index, page->mapping->host->i_ino, err); + CERROR("called filter_commit_write for ino %lu:%lu on err %d\n", + page->mapping->host->i_ino, page->index, err); /* Currently one buffer per page, but in the future... */ for (bh = head, block_start = 0; bh != head || !block_start; @@ -1470,12 +1470,17 @@ static int filter_preprw(int cmd, struct lustre_handle *conn, obd_kmap_get(niocount, 1); for (i = 0; i < objcount; i++, o++) { + struct filter_dentry_data *fdd; struct dentry *dentry; struct inode *inode; int j; dentry = filter_fid2dentry(obd, filter_parent(obd, S_IFREG), o->ioo_id, S_IFREG, 0); + + if (!(fdd = dentry->d_fsdata) || !atomic_read(&fdd->fdd_open_count)) + CERROR("I/O to unopened object "LPX64"\n", o->ioo_id); + if (IS_ERR(dentry)) GOTO(out_clean, rc = PTR_ERR(dentry)); inode = dentry->d_inode; diff --git a/lustre/osc/osc_request.c b/lustre/osc/osc_request.c index de403b5..2412435 100644 --- a/lustre/osc/osc_request.c +++ b/lustre/osc/osc_request.c @@ -67,6 +67,7 @@ static int osc_packmd(struct lustre_handle *conn, struct lov_mds_md **lmmp, struct lov_stripe_md *lsm) { int lmm_size; + ENTRY; lmm_size = sizeof(**lmmp); if (!lmmp) @@ -88,13 +89,14 @@ static int osc_packmd(struct lustre_handle *conn, struct lov_mds_md **lmmp, (*lmmp)->lmm_object_id = (lsm->lsm_object_id); } - return lmm_size; + RETURN(lmm_size); } static int osc_unpackmd(struct lustre_handle *conn, struct lov_stripe_md **lsmp, struct lov_mds_md *lmm) { int lsm_size; + ENTRY; lsm_size = sizeof(**lsmp); if (!lsmp) @@ -118,7 +120,7 @@ static int osc_unpackmd(struct lustre_handle *conn, struct lov_stripe_md **lsmp, LASSERT((*lsmp)->lsm_object_id); } - return lsm_size; + RETURN(lsm_size); } static int osc_getattr(struct lustre_handle *conn, struct obdo *oa, diff --git a/lustre/patches/patch-2.4.18-14 b/lustre/patches/patch-2.4.18-14 index e563f7b..78fa7db 100644 --- a/lustre/patches/patch-2.4.18-14 +++ b/lustre/patches/patch-2.4.18-14 @@ -1,743 +1,428 @@ ---- linux-2.4.18-17.8.0-uml-pristine/include/linux/lustre_version.h Wed Dec 31 19:00:00 1969 -+++ linux-2.4.18-17.8.0-uml/include/linux/lustre_version.h Tue Nov 26 07:02:14 2002 -@@ -0,0 +1 @@ -+#define LUSTRE_KERNEL_VERSION 3 ---- linux-2.4.18-17.8.0-uml-pristine/arch/ia64/mm/init.c 2002-10-19 11:44:08.000000000 -0600 -+++ linux-2.4.18-17.8.0-uml/arch/ia64/mm/init.c 2002-10-19 11:44:51.000000000 -0600 -@@ -37,6 +37,12 @@ - - static unsigned long totalram_pages; +--- lum/fs/namei.c~lustre 2002-12-04 01:39:11.000000000 -0700 ++++ lum-root/fs/namei.c 2002-12-04 01:39:12.000000000 -0700 +@@ -1,3 +1,6 @@ ++ ++ ++ + /* + * linux/fs/namei.c + * +@@ -94,6 +97,14 @@ + * XEmacs seems to be relying on it... + */ -+struct page *check_get_page(unsigned long kaddr) ++void intent_release(struct dentry *de, struct lookup_intent *it) +{ -+#warning FIXME: Lustre team, is this solid? -+ return virt_to_page(kaddr); ++ if (it && de->d_op && de->d_op->d_intent_release) ++ de->d_op->d_intent_release(de, it); ++ +} + - int - do_check_pgt_cache (int low, int high) ++ + /* In order to reduce some races, while at the same time doing additional + * checking and hopefully speeding things up, we copy filenames to the + * kernel data space before using them.. +@@ -260,10 +271,19 @@ void path_release(struct nameidata *nd) + * Internal lookup() using the new generic dcache. + * SMP-safe + */ +-static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, int flags) ++static struct dentry *cached_lookup(struct dentry *parent, struct qstr *name, ++ int flags, struct lookup_intent *it) { ---- linux-2.4.18-17.8.0-uml-pristine/arch/i386/mm/init.c 2002-10-19 11:44:04.000000000 -0600 -+++ linux-2.4.18-17.8.0-uml/arch/i386/mm/init.c 2002-10-19 11:44:51.000000000 -0600 -@@ -43,6 +43,12 @@ - static unsigned long totalram_pages; - static unsigned long totalhigh_pages; + struct dentry * dentry = d_lookup(parent, name); -+struct page *check_get_page(unsigned long kaddr) -+{ -+#warning FIXME: Lustre team, is this solid? -+ return virt_to_page(kaddr); -+} -+ - int do_check_pgt_cache(int low, int high) ++ if (dentry && dentry->d_op && dentry->d_op->d_revalidate2) { ++ if (!dentry->d_op->d_revalidate2(dentry, flags, it) && ++ !d_invalidate(dentry)) { ++ dput(dentry); ++ dentry = NULL; ++ } ++ return dentry; ++ } else + if (dentry && dentry->d_op && dentry->d_op->d_revalidate) { + if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) { + dput(dentry); +@@ -281,7 +301,8 @@ static struct dentry * cached_lookup(str + * make sure that nobody added the entry to the dcache in the meantime.. + * SMP-safe + */ +-static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, int flags) ++static struct dentry *real_lookup(struct dentry *parent, struct qstr *name, ++ int flags, struct lookup_intent *it) { - int freed = 0; ---- linux-2.4.18-17.8.0-uml-pristine/drivers/block/blkpg.c 2002-10-19 11:43:55.000000000 -0600 -+++ linux-2.4.18-17.8.0-uml/drivers/block/blkpg.c 2002-10-19 11:44:51.000000000 -0600 -@@ -297,3 +297,38 @@ + struct dentry * result; + struct inode *dir = parent->d_inode; +@@ -300,6 +321,9 @@ static struct dentry * real_lookup(struc + result = ERR_PTR(-ENOMEM); + if (dentry) { + lock_kernel(); ++ if (dir->i_op->lookup2) ++ result = dir->i_op->lookup2(dir, dentry, it); ++ else + result = dir->i_op->lookup(dir, dentry); + unlock_kernel(); + if (result) +@@ -321,6 +345,12 @@ static struct dentry * real_lookup(struc + dput(result); + result = ERR_PTR(-ENOENT); + } ++ } else if (result->d_op && result->d_op->d_revalidate2) { ++ if (!result->d_op->d_revalidate2(result, flags, it) && ++ !d_invalidate(result)) { ++ dput(result); ++ result = ERR_PTR(-ENOENT); ++ } + } + return result; + } +@@ -334,7 +364,8 @@ int max_recursive_link = 5; + * Without that kind of total limit, nasty chains of consecutive + * symlinks can cause almost arbitrarily long lookups. + */ +-static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd) ++static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd, ++ struct lookup_intent *it) + { + int err; + if (current->link_count >= max_recursive_link) +@@ -348,10 +379,14 @@ static inline int do_follow_link(struct + current->link_count++; + current->total_link_count++; + UPDATE_ATIME(dentry->d_inode); +- err = dentry->d_inode->i_op->follow_link(dentry, nd); ++ if (dentry->d_inode->i_op->follow_link2) ++ err = dentry->d_inode->i_op->follow_link2(dentry, nd, it); ++ else ++ err = dentry->d_inode->i_op->follow_link(dentry, nd); + current->link_count--; + return err; + loop: ++ intent_release(dentry, it); + path_release(nd); + return -ELOOP; + } +@@ -449,7 +484,8 @@ static inline void follow_dotdot(struct + * + * We expect 'base' to be positive and a directory. + */ +-int link_path_walk(const char * name, struct nameidata *nd) ++int link_path_walk_it(const char *name, struct nameidata *nd, ++ struct lookup_intent *it) + { + struct dentry *dentry; + struct inode *inode; +@@ -526,12 +562,12 @@ int link_path_walk(const char * name, st + break; + } + /* This does the actual lookups.. */ +- dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE); ++ dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE, NULL); + if (!dentry) { + err = -EWOULDBLOCKIO; + if (atomic) + break; +- dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE); ++ dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE, NULL); + err = PTR_ERR(dentry); + if (IS_ERR(dentry)) + break; +@@ -548,8 +584,8 @@ int link_path_walk(const char * name, st + if (!inode->i_op) + goto out_dput; + +- if (inode->i_op->follow_link) { +- err = do_follow_link(dentry, nd); ++ if (inode->i_op->follow_link || inode->i_op->follow_link2) { ++ err = do_follow_link(dentry, nd, it); + dput(dentry); + if (err) + goto return_err; +@@ -565,7 +601,7 @@ int link_path_walk(const char * name, st + nd->dentry = dentry; + } + err = -ENOTDIR; +- if (!inode->i_op->lookup) ++ if (!inode->i_op->lookup && !inode->i_op->lookup2) + break; + continue; + /* here ends the main loop */ +@@ -592,12 +628,12 @@ last_component: + if (err < 0) + break; + } +- dentry = cached_lookup(nd->dentry, &this, 0); ++ dentry = cached_lookup(nd->dentry, &this, 0, it); + if (!dentry) { + err = -EWOULDBLOCKIO; + if (atomic) + break; +- dentry = real_lookup(nd->dentry, &this, 0); ++ dentry = real_lookup(nd->dentry, &this, 0, it); + err = PTR_ERR(dentry); + if (IS_ERR(dentry)) + break; +@@ -606,8 +642,10 @@ last_component: + ; + inode = dentry->d_inode; + if ((lookup_flags & LOOKUP_FOLLOW) +- && inode && inode->i_op && inode->i_op->follow_link) { +- err = do_follow_link(dentry, nd); ++ && inode && inode->i_op && ++ (inode->i_op->follow_link || ++ inode->i_op->follow_link2)) { ++ err = do_follow_link(dentry, nd, it); + dput(dentry); + if (err) + goto return_err; +@@ -621,7 +659,8 @@ last_component: + goto no_inode; + if (lookup_flags & LOOKUP_DIRECTORY) { + err = -ENOTDIR; +- if (!inode->i_op || !inode->i_op->lookup) ++ if (!inode->i_op || (!inode->i_op->lookup && ++ !inode->i_op->lookup2)) + break; + } + goto return_base; +@@ -663,10 +702,21 @@ return_err: + return err; } - EXPORT_SYMBOL(blk_ioctl); -+ -+#define NUM_DEV_NO_WRITE 16 -+static int dev_no_write[NUM_DEV_NO_WRITE]; -+ -+/* -+ * Debug code for turning block devices "read-only" (will discard writes -+ * silently). This is for filesystem crash/recovery testing. -+ */ -+void dev_set_rdonly(kdev_t dev, int no_write) ++int link_path_walk(const char * name, struct nameidata *nd) +{ -+ if (dev) { -+ printk(KERN_WARNING "Turning device %s read-only\n", -+ bdevname(dev)); -+ dev_no_write[no_write] = 0xdead0000 + dev; -+ } ++ return link_path_walk_it(name, nd, NULL); +} + -+int dev_check_rdonly(kdev_t dev) { -+ int i; -+ -+ for (i = 0; i < NUM_DEV_NO_WRITE; i++) { -+ if ((dev_no_write[i] & 0xffff0000) == 0xdead0000 && -+ dev == (dev_no_write[i] & 0xffff)) -+ return 1; -+ } -+ return 0; ++int path_walk_it(const char * name, struct nameidata *nd, struct lookup_intent *it) ++{ ++ current->total_link_count = 0; ++ return link_path_walk_it(name, nd, it); +} + -+void dev_clear_rdonly(int no_write) { -+ dev_no_write[no_write] = 0; + int path_walk(const char * name, struct nameidata *nd) + { + current->total_link_count = 0; +- return link_path_walk(name, nd); ++ return link_path_walk_it(name, nd, NULL); + } + + /* SMP-safe */ +@@ -751,6 +801,17 @@ walk_init_root(const char *name, struct + } + + /* SMP-safe */ ++int path_lookup_it(const char *path, unsigned flags, struct nameidata *nd, ++ struct lookup_intent *it) ++{ ++ int error = 0; ++ if (path_init(path, flags, nd)) ++ error = path_walk_it(path, nd, it); ++ return error; +} + -+EXPORT_SYMBOL(dev_set_rdonly); -+EXPORT_SYMBOL(dev_check_rdonly); -+EXPORT_SYMBOL(dev_clear_rdonly); ---- linux-2.4.18-17.8.0-uml-pristine/drivers/block/loop.c 2002-10-19 11:43:55.000000000 -0600 -+++ linux-2.4.18-17.8.0-uml/drivers/block/loop.c 2002-10-19 11:44:51.000000000 -0600 -@@ -491,6 +491,11 @@ - spin_unlock_irq(&lo->lo_lock); - - if (rw == WRITE) { -+#ifdef CONFIG_DEV_RDONLY -+ if (dev_check_rdonly(rbh->b_rdev)) -+ goto err; -+#endif + - if (lo->lo_flags & LO_FLAGS_READ_ONLY) - goto err; - } else if (rw == READA) { ---- linux-2.4.18-17.8.0-uml-pristine/drivers/ide/ide-disk.c 2002-10-19 11:43:58.000000000 -0600 -+++ linux-2.4.18-17.8.0-uml/drivers/ide/ide-disk.c 2002-10-19 11:44:51.000000000 -0600 -@@ -557,6 +557,12 @@ ++/* SMP-safe */ + int path_lookup(const char *path, unsigned flags, struct nameidata *nd) + { + int error = 0; +@@ -779,7 +840,8 @@ int path_init(const char *name, unsigned + * needs parent already locked. Doesn't follow mounts. + * SMP-safe. */ - static ide_startstop_t do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block) +-struct dentry * lookup_hash(struct qstr *name, struct dentry * base) ++struct dentry * lookup_hash_it(struct qstr *name, struct dentry * base, ++ struct lookup_intent *it) { -+#ifdef CONFIG_DEV_RDONLY -+ if (rq->cmd == WRITE && dev_check_rdonly(rq->rq_dev)) { -+ ide_end_request(1, HWGROUP(drive)); -+ return ide_stopped; -+ } -+#endif - if (IDE_CONTROL_REG) - OUT_BYTE(drive->ctl,IDE_CONTROL_REG); - ---- linux-2.4.18-17.8.0-uml-pristine/fs/ext3/Makefile 2002-10-19 11:43:53.000000000 -0600 -+++ linux-2.4.18-17.8.0-uml/fs/ext3/Makefile 2002-10-19 11:44:51.000000000 -0600 -@@ -9,6 +9,8 @@ - - O_TARGET := ext3.o + struct dentry * dentry; + struct inode *inode; +@@ -802,13 +864,16 @@ struct dentry * lookup_hash(struct qstr + goto out; + } -+export-objs := super.o -+ - obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \ - ioctl.o namei.o super.o symlink.o - obj-m := $(O_TARGET) ---- linux-2.4.18-17.8.0-uml-pristine/fs/ext3/super.c 2002-10-19 11:43:53.000000000 -0600 -+++ linux-2.4.18-17.8.0-uml/fs/ext3/super.c 2002-10-19 11:44:51.000000000 -0600 -@@ -1746,7 +1746,7 @@ - unregister_filesystem(&ext3_fs_type); +- dentry = cached_lookup(base, name, 0); ++ dentry = cached_lookup(base, name, 0, it); + if (!dentry) { + struct dentry *new = d_alloc(base, name); + dentry = ERR_PTR(-ENOMEM); + if (!new) + goto out; + lock_kernel(); ++ if (inode->i_op->lookup2) ++ dentry = inode->i_op->lookup2(inode, new, it); ++ else + dentry = inode->i_op->lookup(inode, new); + unlock_kernel(); + if (!dentry) +@@ -820,6 +885,12 @@ out: + return dentry; } --EXPORT_NO_SYMBOLS; -+EXPORT_SYMBOL(ext3_bread); - - MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others"); - MODULE_DESCRIPTION("Second Extended Filesystem with journaling extensions"); ---- linux-2.4.18-17.8.0-uml-pristine/include/linux/slab.h 2002-10-19 11:43:54.000000000 -0600 -+++ linux-2.4.18-17.8.0-uml/include/linux/slab.h 2002-11-02 00:49:24.000000000 -0700 -@@ -57,6 +57,7 @@ - extern int kmem_cache_shrink(kmem_cache_t *); - extern void *kmem_cache_alloc(kmem_cache_t *, int); - extern void kmem_cache_free(kmem_cache_t *, void *); -+extern int kmem_cache_validate(kmem_cache_t *cachep, void *objp); - - extern void *kmalloc(size_t, int); - extern void kfree(const void *); ---- linux-2.4.18-17.8.0-uml-pristine/kernel/ksyms.c 2002-10-19 11:43:53.000000000 -0600 -+++ linux-2.4.18-17.8.0-uml/kernel/ksyms.c 2002-11-02 01:09:34.000000000 -0700 -@@ -292,6 +292,7 @@ - EXPORT_SYMBOL(set_page_dirty); - EXPORT_SYMBOL(vfs_readlink); - EXPORT_SYMBOL(vfs_follow_link); -+EXPORT_SYMBOL(vfs_follow_link_it); - EXPORT_SYMBOL(page_readlink); - EXPORT_SYMBOL(page_follow_link); - EXPORT_SYMBOL(page_symlink_inode_operations); -@@ -306,6 +307,12 @@ - EXPORT_SYMBOL_GPL(nr_free_pages); - EXPORT_SYMBOL_GPL(page_cache_size); - -+/* lustre */ -+EXPORT_SYMBOL(panic_notifier_list); -+EXPORT_SYMBOL(pagecache_lock_cacheline); -+EXPORT_SYMBOL(do_kern_mount); -+EXPORT_SYMBOL(kmem_cache_validate); -+ - /* for stackable file systems (lofs, wrapfs, cryptfs, etc.) */ - EXPORT_SYMBOL(default_llseek); - EXPORT_SYMBOL(dentry_open); ---- linux-2.4.18-17.8.0-uml-pristine/include/linux/dcache.h 2002-10-19 11:43:54.000000000 -0600 -+++ linux-2.4.18-17.8.0-uml/include/linux/dcache.h 2002-11-02 00:49:24.000000000 -0700 -@@ -6,6 +6,34 @@ - #include - #include - -+#define IT_OPEN (1) -+#define IT_CREAT (1<<1) -+#define IT_MKDIR (1<<2) -+#define IT_LINK (1<<3) -+#define IT_LINK2 (1<<4) -+#define IT_SYMLINK (1<<5) -+#define IT_UNLINK (1<<6) -+#define IT_RMDIR (1<<7) -+#define IT_RENAME (1<<8) -+#define IT_RENAME2 (1<<9) -+#define IT_READDIR (1<<10) -+#define IT_GETATTR (1<<11) -+#define IT_SETATTR (1<<12) -+#define IT_READLINK (1<<13) -+#define IT_MKNOD (1<<14) -+#define IT_LOOKUP (1<<15) ++struct dentry * lookup_hash(struct qstr *name, struct dentry * base) ++{ ++ return lookup_hash_it(name, base, NULL); ++} + -+struct lookup_intent { -+ int it_op; -+ int it_mode; -+ int it_disposition; -+ int it_status; -+ struct iattr *it_iattr; -+ __u64 it_lock_handle[2]; -+ int it_lock_mode; -+ void *it_data; -+}; + - /* - * linux/include/linux/dcache.h - * -@@ -78,6 +106,7 @@ - unsigned long d_time; /* used by d_revalidate */ - struct dentry_operations *d_op; - struct super_block * d_sb; /* The root of the dentry tree */ -+ struct lookup_intent *d_it; - unsigned long d_vfs_flags; - void * d_fsdata; /* fs-specific data */ - void * d_extra_attributes; /* TUX-specific data */ -@@ -91,6 +120,8 @@ - int (*d_delete)(struct dentry *); - void (*d_release)(struct dentry *); - void (*d_iput)(struct dentry *, struct inode *); -+ int (*d_revalidate2)(struct dentry *, int, struct lookup_intent *); -+ void (*d_intent_release)(struct dentry *, struct lookup_intent *); - }; - - /* the dentry parameter passed to d_hash and d_compare is the parent ---- linux-2.4.18-17.8.0-uml-pristine/include/linux/fs.h 2002-10-19 11:43:54.000000000 -0600 -+++ linux-2.4.18-17.8.0-uml/include/linux/fs.h 2002-11-02 00:49:24.000000000 -0700 -@@ -576,6 +576,7 @@ - - /* needed for tty driver, and maybe others */ - void *private_data; -+ struct lookup_intent *f_intent; - - /* preallocated helper kiobuf to speedup O_DIRECT */ - struct kiobuf *f_iobuf; -@@ -836,7 +837,9 @@ - extern int vfs_link(struct dentry *, struct inode *, struct dentry *); - extern int vfs_rmdir(struct inode *, struct dentry *); - extern int vfs_unlink(struct inode *, struct dentry *); --extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); -+int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, -+ struct inode *new_dir, struct dentry *new_dentry, -+ struct lookup_intent *it); - - /* - * File types -@@ -897,6 +900,7 @@ - struct inode_operations { - int (*create) (struct inode *,struct dentry *,int); - struct dentry * (*lookup) (struct inode *,struct dentry *); -+ struct dentry * (*lookup2) (struct inode *,struct dentry *, struct lookup_intent *); - int (*link) (struct dentry *,struct inode *,struct dentry *); - int (*unlink) (struct inode *,struct dentry *); - int (*symlink) (struct inode *,struct dentry *,const char *); -@@ -907,6 +911,8 @@ - struct inode *, struct dentry *); - int (*readlink) (struct dentry *, char *,int); - int (*follow_link) (struct dentry *, struct nameidata *); -+ int (*follow_link2) (struct dentry *, struct nameidata *, -+ struct lookup_intent *it); - void (*truncate) (struct inode *); - int (*permission) (struct inode *, int); - int (*revalidate) (struct dentry *); -@@ -1046,6 +1052,7 @@ - extern struct vfsmount *kern_mount(struct file_system_type *); - extern int may_umount(struct vfsmount *); - extern long do_mount(char *, char *, char *, unsigned long, void *); -+struct vfsmount *do_kern_mount(const char *type, int flags, char *name, void *data); - extern void umount_tree(struct vfsmount *); - - #define kern_umount mntput -@@ -1380,6 +1387,7 @@ - extern loff_t default_llseek(struct file *file, loff_t offset, int origin); - - extern int FASTCALL(__user_walk(const char *, unsigned, struct nameidata *)); -+extern int FASTCALL(__user_walk_it(const char *, unsigned, struct nameidata *, struct lookup_intent *it)); - extern int FASTCALL(path_init(const char *, unsigned, struct nameidata *)); - extern int FASTCALL(path_walk(const char *, struct nameidata *)); - extern int FASTCALL(path_lookup(const char *, unsigned, struct nameidata *)); -@@ -1391,6 +1399,8 @@ - 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) -+#define user_path_walk_it(name,nd,it) __user_walk_it(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd, it) -+#define user_path_walk_link_it(name,nd,it) __user_walk_it(name, LOOKUP_POSITIVE, nd, it) - - extern void inode_init_once(struct inode *); - extern void iput(struct inode *); -@@ -1491,6 +1501,8 @@ - - extern int vfs_readlink(struct dentry *, char *, int, const char *); - extern int vfs_follow_link(struct nameidata *, const char *); -+extern int vfs_follow_link_it(struct nameidata *, const char *, -+ struct lookup_intent *it); - extern int page_readlink(struct dentry *, char *, int); - extern int page_follow_link(struct dentry *, struct nameidata *); - extern struct inode_operations page_symlink_inode_operations; ---- linux-2.4.18-17.8.0-uml-pristine/fs/dcache.c 2002-10-19 11:43:53.000000000 -0600 -+++ linux-2.4.18-17.8.0-uml/fs/dcache.c 2002-10-31 13:10:34.000000000 -0700 -@@ -150,6 +150,8 @@ - unhash_it: - list_del_init(&dentry->d_hash); + /* SMP-safe */ + struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) + { +@@ -841,7 +912,7 @@ struct dentry * lookup_one_len(const cha + } + this.hash = end_name_hash(hash); -+ -+ - kill_it: { - struct dentry *parent; - list_del(&dentry->d_child); -@@ -645,6 +647,7 @@ - dentry->d_fsdata = NULL; - dentry->d_extra_attributes = NULL; - dentry->d_mounted = 0; -+ dentry->d_it = NULL; - INIT_LIST_HEAD(&dentry->d_hash); - INIT_LIST_HEAD(&dentry->d_lru); - INIT_LIST_HEAD(&dentry->d_subdirs); ---- linux-2.4.18-17.8.0-uml-pristine/fs/nfsd/vfs.c 2002-10-19 11:43:53.000000000 -0600 -+++ linux-2.4.18-17.8.0-uml/fs/nfsd/vfs.c 2002-10-19 11:44:51.000000000 -0600 -@@ -1298,7 +1298,7 @@ - err = nfserr_perm; - } else - #endif -- err = vfs_rename(fdir, odentry, tdir, ndentry); -+ err = vfs_rename(fdir, odentry, tdir, ndentry, NULL); - unlock_kernel(); - if (!err && EX_ISSYNC(tfhp->fh_export)) { - nfsd_sync_dir(tdentry); ---- linux-2.4.18-17.8.0-uml-pristine/fs/namei.c 2002-10-19 11:43:53.000000000 -0600 -+++ linux-2.4.18-17.8.0-uml/fs/namei.c 2002-11-02 01:02:26.000000000 -0700 -@@ -1,3 +1,6 @@ -+ -+ -+ - /* - * linux/fs/namei.c - * -@@ -94,6 +97,14 @@ - * XEmacs seems to be relying on it... - */ +- return lookup_hash(&this, base); ++ return lookup_hash_it(&this, base, NULL); + access: + return ERR_PTR(-EACCES); + } +@@ -872,6 +943,23 @@ int __user_walk(const char *name, unsign + return err; + } -+void intent_release(struct dentry *de, struct lookup_intent *it) ++int __user_walk_it(const char *name, unsigned flags, struct nameidata *nd, ++ struct lookup_intent *it) +{ -+ if (de->d_op && de->d_op->d_intent_release) -+ de->d_op->d_intent_release(de, it); ++ char *tmp; ++ int err; + ++ tmp = getname(name); ++ err = PTR_ERR(tmp); ++ if (!IS_ERR(tmp)) { ++ err = 0; ++ if (path_init(tmp, flags, nd)) ++ err = path_walk_it(tmp, nd, it); ++ putname(tmp); ++ } ++ return err; +} + -+ - /* In order to reduce some races, while at the same time doing additional - * checking and hopefully speeding things up, we copy filenames to the - * kernel data space before using them.. -@@ -260,10 +271,19 @@ - * Internal lookup() using the new generic dcache. + /* + * It's inline, so penalty for filesystems that don't use sticky bit is + * minimal. +@@ -1010,7 +1098,8 @@ exit_lock: + * for symlinks (where the permissions are checked later). * SMP-safe */ --static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, int flags) -+static struct dentry *cached_lookup(struct dentry *parent, struct qstr *name, -+ int flags, struct lookup_intent *it) +-int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) ++int open_namei_it(const char *pathname, int flag, int mode, ++ struct nameidata *nd, struct lookup_intent *it) { - struct dentry * dentry = d_lookup(parent, name); + int acc_mode, error = 0; + struct inode *inode; +@@ -1024,7 +1113,7 @@ int open_namei(const char * pathname, in + * The simplest case - just a plain lookup. + */ + if (!(flag & O_CREAT)) { +- error = path_lookup(pathname, lookup_flags(flag), nd); ++ error = path_lookup_it(pathname, lookup_flags(flag), nd, it); + if (error) + return error; + dentry = nd->dentry; +@@ -1034,6 +1123,10 @@ int open_namei(const char * pathname, in + /* + * Create - we need to know the parent. + */ ++ if (it) { ++ it->it_mode = mode; ++ it->it_op |= IT_CREAT; ++ } + error = path_lookup(pathname, LOOKUP_PARENT, nd); + if (error) + return error; +@@ -1049,7 +1142,7 @@ int open_namei(const char * pathname, in -+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate2) { -+ if (!dentry->d_op->d_revalidate2(dentry, flags, it) && -+ !d_invalidate(dentry)) { -+ dput(dentry); -+ dentry = NULL; -+ } -+ return dentry; -+ } else - if (dentry && dentry->d_op && dentry->d_op->d_revalidate) { - if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) { - dput(dentry); -@@ -281,7 +301,8 @@ - * make sure that nobody added the entry to the dcache in the meantime.. - * SMP-safe - */ --static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, int flags) -+static struct dentry *real_lookup(struct dentry *parent, struct qstr *name, -+ int flags, struct lookup_intent *it) - { - struct dentry * result; - struct inode *dir = parent->d_inode; -@@ -300,6 +321,9 @@ - result = ERR_PTR(-ENOMEM); - if (dentry) { - lock_kernel(); -+ if (dir->i_op->lookup2) -+ result = dir->i_op->lookup2(dir, dentry, it); -+ else - result = dir->i_op->lookup(dir, dentry); - unlock_kernel(); - if (result) -@@ -321,6 +345,12 @@ - dput(result); - result = ERR_PTR(-ENOENT); - } -+ } else if (result->d_op && result->d_op->d_revalidate2) { -+ if (!result->d_op->d_revalidate2(result, flags, it) && -+ !d_invalidate(result)) { -+ dput(result); -+ result = ERR_PTR(-ENOENT); -+ } + dir = nd->dentry; + down(&dir->d_inode->i_sem); +- dentry = lookup_hash(&nd->last, nd->dentry); ++ dentry = lookup_hash_it(&nd->last, nd->dentry, it); + + do_last: + error = PTR_ERR(dentry); +@@ -1058,6 +1151,7 @@ do_last: + goto exit; } - return result; - } -@@ -334,7 +364,8 @@ - * Without that kind of total limit, nasty chains of consecutive - * symlinks can cause almost arbitrarily long lookups. - */ --static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd) -+static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd, -+ struct lookup_intent *it) - { - int err; - if (current->link_count >= max_recursive_link) -@@ -348,10 +379,14 @@ - current->link_count++; - current->total_link_count++; - UPDATE_ATIME(dentry->d_inode); -- err = dentry->d_inode->i_op->follow_link(dentry, nd); -+ if (dentry->d_inode->i_op->follow_link2) -+ err = dentry->d_inode->i_op->follow_link2(dentry, nd, it); -+ else -+ err = dentry->d_inode->i_op->follow_link(dentry, nd); - current->link_count--; - return err; - loop: -+ intent_release(dentry, it); + ++ it->it_mode = mode; + /* Negative dentry, just create the file */ + if (!dentry->d_inode) { + error = vfs_create(dir->d_inode, dentry, +@@ -1091,7 +1185,8 @@ do_last: + error = -ENOENT; + if (!dentry->d_inode) + goto exit_dput; +- if (dentry->d_inode->i_op && dentry->d_inode->i_op->follow_link) ++ if (dentry->d_inode->i_op && (dentry->d_inode->i_op->follow_link || ++ dentry->d_inode->i_op->follow_link2)) + goto do_link; + + dput(nd->dentry); +@@ -1177,8 +1272,10 @@ ok: + return 0; + + exit_dput: ++ intent_release(dentry, it); + dput(dentry); + exit: ++ intent_release(nd->dentry, it); path_release(nd); - return -ELOOP; - } -@@ -449,7 +484,8 @@ - * - * We expect 'base' to be positive and a directory. - */ --int link_path_walk(const char * name, struct nameidata *nd) -+int link_path_walk_it(const char *name, struct nameidata *nd, -+ struct lookup_intent *it) - { - struct dentry *dentry; - struct inode *inode; -@@ -526,12 +562,12 @@ - break; - } - /* This does the actual lookups.. */ -- dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE); -+ dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE, NULL); - if (!dentry) { - err = -EWOULDBLOCKIO; - if (atomic) - break; -- dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE); -+ dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE, NULL); - err = PTR_ERR(dentry); - if (IS_ERR(dentry)) - break; -@@ -548,8 +584,8 @@ - if (!inode->i_op) - goto out_dput; + return error; -- if (inode->i_op->follow_link) { -- err = do_follow_link(dentry, nd); -+ if (inode->i_op->follow_link || inode->i_op->follow_link2) { -+ err = do_follow_link(dentry, nd, it); - dput(dentry); - if (err) - goto return_err; -@@ -565,7 +601,7 @@ - nd->dentry = dentry; - } - err = -ENOTDIR; -- if (!inode->i_op->lookup) -+ if (!inode->i_op->lookup && !inode->i_op->lookup2) - break; - continue; - /* here ends the main loop */ -@@ -592,12 +628,12 @@ - if (err < 0) - break; - } -- dentry = cached_lookup(nd->dentry, &this, 0); -+ dentry = cached_lookup(nd->dentry, &this, 0, it); - if (!dentry) { - err = -EWOULDBLOCKIO; - if (atomic) - break; -- dentry = real_lookup(nd->dentry, &this, 0); -+ dentry = real_lookup(nd->dentry, &this, 0, it); - err = PTR_ERR(dentry); - if (IS_ERR(dentry)) - break; -@@ -606,8 +642,10 @@ - ; - inode = dentry->d_inode; - if ((lookup_flags & LOOKUP_FOLLOW) -- && inode && inode->i_op && inode->i_op->follow_link) { -- err = do_follow_link(dentry, nd); -+ && inode && inode->i_op && -+ (inode->i_op->follow_link || -+ inode->i_op->follow_link2)) { -+ err = do_follow_link(dentry, nd, it); - dput(dentry); - if (err) - goto return_err; -@@ -621,7 +659,8 @@ - goto no_inode; - if (lookup_flags & LOOKUP_DIRECTORY) { - err = -ENOTDIR; -- if (!inode->i_op || !inode->i_op->lookup) -+ if (!inode->i_op || (!inode->i_op->lookup && -+ !inode->i_op->lookup2)) - break; - } - goto return_base; -@@ -663,10 +702,21 @@ - return err; +@@ -1197,7 +1294,12 @@ do_link: + * are done. Procfs-like symlinks just set LAST_BIND. + */ + UPDATE_ATIME(dentry->d_inode); +- error = dentry->d_inode->i_op->follow_link(dentry, nd); ++ if (dentry->d_inode->i_op->follow_link2) ++ error = dentry->d_inode->i_op->follow_link2(dentry, nd, it); ++ else ++ error = dentry->d_inode->i_op->follow_link(dentry, nd); ++ if (error) ++ intent_release(dentry, it); + dput(dentry); + if (error) + return error; +@@ -1219,13 +1321,20 @@ do_link: + } + dir = nd->dentry; + down(&dir->d_inode->i_sem); +- dentry = lookup_hash(&nd->last, nd->dentry); ++ dentry = lookup_hash_it(&nd->last, nd->dentry, it); + putname(nd->last.name); + goto do_last; } -+int link_path_walk(const char * name, struct nameidata *nd) ++int open_namei(const char *pathname, int flag, int mode, struct nameidata *nd) +{ -+ return link_path_walk_it(name, nd, NULL); ++ return open_namei_it(pathname, flag, mode, nd, NULL); +} + -+int path_walk_it(const char * name, struct nameidata *nd, struct lookup_intent *it) -+{ -+ current->total_link_count = 0; -+ return link_path_walk_it(name, nd, it); -+} + - int path_walk(const char * name, struct nameidata *nd) + /* SMP-safe */ +-static struct dentry *lookup_create(struct nameidata *nd, int is_dir) ++static struct dentry *lookup_create(struct nameidata *nd, int is_dir, ++ struct lookup_intent *it) { - current->total_link_count = 0; -- return link_path_walk(name, nd); -+ return link_path_walk_it(name, nd, NULL); - } + struct dentry *dentry; - /* SMP-safe */ -@@ -751,6 +801,17 @@ - } - - /* SMP-safe */ -+int path_lookup_it(const char *path, unsigned flags, struct nameidata *nd, -+ struct lookup_intent *it) -+{ -+ int error = 0; -+ if (path_init(path, flags, nd)) -+ error = path_walk_it(path, nd, it); -+ return error; -+} -+ -+ -+/* SMP-safe */ - int path_lookup(const char *path, unsigned flags, struct nameidata *nd) - { - int error = 0; -@@ -779,7 +840,8 @@ - * needs parent already locked. Doesn't follow mounts. - * SMP-safe. - */ --struct dentry * lookup_hash(struct qstr *name, struct dentry * base) -+struct dentry * lookup_hash_it(struct qstr *name, struct dentry * base, -+ struct lookup_intent *it) - { - struct dentry * dentry; - struct inode *inode; -@@ -802,13 +864,16 @@ - goto out; - } - -- dentry = cached_lookup(base, name, 0); -+ dentry = cached_lookup(base, name, 0, it); - if (!dentry) { - struct dentry *new = d_alloc(base, name); - dentry = ERR_PTR(-ENOMEM); - if (!new) - goto out; - lock_kernel(); -+ if (inode->i_op->lookup2) -+ dentry = inode->i_op->lookup2(inode, new, it); -+ else - dentry = inode->i_op->lookup(inode, new); - unlock_kernel(); - if (!dentry) -@@ -820,6 +885,12 @@ - return dentry; - } - -+struct dentry * lookup_hash(struct qstr *name, struct dentry * base) -+{ -+ return lookup_hash_it(name, base, NULL); -+} -+ -+ - /* SMP-safe */ - struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) - { -@@ -841,7 +912,7 @@ - } - this.hash = end_name_hash(hash); - -- return lookup_hash(&this, base); -+ return lookup_hash_it(&this, base, NULL); - access: - return ERR_PTR(-EACCES); - } -@@ -872,6 +943,23 @@ - return err; - } - -+int __user_walk_it(const char *name, unsigned flags, struct nameidata *nd, -+ struct lookup_intent *it) -+{ -+ char *tmp; -+ int err; -+ -+ tmp = getname(name); -+ err = PTR_ERR(tmp); -+ if (!IS_ERR(tmp)) { -+ err = 0; -+ if (path_init(tmp, flags, nd)) -+ err = path_walk_it(tmp, nd, it); -+ putname(tmp); -+ } -+ return err; -+} -+ - /* - * It's inline, so penalty for filesystems that don't use sticky bit is - * minimal. -@@ -1010,7 +1098,8 @@ - * for symlinks (where the permissions are checked later). - * SMP-safe - */ --int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) -+int open_namei_it(const char *pathname, int flag, int mode, -+ struct nameidata *nd, struct lookup_intent *it) - { - int acc_mode, error = 0; - struct inode *inode; -@@ -1024,7 +1113,7 @@ - * The simplest case - just a plain lookup. - */ - if (!(flag & O_CREAT)) { -- error = path_lookup(pathname, lookup_flags(flag), nd); -+ error = path_lookup_it(pathname, lookup_flags(flag), nd, it); - if (error) - return error; - dentry = nd->dentry; -@@ -1034,6 +1123,10 @@ - /* - * Create - we need to know the parent. - */ -+ if (it) { -+ it->it_mode = mode; -+ it->it_op |= IT_CREAT; -+ } - error = path_lookup(pathname, LOOKUP_PARENT, nd); - if (error) - return error; -@@ -1049,7 +1142,7 @@ - - dir = nd->dentry; - down(&dir->d_inode->i_sem); -- dentry = lookup_hash(&nd->last, nd->dentry); -+ dentry = lookup_hash_it(&nd->last, nd->dentry, it); - - do_last: - error = PTR_ERR(dentry); -@@ -1058,6 +1151,7 @@ - goto exit; - } - -+ it->it_mode = mode; - /* Negative dentry, just create the file */ - if (!dentry->d_inode) { - error = vfs_create(dir->d_inode, dentry, -@@ -1091,7 +1185,8 @@ - error = -ENOENT; - if (!dentry->d_inode) - goto exit_dput; -- if (dentry->d_inode->i_op && dentry->d_inode->i_op->follow_link) -+ if (dentry->d_inode->i_op && (dentry->d_inode->i_op->follow_link || -+ dentry->d_inode->i_op->follow_link2)) - goto do_link; - - dput(nd->dentry); -@@ -1177,8 +1272,10 @@ - return 0; - - exit_dput: -+ intent_release(dentry, it); - dput(dentry); - exit: -+ intent_release(nd->dentry, it); - path_release(nd); - return error; - -@@ -1197,7 +1294,12 @@ - * are done. Procfs-like symlinks just set LAST_BIND. - */ - UPDATE_ATIME(dentry->d_inode); -- error = dentry->d_inode->i_op->follow_link(dentry, nd); -+ if (dentry->d_inode->i_op->follow_link2) -+ error = dentry->d_inode->i_op->follow_link2(dentry, nd, it); -+ else -+ error = dentry->d_inode->i_op->follow_link(dentry, nd); -+ if (error) -+ intent_release(dentry, it); - dput(dentry); - if (error) - return error; -@@ -1219,13 +1321,20 @@ - } - dir = nd->dentry; - down(&dir->d_inode->i_sem); -- dentry = lookup_hash(&nd->last, nd->dentry); -+ dentry = lookup_hash_it(&nd->last, nd->dentry, it); - putname(nd->last.name); - goto do_last; - } - -+int open_namei(const char *pathname, int flag, int mode, struct nameidata *nd) -+{ -+ return open_namei_it(pathname, flag, mode, nd, NULL); -+} -+ -+ - /* SMP-safe */ --static struct dentry *lookup_create(struct nameidata *nd, int is_dir) -+static struct dentry *lookup_create(struct nameidata *nd, int is_dir, -+ struct lookup_intent *it) - { - struct dentry *dentry; - -@@ -1233,7 +1342,7 @@ - dentry = ERR_PTR(-EEXIST); - if (nd->last_type != LAST_NORM) - goto fail; -- dentry = lookup_hash(&nd->last, nd->dentry); -+ dentry = lookup_hash_it(&nd->last, nd->dentry, it); - if (IS_ERR(dentry)) - goto fail; - if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode) -@@ -1279,6 +1388,7 @@ - char * tmp; - struct dentry * dentry; - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_MKNOD, .it_mode = mode }; +@@ -1233,7 +1342,7 @@ static struct dentry *lookup_create(stru + dentry = ERR_PTR(-EEXIST); + if (nd->last_type != LAST_NORM) + goto fail; +- dentry = lookup_hash(&nd->last, nd->dentry); ++ dentry = lookup_hash_it(&nd->last, nd->dentry, it); + if (IS_ERR(dentry)) + goto fail; + if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode) +@@ -1279,6 +1388,7 @@ asmlinkage long sys_mknod(const char * f + char * tmp; + struct dentry * dentry; + struct nameidata nd; ++ struct lookup_intent it = { .it_op = IT_MKNOD, .it_mode = mode }; if (S_ISDIR(mode)) return -EPERM; -@@ -1289,7 +1399,7 @@ +@@ -1289,7 +1399,7 @@ asmlinkage long sys_mknod(const char * f error = path_lookup(tmp, LOOKUP_PARENT, &nd); if (error) goto out; @@ -746,7 +431,7 @@ error = PTR_ERR(dentry); mode &= ~current->fs->umask; -@@ -1307,6 +1417,7 @@ +@@ -1307,6 +1417,7 @@ asmlinkage long sys_mknod(const char * f default: error = -EINVAL; } @@ -754,7 +439,7 @@ dput(dentry); } up(&nd.dentry->d_inode->i_sem); -@@ -1347,6 +1458,7 @@ +@@ -1347,6 +1458,7 @@ asmlinkage long sys_mkdir(const char * p { int error = 0; char * tmp; @@ -762,7 +447,7 @@ tmp = getname(pathname); error = PTR_ERR(tmp); -@@ -1357,11 +1469,12 @@ +@@ -1357,11 +1469,12 @@ asmlinkage long sys_mkdir(const char * p error = path_lookup(tmp, LOOKUP_PARENT, &nd); if (error) goto out; @@ -776,7 +461,7 @@ dput(dentry); } up(&nd.dentry->d_inode->i_sem); -@@ -1445,6 +1558,7 @@ +@@ -1445,6 +1558,7 @@ asmlinkage long sys_rmdir(const char * p char * name; struct dentry *dentry; struct nameidata nd; @@ -784,7 +469,7 @@ name = getname(pathname); if(IS_ERR(name)) -@@ -1466,10 +1580,11 @@ +@@ -1466,10 +1580,11 @@ asmlinkage long sys_rmdir(const char * p goto exit1; } down(&nd.dentry->d_inode->i_sem); @@ -797,7 +482,7 @@ dput(dentry); } up(&nd.dentry->d_inode->i_sem); -@@ -1513,6 +1628,7 @@ +@@ -1513,6 +1628,7 @@ asmlinkage long sys_unlink(const char * char * name; struct dentry *dentry; struct nameidata nd; @@ -805,7 +490,7 @@ name = getname(pathname); if(IS_ERR(name)) -@@ -1525,7 +1641,7 @@ +@@ -1525,7 +1641,7 @@ asmlinkage long sys_unlink(const char * if (nd.last_type != LAST_NORM) goto exit1; down(&nd.dentry->d_inode->i_sem); @@ -814,7 +499,7 @@ error = PTR_ERR(dentry); if (!IS_ERR(dentry)) { /* Why not before? Because we want correct error value */ -@@ -1533,6 +1649,7 @@ +@@ -1533,6 +1649,7 @@ asmlinkage long sys_unlink(const char * goto slashes; error = vfs_unlink(nd.dentry->d_inode, dentry); exit2: @@ -822,7 +507,7 @@ dput(dentry); } up(&nd.dentry->d_inode->i_sem); -@@ -1579,6 +1696,7 @@ +@@ -1579,6 +1696,7 @@ asmlinkage long sys_symlink(const char * int error = 0; char * from; char * to; @@ -830,7 +515,7 @@ from = getname(oldname); if(IS_ERR(from)) -@@ -1592,10 +1710,12 @@ +@@ -1592,10 +1710,12 @@ asmlinkage long sys_symlink(const char * error = path_lookup(to, LOOKUP_PARENT, &nd); if (error) goto out; @@ -844,7 +529,7 @@ dput(dentry); } up(&nd.dentry->d_inode->i_sem); -@@ -1660,6 +1780,7 @@ +@@ -1660,6 +1780,7 @@ asmlinkage long sys_link(const char * ol { int error; char * to; @@ -852,7 +537,7 @@ to = getname(newname); error = PTR_ERR(to); -@@ -1667,7 +1788,7 @@ +@@ -1667,7 +1788,7 @@ asmlinkage long sys_link(const char * ol struct dentry *new_dentry; struct nameidata nd, old_nd; @@ -861,7 +546,7 @@ if (error) goto exit; error = path_lookup(to, LOOKUP_PARENT, &nd); -@@ -1676,10 +1797,12 @@ +@@ -1676,10 +1797,12 @@ asmlinkage long sys_link(const char * ol error = -EXDEV; if (old_nd.mnt != nd.mnt) goto out_release; @@ -875,7 +560,7 @@ dput(new_dentry); } up(&nd.dentry->d_inode->i_sem); -@@ -1720,7 +1843,8 @@ +@@ -1720,7 +1843,8 @@ exit: * locking]. */ int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, @@ -885,7 +570,7 @@ { int error; struct inode *target; -@@ -1778,6 +1902,7 @@ +@@ -1778,6 +1902,7 @@ int vfs_rename_dir(struct inode *old_dir error = -EBUSY; else error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry); @@ -893,7 +578,7 @@ if (target) { if (!error) target->i_flags |= S_DEAD; -@@ -1799,7 +1924,8 @@ +@@ -1799,7 +1924,8 @@ out_unlock: } int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry, @@ -903,7 +588,7 @@ { int error; -@@ -1830,6 +1956,7 @@ +@@ -1830,6 +1956,7 @@ int vfs_rename_other(struct inode *old_d error = -EBUSY; else error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry); @@ -911,7 +596,7 @@ double_up(&old_dir->i_zombie, &new_dir->i_zombie); if (error) return error; -@@ -1841,13 +1968,14 @@ +@@ -1841,13 +1968,14 @@ int vfs_rename_other(struct inode *old_d } int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, @@ -929,7 +614,7 @@ if (!error) { if (old_dir == new_dir) inode_dir_notify(old_dir, DN_RENAME); -@@ -1864,6 +1992,7 @@ +@@ -1864,6 +1992,7 @@ static inline int do_rename(const char * int error = 0; struct dentry * old_dir, * new_dir; struct dentry * old_dentry, *new_dentry; @@ -937,7 +622,7 @@ struct nameidata oldnd, newnd; error = path_lookup(oldname, LOOKUP_PARENT, &oldnd); -@@ -1889,7 +2018,7 @@ +@@ -1889,7 +2018,7 @@ static inline int do_rename(const char * double_lock(new_dir, old_dir); @@ -946,7 +631,7 @@ error = PTR_ERR(old_dentry); if (IS_ERR(old_dentry)) goto exit3; -@@ -1905,18 +2034,21 @@ +@@ -1905,18 +2034,21 @@ static inline int do_rename(const char * if (newnd.last.name[newnd.last.len]) goto exit4; } @@ -963,14 +648,14 @@ + new_dir->d_inode, new_dentry, &it); unlock_kernel(); -+ intent_release(new_dentry, NULL); ++ intent_release(new_dentry, &it); dput(new_dentry); exit4: + intent_release(old_dentry, &it); dput(old_dentry); exit3: double_up(&new_dir->d_inode->i_sem, &old_dir->d_inode->i_sem); -@@ -1965,7 +2097,8 @@ +@@ -1965,7 +2097,8 @@ out: } static inline int @@ -980,7 +665,7 @@ { int res = 0; char *name; -@@ -1978,7 +2111,7 @@ +@@ -1978,7 +2111,7 @@ __vfs_follow_link(struct nameidata *nd, /* weird __emul_prefix() stuff did it */ goto out; } @@ -989,7 +674,7 @@ out: if (current->link_count || res || nd->last_type!=LAST_NORM) return res; -@@ -2000,7 +2133,13 @@ +@@ -2000,7 +2133,13 @@ fail: int vfs_follow_link(struct nameidata *nd, const char *link) { @@ -1004,7 +689,7 @@ } /* get the link contents into pagecache */ -@@ -2042,7 +2181,7 @@ +@@ -2042,7 +2181,7 @@ int page_follow_link(struct dentry *dent { struct page *page = NULL; char *s = page_getlink(dentry, &page); @@ -1013,8 +698,323 @@ if (page) { kunmap(page); page_cache_release(page); ---- linux-2.4.18-17.8.0-uml-pristine/fs/open.c 2002-10-19 11:43:53.000000000 -0600 -+++ linux-2.4.18-17.8.0-uml/fs/open.c 2002-10-19 11:44:51.000000000 -0600 +--- /dev/null 2002-08-30 17:31:37.000000000 -0600 ++++ lum-root/include/linux/lustre_version.h 2002-12-04 01:39:12.000000000 -0700 +@@ -0,0 +1 @@ ++#define LUSTRE_KERNEL_VERSION 4 +--- lum/arch/ia64/mm/init.c~lustre 2002-12-04 01:39:11.000000000 -0700 ++++ lum-root/arch/ia64/mm/init.c 2002-12-04 01:39:12.000000000 -0700 +@@ -37,6 +37,12 @@ unsigned long MAX_DMA_ADDRESS = PAGE_OFF + + static unsigned long totalram_pages; + ++struct page *check_get_page(unsigned long kaddr) ++{ ++#warning FIXME: Lustre team, is this solid? ++ return virt_to_page(kaddr); ++} ++ + int + do_check_pgt_cache (int low, int high) + { +--- lum/arch/i386/mm/init.c~lustre 2002-12-04 01:39:11.000000000 -0700 ++++ lum-root/arch/i386/mm/init.c 2002-12-04 01:39:12.000000000 -0700 +@@ -43,6 +43,12 @@ unsigned long highstart_pfn, highend_pfn + static unsigned long totalram_pages; + static unsigned long totalhigh_pages; + ++struct page *check_get_page(unsigned long kaddr) ++{ ++#warning FIXME: Lustre team, is this solid? ++ return virt_to_page(kaddr); ++} ++ + int do_check_pgt_cache(int low, int high) + { + int freed = 0; +--- lum/drivers/block/blkpg.c~lustre 2002-12-04 01:39:11.000000000 -0700 ++++ lum-root/drivers/block/blkpg.c 2002-12-04 01:39:12.000000000 -0700 +@@ -297,3 +297,38 @@ int blk_ioctl(kdev_t dev, unsigned int c + } + + EXPORT_SYMBOL(blk_ioctl); ++ ++#define NUM_DEV_NO_WRITE 16 ++static int dev_no_write[NUM_DEV_NO_WRITE]; ++ ++/* ++ * Debug code for turning block devices "read-only" (will discard writes ++ * silently). This is for filesystem crash/recovery testing. ++ */ ++void dev_set_rdonly(kdev_t dev, int no_write) ++{ ++ if (dev) { ++ printk(KERN_WARNING "Turning device %s read-only\n", ++ bdevname(dev)); ++ dev_no_write[no_write] = 0xdead0000 + dev; ++ } ++} ++ ++int dev_check_rdonly(kdev_t dev) { ++ int i; ++ ++ for (i = 0; i < NUM_DEV_NO_WRITE; i++) { ++ if ((dev_no_write[i] & 0xffff0000) == 0xdead0000 && ++ dev == (dev_no_write[i] & 0xffff)) ++ return 1; ++ } ++ return 0; ++} ++ ++void dev_clear_rdonly(int no_write) { ++ dev_no_write[no_write] = 0; ++} ++ ++EXPORT_SYMBOL(dev_set_rdonly); ++EXPORT_SYMBOL(dev_check_rdonly); ++EXPORT_SYMBOL(dev_clear_rdonly); +--- lum/drivers/block/loop.c~lustre 2002-12-04 01:39:12.000000000 -0700 ++++ lum-root/drivers/block/loop.c 2002-12-04 01:39:12.000000000 -0700 +@@ -491,6 +491,11 @@ static int loop_make_request(request_que + spin_unlock_irq(&lo->lo_lock); + + if (rw == WRITE) { ++#ifdef CONFIG_DEV_RDONLY ++ if (dev_check_rdonly(rbh->b_rdev)) ++ goto err; ++#endif ++ + if (lo->lo_flags & LO_FLAGS_READ_ONLY) + goto err; + } else if (rw == READA) { +--- lum/drivers/ide/ide-disk.c~lustre 2002-12-04 01:39:12.000000000 -0700 ++++ lum-root/drivers/ide/ide-disk.c 2002-12-04 01:39:12.000000000 -0700 +@@ -557,6 +557,12 @@ static ide_startstop_t lba_48_rw_disk (i + */ + static ide_startstop_t do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block) + { ++#ifdef CONFIG_DEV_RDONLY ++ if (rq->cmd == WRITE && dev_check_rdonly(rq->rq_dev)) { ++ ide_end_request(1, HWGROUP(drive)); ++ return ide_stopped; ++ } ++#endif + if (IDE_CONTROL_REG) + OUT_BYTE(drive->ctl,IDE_CONTROL_REG); + +--- lum/fs/ext3/Makefile~lustre 2002-12-04 01:39:12.000000000 -0700 ++++ lum-root/fs/ext3/Makefile 2002-12-04 01:39:12.000000000 -0700 +@@ -9,6 +9,8 @@ + + O_TARGET := ext3.o + ++export-objs := super.o ++ + obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \ + ioctl.o namei.o super.o symlink.o + obj-m := $(O_TARGET) +--- lum/fs/ext3/super.c~lustre 2002-12-04 01:39:12.000000000 -0700 ++++ lum-root/fs/ext3/super.c 2002-12-04 01:39:12.000000000 -0700 +@@ -1746,7 +1746,7 @@ static void __exit exit_ext3_fs(void) + unregister_filesystem(&ext3_fs_type); + } + +-EXPORT_NO_SYMBOLS; ++EXPORT_SYMBOL(ext3_bread); + + MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others"); + MODULE_DESCRIPTION("Second Extended Filesystem with journaling extensions"); +--- lum/include/linux/slab.h~lustre 2002-12-04 01:39:12.000000000 -0700 ++++ lum-root/include/linux/slab.h 2002-12-04 01:39:12.000000000 -0700 +@@ -57,6 +57,7 @@ extern int kmem_cache_destroy(kmem_cache + extern int kmem_cache_shrink(kmem_cache_t *); + extern void *kmem_cache_alloc(kmem_cache_t *, int); + extern void kmem_cache_free(kmem_cache_t *, void *); ++extern int kmem_cache_validate(kmem_cache_t *cachep, void *objp); + + extern void *kmalloc(size_t, int); + extern void kfree(const void *); +--- lum/kernel/ksyms.c~lustre 2002-12-04 01:39:12.000000000 -0700 ++++ lum-root/kernel/ksyms.c 2002-12-04 01:39:12.000000000 -0700 +@@ -292,6 +292,7 @@ EXPORT_SYMBOL(read_cache_page); + EXPORT_SYMBOL(set_page_dirty); + EXPORT_SYMBOL(vfs_readlink); + EXPORT_SYMBOL(vfs_follow_link); ++EXPORT_SYMBOL(vfs_follow_link_it); + EXPORT_SYMBOL(page_readlink); + EXPORT_SYMBOL(page_follow_link); + EXPORT_SYMBOL(page_symlink_inode_operations); +@@ -306,6 +307,12 @@ EXPORT_SYMBOL_GPL(buffermem_pages); + EXPORT_SYMBOL_GPL(nr_free_pages); + EXPORT_SYMBOL_GPL(page_cache_size); + ++/* lustre */ ++EXPORT_SYMBOL(panic_notifier_list); ++EXPORT_SYMBOL(pagecache_lock_cacheline); ++EXPORT_SYMBOL(do_kern_mount); ++EXPORT_SYMBOL(kmem_cache_validate); ++ + /* for stackable file systems (lofs, wrapfs, cryptfs, etc.) */ + EXPORT_SYMBOL(default_llseek); + EXPORT_SYMBOL(dentry_open); +--- lum/include/linux/dcache.h~lustre 2002-12-04 01:39:12.000000000 -0700 ++++ lum-root/include/linux/dcache.h 2002-12-04 01:39:12.000000000 -0700 +@@ -6,6 +6,34 @@ + #include + #include + ++#define IT_OPEN (1) ++#define IT_CREAT (1<<1) ++#define IT_MKDIR (1<<2) ++#define IT_LINK (1<<3) ++#define IT_LINK2 (1<<4) ++#define IT_SYMLINK (1<<5) ++#define IT_UNLINK (1<<6) ++#define IT_RMDIR (1<<7) ++#define IT_RENAME (1<<8) ++#define IT_RENAME2 (1<<9) ++#define IT_READDIR (1<<10) ++#define IT_GETATTR (1<<11) ++#define IT_SETATTR (1<<12) ++#define IT_READLINK (1<<13) ++#define IT_MKNOD (1<<14) ++#define IT_LOOKUP (1<<15) ++ ++struct lookup_intent { ++ int it_op; ++ int it_mode; ++ int it_disposition; ++ int it_status; ++ struct iattr *it_iattr; ++ __u64 it_lock_handle[2]; ++ int it_lock_mode; ++ void *it_data; ++}; ++ + /* + * linux/include/linux/dcache.h + * +@@ -78,6 +106,7 @@ struct dentry { + unsigned long d_time; /* used by d_revalidate */ + struct dentry_operations *d_op; + struct super_block * d_sb; /* The root of the dentry tree */ ++ struct lookup_intent *d_it; + unsigned long d_vfs_flags; + void * d_fsdata; /* fs-specific data */ + void * d_extra_attributes; /* TUX-specific data */ +@@ -91,6 +120,8 @@ struct dentry_operations { + int (*d_delete)(struct dentry *); + void (*d_release)(struct dentry *); + void (*d_iput)(struct dentry *, struct inode *); ++ int (*d_revalidate2)(struct dentry *, int, struct lookup_intent *); ++ void (*d_intent_release)(struct dentry *, struct lookup_intent *); + }; + + /* the dentry parameter passed to d_hash and d_compare is the parent +--- lum/include/linux/fs.h~lustre 2002-12-04 01:39:12.000000000 -0700 ++++ lum-root/include/linux/fs.h 2002-12-04 01:39:12.000000000 -0700 +@@ -576,6 +576,7 @@ struct file { + + /* needed for tty driver, and maybe others */ + void *private_data; ++ struct lookup_intent *f_intent; + + /* preallocated helper kiobuf to speedup O_DIRECT */ + struct kiobuf *f_iobuf; +@@ -836,7 +837,9 @@ extern int vfs_symlink(struct inode *, s + extern int vfs_link(struct dentry *, struct inode *, struct dentry *); + extern int vfs_rmdir(struct inode *, struct dentry *); + extern int vfs_unlink(struct inode *, struct dentry *); +-extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); ++int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, ++ struct inode *new_dir, struct dentry *new_dentry, ++ struct lookup_intent *it); + + /* + * File types +@@ -897,6 +900,7 @@ struct file_operations { + struct inode_operations { + int (*create) (struct inode *,struct dentry *,int); + struct dentry * (*lookup) (struct inode *,struct dentry *); ++ struct dentry * (*lookup2) (struct inode *,struct dentry *, struct lookup_intent *); + int (*link) (struct dentry *,struct inode *,struct dentry *); + int (*unlink) (struct inode *,struct dentry *); + int (*symlink) (struct inode *,struct dentry *,const char *); +@@ -907,6 +911,8 @@ struct inode_operations { + struct inode *, struct dentry *); + int (*readlink) (struct dentry *, char *,int); + int (*follow_link) (struct dentry *, struct nameidata *); ++ int (*follow_link2) (struct dentry *, struct nameidata *, ++ struct lookup_intent *it); + void (*truncate) (struct inode *); + int (*permission) (struct inode *, int); + int (*revalidate) (struct dentry *); +@@ -1046,6 +1052,7 @@ extern int unregister_filesystem(struct + extern struct vfsmount *kern_mount(struct file_system_type *); + extern int may_umount(struct vfsmount *); + extern long do_mount(char *, char *, char *, unsigned long, void *); ++struct vfsmount *do_kern_mount(const char *type, int flags, char *name, void *data); + extern void umount_tree(struct vfsmount *); + + #define kern_umount mntput +@@ -1380,6 +1387,7 @@ typedef int (*read_actor_t)(read_descrip + extern loff_t default_llseek(struct file *file, loff_t offset, int origin); + + extern int FASTCALL(__user_walk(const char *, unsigned, struct nameidata *)); ++extern int FASTCALL(__user_walk_it(const char *, unsigned, struct nameidata *, struct lookup_intent *it)); + extern int FASTCALL(path_init(const char *, unsigned, struct nameidata *)); + extern int FASTCALL(path_walk(const char *, struct nameidata *)); + extern int FASTCALL(path_lookup(const char *, unsigned, struct nameidata *)); +@@ -1391,6 +1399,8 @@ extern struct dentry * lookup_one_len(co + 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) ++#define user_path_walk_it(name,nd,it) __user_walk_it(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd, it) ++#define user_path_walk_link_it(name,nd,it) __user_walk_it(name, LOOKUP_POSITIVE, nd, it) + + extern void inode_init_once(struct inode *); + extern void iput(struct inode *); +@@ -1491,6 +1501,8 @@ extern struct file_operations generic_ro + + extern int vfs_readlink(struct dentry *, char *, int, const char *); + extern int vfs_follow_link(struct nameidata *, const char *); ++extern int vfs_follow_link_it(struct nameidata *, const char *, ++ struct lookup_intent *it); + extern int page_readlink(struct dentry *, char *, int); + extern int page_follow_link(struct dentry *, struct nameidata *); + extern struct inode_operations page_symlink_inode_operations; +--- lum/fs/dcache.c~lustre 2002-12-04 01:39:12.000000000 -0700 ++++ lum-root/fs/dcache.c 2002-12-04 01:39:12.000000000 -0700 +@@ -150,6 +150,8 @@ repeat: + unhash_it: + list_del_init(&dentry->d_hash); + ++ ++ + kill_it: { + struct dentry *parent; + list_del(&dentry->d_child); +@@ -645,6 +647,7 @@ struct dentry * d_alloc(struct dentry * + dentry->d_fsdata = NULL; + dentry->d_extra_attributes = NULL; + dentry->d_mounted = 0; ++ dentry->d_it = NULL; + INIT_LIST_HEAD(&dentry->d_hash); + INIT_LIST_HEAD(&dentry->d_lru); + INIT_LIST_HEAD(&dentry->d_subdirs); +--- lum/fs/nfsd/vfs.c~lustre 2002-12-04 01:39:12.000000000 -0700 ++++ lum-root/fs/nfsd/vfs.c 2002-12-04 01:39:12.000000000 -0700 +@@ -1298,7 +1298,7 @@ nfsd_rename(struct svc_rqst *rqstp, stru + err = nfserr_perm; + } else + #endif +- err = vfs_rename(fdir, odentry, tdir, ndentry); ++ err = vfs_rename(fdir, odentry, tdir, ndentry, NULL); + unlock_kernel(); + if (!err && EX_ISSYNC(tfhp->fh_export)) { + nfsd_sync_dir(tdentry); +--- lum/fs/open.c~lustre 2002-12-04 01:39:12.000000000 -0700 ++++ lum-root/fs/open.c 2002-12-04 01:39:12.000000000 -0700 @@ -19,6 +19,9 @@ #include @@ -1025,7 +1025,7 @@ int vfs_statfs(struct super_block *sb, struct statfs *buf) { -@@ -118,12 +121,13 @@ +@@ -118,12 +121,13 @@ static inline long do_sys_truncate(const struct nameidata nd; struct inode * inode; int error; @@ -1040,7 +1040,7 @@ if (error) goto out; inode = nd.dentry->d_inode; -@@ -168,6 +172,7 @@ +@@ -168,6 +172,7 @@ static inline long do_sys_truncate(const put_write_access(inode); dput_and_out: @@ -1048,7 +1048,7 @@ path_release(&nd); out: return error; -@@ -259,8 +264,9 @@ +@@ -259,8 +264,9 @@ asmlinkage long sys_utime(char * filenam struct nameidata nd; struct inode * inode; struct iattr newattrs; @@ -1059,7 +1059,7 @@ if (error) goto out; inode = nd.dentry->d_inode; -@@ -286,6 +292,7 @@ +@@ -286,6 +292,7 @@ asmlinkage long sys_utime(char * filenam } error = notify_change(nd.dentry, &newattrs); dput_and_out: @@ -1067,7 +1067,7 @@ path_release(&nd); out: return error; -@@ -303,8 +310,9 @@ +@@ -303,8 +310,9 @@ asmlinkage long sys_utimes(char * filena struct nameidata nd; struct inode * inode; struct iattr newattrs; @@ -1078,7 +1078,7 @@ if (error) goto out; -@@ -331,6 +339,7 @@ +@@ -331,6 +339,7 @@ asmlinkage long sys_utimes(char * filena } error = notify_change(nd.dentry, &newattrs); dput_and_out: @@ -1086,7 +1086,7 @@ path_release(&nd); out: return error; -@@ -347,6 +356,7 @@ +@@ -347,6 +356,7 @@ asmlinkage long sys_access(const char * int old_fsuid, old_fsgid; kernel_cap_t old_cap; int res; @@ -1094,7 +1094,7 @@ if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */ return -EINVAL; -@@ -364,13 +374,14 @@ +@@ -364,13 +374,14 @@ asmlinkage long sys_access(const char * else current->cap_effective = current->cap_permitted; @@ -1110,7 +1110,7 @@ path_release(&nd); } -@@ -385,8 +396,11 @@ +@@ -385,8 +396,11 @@ asmlinkage long sys_chdir(const char * f { int error; struct nameidata nd; @@ -1123,7 +1123,7 @@ if (error) goto out; -@@ -397,6 +411,7 @@ +@@ -397,6 +411,7 @@ asmlinkage long sys_chdir(const char * f set_fs_pwd(current->fs, nd.mnt, nd.dentry); dput_and_out: @@ -1131,7 +1131,7 @@ path_release(&nd); out: return error; -@@ -436,9 +451,10 @@ +@@ -436,9 +451,10 @@ asmlinkage long sys_chroot(const char * { int error; struct nameidata nd; @@ -1144,7 +1144,7 @@ if (error) goto out; -@@ -454,6 +470,7 @@ +@@ -454,6 +470,7 @@ asmlinkage long sys_chroot(const char * set_fs_altroot(); error = 0; dput_and_out: @@ -1152,7 +1152,7 @@ path_release(&nd); out: return error; -@@ -498,8 +515,9 @@ +@@ -498,8 +515,9 @@ asmlinkage long sys_chmod(const char * f struct inode * inode; int error; struct iattr newattrs; @@ -1163,7 +1163,7 @@ if (error) goto out; inode = nd.dentry->d_inode; -@@ -519,6 +537,7 @@ +@@ -519,6 +537,7 @@ asmlinkage long sys_chmod(const char * f error = notify_change(nd.dentry, &newattrs); dput_and_out: @@ -1171,7 +1171,7 @@ path_release(&nd); out: return error; -@@ -588,10 +607,12 @@ +@@ -588,10 +607,12 @@ asmlinkage long sys_chown(const char * f { struct nameidata nd; int error; @@ -1185,7 +1185,7 @@ path_release(&nd); } return error; -@@ -601,10 +622,12 @@ +@@ -601,10 +622,12 @@ asmlinkage long sys_lchown(const char * { struct nameidata nd; int error; @@ -1199,7 +1199,7 @@ path_release(&nd); } return error; -@@ -638,10 +661,16 @@ +@@ -638,10 +661,16 @@ asmlinkage long sys_fchown(unsigned int * for the internal routines (ie open_namei()/follow_link() etc). 00 is * used by symlinks. */ @@ -1216,7 +1216,7 @@ namei_flags = flags; if ((namei_flags+1) & O_ACCMODE) -@@ -649,18 +678,19 @@ +@@ -649,18 +678,19 @@ struct file *filp_open(const char * file if (namei_flags & O_TRUNC) namei_flags |= 2; @@ -1241,7 +1241,7 @@ { struct file * f; struct inode *inode; -@@ -711,6 +741,7 @@ +@@ -711,6 +741,7 @@ struct file *dentry_open(struct dentry * do_readahead(f, 0, (48 * 1024) >> PAGE_SHIFT); @@ -1249,7 +1249,7 @@ return f; cleanup_all: -@@ -725,11 +756,17 @@ +@@ -725,11 +756,17 @@ cleanup_all: cleanup_file: put_filp(f); cleanup_dentry: @@ -1267,8 +1267,8 @@ /* * Find an empty file descriptor entry, and mark it busy. */ ---- linux-2.4.18-17.8.0-uml-pristine/fs/stat.c 2002-10-19 11:43:53.000000000 -0600 -+++ linux-2.4.18-17.8.0-uml/fs/stat.c 2002-10-19 11:44:51.000000000 -0600 +--- lum/fs/stat.c~lustre 2002-12-04 01:39:12.000000000 -0700 ++++ lum-root/fs/stat.c 2002-12-04 01:39:12.000000000 -0700 @@ -13,6 +13,7 @@ #include @@ -1277,7 +1277,7 @@ /* * Revalidate the inode. This is required for proper NFS attribute caching. */ -@@ -104,10 +105,12 @@ +@@ -104,10 +105,12 @@ int vfs_stat(char *name, struct kstat *s { struct nameidata nd; int error; @@ -1291,7 +1291,7 @@ path_release(&nd); } return error; -@@ -117,10 +120,12 @@ +@@ -117,10 +120,12 @@ int vfs_lstat(char *name, struct kstat * { struct nameidata nd; int error; @@ -1305,9 +1305,9 @@ path_release(&nd); } return error; ---- linux-2.4.18-17.8.0-uml-pristine/mm/slab.c 2002-10-19 11:43:54.000000000 -0600 -+++ linux-2.4.18-17.8.0-uml/mm/slab.c 2002-10-19 11:44:51.000000000 -0600 -@@ -1208,6 +1208,59 @@ +--- lum/mm/slab.c~lustre 2002-12-04 01:39:12.000000000 -0700 ++++ lum-root/mm/slab.c 2002-12-04 01:39:12.000000000 -0700 +@@ -1208,6 +1208,59 @@ failed: * Called with the cache-lock held. */ @@ -1367,3 +1367,5 @@ #if DEBUG static int kmem_extra_free_checks (kmem_cache_t * cachep, slab_t *slabp, void * objp) + +_ diff --git a/lustre/patches/patch-2.4.18-hp1_pnnl18.2.8qsnet b/lustre/patches/patch-2.4.18-hp1_pnnl18.2.8qsnet new file mode 100644 index 0000000..356cc37 --- /dev/null +++ b/lustre/patches/patch-2.4.18-hp1_pnnl18.2.8qsnet @@ -0,0 +1,1673 @@ +--- linux-pristine/./include/linux/lustre_version.h Wed Dec 31 19:00:00 1969 ++++ linux/./include/linux/lustre_version.h Tue Nov 26 07:02:14 2002 +@@ -0,0 +1 @@ ++#define LUSTRE_KERNEL_VERSION 3 +--- linux-pristine/./arch/ia64/mm/init.c Thu Dec 5 10:47:25 2002 ++++ linux/./arch/ia64/mm/init.c Fri Nov 29 18:06:20 2002 +@@ -44,6 +44,12 @@ + + static struct page *vmem_map; + ++struct page *check_get_page(unsigned long kaddr) ++{ ++#warning FIXME: Lustre team, is this solid? ++ return virt_to_page(kaddr); ++} ++ + int + do_check_pgt_cache (int low, int high) + { +--- linux-pristine/./arch/i386/mm/init.c Thu Dec 5 10:47:24 2002 ++++ linux/./arch/i386/mm/init.c Fri Nov 29 18:06:20 2002 +@@ -43,6 +43,12 @@ + static unsigned long totalram_pages; + static unsigned long totalhigh_pages; + ++struct page *check_get_page(unsigned long kaddr) ++{ ++#warning FIXME: Lustre team, is this solid? ++ return virt_to_page(kaddr); ++} ++ + int do_check_pgt_cache(int low, int high) + { + int freed = 0; +--- linux-pristine/./drivers/block/blkpg.c Thu Dec 5 10:47:36 2002 ++++ linux/./drivers/block/blkpg.c Fri Nov 29 18:08:05 2002 +@@ -308,6 +308,41 @@ + + EXPORT_SYMBOL(blk_ioctl); + ++#define NUM_DEV_NO_WRITE 16 ++static int dev_no_write[NUM_DEV_NO_WRITE]; ++ ++/* ++ * Debug code for turning block devices "read-only" (will discard writes ++ * silently). This is for filesystem crash/recovery testing. ++ */ ++void dev_set_rdonly(kdev_t dev, int no_write) ++{ ++ if (dev) { ++ printk(KERN_WARNING "Turning device %s read-only\n", ++ bdevname(dev)); ++ dev_no_write[no_write] = 0xdead0000 + dev; ++ } ++} ++ ++int dev_check_rdonly(kdev_t dev) { ++ int i; ++ ++ for (i = 0; i < NUM_DEV_NO_WRITE; i++) { ++ if ((dev_no_write[i] & 0xffff0000) == 0xdead0000 && ++ dev == (dev_no_write[i] & 0xffff)) ++ return 1; ++ } ++ return 0; ++} ++ ++void dev_clear_rdonly(int no_write) { ++ dev_no_write[no_write] = 0; ++} ++ ++EXPORT_SYMBOL(dev_set_rdonly); ++EXPORT_SYMBOL(dev_check_rdonly); ++EXPORT_SYMBOL(dev_clear_rdonly); ++ + /********************* + * get_last_sector() + * +--- linux-pristine/./drivers/block/loop.c Thu Dec 5 10:47:37 2002 ++++ linux/./drivers/block/loop.c Fri Nov 29 18:06:20 2002 +@@ -471,6 +471,11 @@ + spin_unlock_irq(&lo->lo_lock); + + if (rw == WRITE) { ++#ifdef CONFIG_DEV_RDONLY ++ if (dev_check_rdonly(rbh->b_rdev)) ++ goto err; ++#endif ++ + if (lo->lo_flags & LO_FLAGS_READ_ONLY) + goto err; + } else if (rw == READA) { +--- linux-pristine/./drivers/ide/ide-disk.c Thu Dec 5 10:47:59 2002 ++++ linux/./drivers/ide/ide-disk.c Fri Nov 29 18:06:20 2002 +@@ -367,6 +367,12 @@ + */ + static ide_startstop_t do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block) + { ++#ifdef CONFIG_DEV_RDONLY ++ if (rq->cmd == WRITE && dev_check_rdonly(rq->rq_dev)) { ++ ide_end_request(1, HWGROUP(drive)); ++ return ide_stopped; ++ } ++#endif + if (IDE_CONTROL_REG) + OUT_BYTE(drive->ctl,IDE_CONTROL_REG); + OUT_BYTE(0x00, IDE_FEATURE_REG); +--- linux-pristine/./fs/ext3/Makefile Thu Dec 5 10:49:13 2002 ++++ linux/./fs/ext3/Makefile Fri Nov 29 18:06:20 2002 +@@ -9,6 +9,8 @@ + + O_TARGET := ext3.o + ++export-objs := super.o ++ + obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \ + ioctl.o namei.o super.o symlink.o + obj-m := $(O_TARGET) +--- linux-pristine/./fs/ext3/super.c Thu Dec 5 10:49:13 2002 ++++ linux/./fs/ext3/super.c Fri Nov 29 18:06:20 2002 +@@ -1744,7 +1744,7 @@ + unregister_filesystem(&ext3_fs_type); + } + +-EXPORT_NO_SYMBOLS; ++EXPORT_SYMBOL(ext3_bread); + + MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others"); + MODULE_DESCRIPTION("Second Extended Filesystem with journaling extensions"); +--- linux-pristine/./fs/jbd/commit.c Thu Dec 5 10:49:15 2002 ++++ linux/./fs/jbd/commit.c Fri Nov 29 18:06:20 2002 +@@ -475,7 +475,7 @@ + transaction's t_log_list queue, and metadata buffers are on + the t_iobuf_list queue. + +- Wait for the transactions in reverse order. That way we are ++ Wait for the buffers in reverse order. That way we are + less likely to be woken up until all IOs have completed, and + so we incur less scheduling load. + */ +@@ -566,8 +566,10 @@ + + jbd_debug(3, "JBD: commit phase 6\n"); + +- if (is_journal_aborted(journal)) ++ if (is_journal_aborted(journal)) { ++ unlock_journal(journal); + goto skip_commit; ++ } + + /* Done it all: now write the commit record. We should have + * cleaned up our previous buffers by now, so if we are in abort +@@ -577,6 +579,7 @@ + descriptor = journal_get_descriptor_buffer(journal); + if (!descriptor) { + __journal_abort_hard(journal); ++ unlock_journal(journal); + goto skip_commit; + } + +@@ -600,7 +603,6 @@ + put_bh(bh); /* One for getblk() */ + journal_unlock_journal_head(descriptor); + } +- lock_journal(journal); + + /* End of a transaction! Finally, we can do checkpoint + processing: any buffers committed as a result of this +@@ -609,6 +611,25 @@ + + skip_commit: + ++ /* Call any callbacks that had been registered for handles in this ++ * transaction. It is up to the callback to free any allocated ++ * memory. ++ */ ++ if (!list_empty(&commit_transaction->t_jcb)) { ++ struct list_head *p, *n; ++ int error = is_journal_aborted(journal); ++ ++ list_for_each_safe(p, n, &commit_transaction->t_jcb) { ++ struct journal_callback *jcb; ++ ++ jcb = list_entry(p, struct journal_callback, jcb_list); ++ list_del(p); ++ jcb->jcb_func(jcb, error); ++ } ++ } ++ ++ lock_journal(journal); ++ + jbd_debug(3, "JBD: commit phase 7\n"); + + J_ASSERT(commit_transaction->t_sync_datalist == NULL); +--- linux-pristine/./fs/jbd/journal.c Thu Dec 5 10:49:15 2002 ++++ linux/./fs/jbd/journal.c Fri Nov 29 18:06:20 2002 +@@ -58,6 +58,7 @@ + #endif + EXPORT_SYMBOL(journal_flush); + EXPORT_SYMBOL(journal_revoke); ++EXPORT_SYMBOL(journal_callback_set); + + EXPORT_SYMBOL(journal_init_dev); + EXPORT_SYMBOL(journal_init_inode); +--- linux-pristine/./fs/jbd/transaction.c Thu Dec 5 10:49:15 2002 ++++ linux/./fs/jbd/transaction.c Fri Nov 29 18:06:20 2002 +@@ -57,6 +57,7 @@ + transaction->t_state = T_RUNNING; + transaction->t_tid = journal->j_transaction_sequence++; + transaction->t_expires = jiffies + journal->j_commit_interval; ++ INIT_LIST_HEAD(&transaction->t_jcb); + + /* Set up the commit timer for the new transaction. */ + J_ASSERT (!journal->j_commit_timer_active); +@@ -201,6 +202,20 @@ + return 0; + } + ++/* Allocate a new handle. This should probably be in a slab... */ ++static handle_t *new_handle(int nblocks) ++{ ++ handle_t *handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS); ++ if (!handle) ++ return NULL; ++ memset(handle, 0, sizeof (handle_t)); ++ handle->h_buffer_credits = nblocks; ++ handle->h_ref = 1; ++ INIT_LIST_HEAD(&handle->h_jcb); ++ ++ return handle; ++} ++ + /* + * Obtain a new handle. + * +@@ -227,14 +242,11 @@ + handle->h_ref++; + return handle; + } +- +- handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS); ++ ++ handle = new_handle(nblocks); + if (!handle) + return ERR_PTR(-ENOMEM); +- memset (handle, 0, sizeof (handle_t)); + +- handle->h_buffer_credits = nblocks; +- handle->h_ref = 1; + current->journal_info = handle; + + err = start_this_handle(journal, handle); +@@ -333,14 +345,11 @@ + + if (is_journal_aborted(journal)) + return ERR_PTR(-EIO); +- +- handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS); ++ ++ handle = new_handle(nblocks); + if (!handle) + return ERR_PTR(-ENOMEM); +- memset (handle, 0, sizeof (handle_t)); + +- handle->h_buffer_credits = nblocks; +- handle->h_ref = 1; + current->journal_info = handle; + + err = try_start_this_handle(journal, handle); +@@ -1328,6 +1337,28 @@ + #endif + + /* ++ * Register a callback function for this handle. The function will be ++ * called when the transaction that this handle is part of has been ++ * committed to disk with the original callback data struct and the ++ * error status of the journal as parameters. There is no guarantee of ++ * ordering between handles within a single transaction, nor between ++ * callbacks registered on the same handle. ++ * ++ * The caller is responsible for allocating the journal_callback struct. ++ * This is to allow the caller to add as much extra data to the callback ++ * as needed, but reduce the overhead of multiple allocations. The caller ++ * allocated struct must start with a struct journal_callback at offset 0, ++ * and has the caller-specific data afterwards. ++ */ ++void journal_callback_set(handle_t *handle, ++ void (*func)(struct journal_callback *jcb, int error), ++ struct journal_callback *jcb) ++{ ++ list_add(&jcb->jcb_list, &handle->h_jcb); ++ jcb->jcb_func = func; ++} ++ ++/* + * All done for a particular handle. + * + * There is not much action needed here. We just return any remaining +@@ -1393,7 +1424,10 @@ + wake_up(&journal->j_wait_transaction_locked); + } + +- /* ++ /* Move callbacks from the handle to the transaction. */ ++ list_splice(&handle->h_jcb, &transaction->t_jcb); ++ ++ /* + * If the handle is marked SYNC, we need to set another commit + * going! We also want to force a commit if the current + * transaction is occupying too much of the log, or if the +--- linux-pristine/./include/linux/blkdev.h Thu Dec 5 10:49:41 2002 ++++ linux/./include/linux/blkdev.h Fri Nov 29 18:30:34 2002 +@@ -228,4 +228,8 @@ + return retval; + } + ++#define CONFIG_DEV_RDONLY ++void dev_set_rdonly(kdev_t, int); ++int dev_check_rdonly(kdev_t); ++void dev_clear_rdonly(int); + #endif +--- linux-pristine/./include/linux/slab.h Thu Dec 5 10:49:53 2002 ++++ linux/./include/linux/slab.h Fri Nov 29 18:30:15 2002 +@@ -58,6 +58,7 @@ + extern void *kmem_cache_alloc(kmem_cache_t *, int); + extern void *kmem_cache_zalloc(kmem_cache_t *, int); + extern void kmem_cache_free(kmem_cache_t *, void *); ++extern int kmem_cache_validate(kmem_cache_t *cachep, void *objp); + + extern void *kmalloc(size_t, int); + extern void kfree(const void *); +--- linux-pristine/./include/linux/jbd.h Thu Dec 5 10:49:43 2002 ++++ linux/./include/linux/jbd.h Fri Nov 29 18:50:01 2002 +@@ -249,6 +249,13 @@ + return bh->b_private; + } + ++#define HAVE_JOURNAL_CALLBACK_STATUS ++struct journal_callback { ++ struct list_head jcb_list; ++ void (*jcb_func)(struct journal_callback *jcb, int error); ++ /* user data goes here */ ++}; ++ + struct jbd_revoke_table_s; + + /* The handle_t type represents a single atomic update being performed +@@ -279,6 +286,12 @@ + operations */ + int h_err; + ++ /* List of application registered callbacks for this handle. ++ * The function(s) will be called after the transaction that ++ * this handle is part of has been committed to disk. ++ */ ++ struct list_head h_jcb; ++ + /* Flags */ + unsigned int h_sync: 1; /* sync-on-close */ + unsigned int h_jdata: 1; /* force data journaling */ +@@ -398,6 +411,10 @@ + + /* How many handles used this transaction? */ + int t_handle_count; ++ ++ /* List of registered callback functions for this transaction. ++ * Called when the transaction is committed. */ ++ struct list_head t_jcb; + }; + + +@@ -646,6 +663,9 @@ + extern int journal_try_to_free_buffers(journal_t *, struct page *, int); + extern int journal_stop(handle_t *); + extern int journal_flush (journal_t *); ++extern void journal_callback_set(handle_t *handle, ++ void (*fn)(struct journal_callback *,int), ++ struct journal_callback *jcb); + + extern void journal_lock_updates (journal_t *); + extern void journal_unlock_updates (journal_t *); +--- linux-pristine/./kernel/ksyms.c Thu Dec 5 10:50:01 2002 ++++ linux/./kernel/ksyms.c Fri Nov 29 18:37:23 2002 +@@ -271,6 +271,7 @@ + EXPORT_SYMBOL(set_page_dirty); + EXPORT_SYMBOL(vfs_readlink); + EXPORT_SYMBOL(vfs_follow_link); ++EXPORT_SYMBOL(vfs_follow_link_it); + EXPORT_SYMBOL(page_readlink); + EXPORT_SYMBOL(page_follow_link); + EXPORT_SYMBOL(page_symlink_inode_operations); +@@ -285,6 +286,11 @@ + EXPORT_SYMBOL(nr_free_pages); + EXPORT_SYMBOL(page_cache_size); + ++/* lustre */ ++EXPORT_SYMBOL(pagecache_lock); ++EXPORT_SYMBOL(do_kern_mount); ++EXPORT_SYMBOL(kmem_cache_validate); ++ + /* for stackable file systems (lofs, wrapfs, cryptfs, etc.) */ + EXPORT_SYMBOL(default_llseek); + EXPORT_SYMBOL(dentry_open); +--- linux-pristine/./include/linux/dcache.h Thu Dec 5 10:49:42 2002 ++++ linux/./include/linux/dcache.h Fri Nov 29 18:30:11 2002 +@@ -6,6 +6,34 @@ + #include + #include + ++#define IT_OPEN (1) ++#define IT_CREAT (1<<1) ++#define IT_MKDIR (1<<2) ++#define IT_LINK (1<<3) ++#define IT_LINK2 (1<<4) ++#define IT_SYMLINK (1<<5) ++#define IT_UNLINK (1<<6) ++#define IT_RMDIR (1<<7) ++#define IT_RENAME (1<<8) ++#define IT_RENAME2 (1<<9) ++#define IT_READDIR (1<<10) ++#define IT_GETATTR (1<<11) ++#define IT_SETATTR (1<<12) ++#define IT_READLINK (1<<13) ++#define IT_MKNOD (1<<14) ++#define IT_LOOKUP (1<<15) ++ ++struct lookup_intent { ++ int it_op; ++ int it_mode; ++ int it_disposition; ++ int it_status; ++ struct iattr *it_iattr; ++ __u64 it_lock_handle[2]; ++ int it_lock_mode; ++ void *it_data; ++}; ++ + /* + * linux/include/linux/dcache.h + * +@@ -78,6 +106,7 @@ + unsigned long d_time; /* used by d_revalidate */ + struct dentry_operations *d_op; + struct super_block * d_sb; /* The root of the dentry tree */ ++ struct lookup_intent *d_it; + unsigned long d_vfs_flags; + void * d_fsdata; /* fs-specific data */ + unsigned char d_iname[DNAME_INLINE_LEN]; /* small names */ +@@ -90,6 +119,8 @@ + int (*d_delete)(struct dentry *); + void (*d_release)(struct dentry *); + void (*d_iput)(struct dentry *, struct inode *); ++ int (*d_revalidate2)(struct dentry *, int, struct lookup_intent *); ++ void (*d_intent_release)(struct dentry *, struct lookup_intent *); + }; + + /* the dentry parameter passed to d_hash and d_compare is the parent +--- linux-pristine/./include/linux/fs.h Thu Dec 5 10:49:42 2002 ++++ linux/./include/linux/fs.h Fri Nov 29 18:30:15 2002 +@@ -588,6 +588,7 @@ + + /* needed for tty driver, and maybe others */ + void *private_data; ++ struct lookup_intent *f_intent; + + /* preallocated helper kiobuf to speedup O_DIRECT */ + struct kiobuf *f_iobuf; +@@ -849,7 +850,9 @@ + extern int vfs_link(struct dentry *, struct inode *, struct dentry *); + extern int vfs_rmdir(struct inode *, struct dentry *); + extern int vfs_unlink(struct inode *, struct dentry *); +-extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); ++int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, ++ struct inode *new_dir, struct dentry *new_dentry, ++ struct lookup_intent *it); + + /* + * File types +@@ -911,6 +914,7 @@ + struct inode_operations { + int (*create) (struct inode *,struct dentry *,int); + struct dentry * (*lookup) (struct inode *,struct dentry *); ++ struct dentry * (*lookup2) (struct inode *,struct dentry *, struct lookup_intent *); + int (*link) (struct dentry *,struct inode *,struct dentry *); + int (*unlink) (struct inode *,struct dentry *); + int (*symlink) (struct inode *,struct dentry *,const char *); +@@ -921,6 +925,8 @@ + struct inode *, struct dentry *); + int (*readlink) (struct dentry *, char *,int); + int (*follow_link) (struct dentry *, struct nameidata *); ++ int (*follow_link2) (struct dentry *, struct nameidata *, ++ struct lookup_intent *it); + void (*truncate) (struct inode *); + int (*permission) (struct inode *, int); + int (*revalidate) (struct dentry *); +@@ -1063,7 +1069,7 @@ + extern struct vfsmount *kern_mount(struct file_system_type *); + extern int may_umount(struct vfsmount *); + extern long do_mount(char *, char *, char *, unsigned long, void *); +- ++struct vfsmount *do_kern_mount(char *type, int flags, char *name, void *data); + #define kern_umount mntput + + extern int vfs_statfs(struct super_block *, struct statfs *); +@@ -1387,6 +1393,7 @@ + extern loff_t default_llseek(struct file *file, loff_t offset, int origin); + + extern int FASTCALL(__user_walk(const char *, unsigned, struct nameidata *)); ++extern int FASTCALL(__user_walk_it(const char *, unsigned, struct nameidata *, struct lookup_intent *it)); + extern int FASTCALL(path_init(const char *, unsigned, struct nameidata *)); + extern int FASTCALL(path_walk(const char *, struct nameidata *)); + extern int FASTCALL(link_path_walk(const char *, struct nameidata *)); +@@ -1397,6 +1404,8 @@ + 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) ++#define user_path_walk_it(name,nd,it) __user_walk_it(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd, it) ++#define user_path_walk_link_it(name,nd,it) __user_walk_it(name, LOOKUP_POSITIVE, nd, it) + + extern void iput(struct inode *); + extern void force_delete(struct inode *); +@@ -1508,6 +1517,8 @@ + + extern int vfs_readlink(struct dentry *, char *, int, const char *); + extern int vfs_follow_link(struct nameidata *, const char *); ++extern int vfs_follow_link_it(struct nameidata *, const char *, ++ struct lookup_intent *it); + extern int page_readlink(struct dentry *, char *, int); + extern int page_follow_link(struct dentry *, struct nameidata *); + extern struct inode_operations page_symlink_inode_operations; +--- linux-pristine/./fs/dcache.c Thu Dec 5 10:49:13 2002 ++++ linux/./fs/dcache.c Fri Nov 29 18:06:20 2002 +@@ -617,6 +617,7 @@ + dentry->d_op = NULL; + dentry->d_fsdata = NULL; + dentry->d_mounted = 0; ++ dentry->d_it = NULL; + INIT_LIST_HEAD(&dentry->d_hash); + INIT_LIST_HEAD(&dentry->d_lru); + INIT_LIST_HEAD(&dentry->d_subdirs); +--- linux-pristine/./fs/nfsd/vfs.c Thu Dec 5 10:49:18 2002 ++++ linux/./fs/nfsd/vfs.c Fri Nov 29 18:06:20 2002 +@@ -1285,7 +1285,7 @@ + err = nfserr_perm; + } else + #endif +- err = vfs_rename(fdir, odentry, tdir, ndentry); ++ err = vfs_rename(fdir, odentry, tdir, ndentry, NULL); + if (!err && EX_ISSYNC(tfhp->fh_export)) { + nfsd_sync_dir(tdentry); + nfsd_sync_dir(fdentry); +--- linux-pristine/./fs/namei.c Thu Dec 5 10:49:16 2002 ++++ linux/./fs/namei.c Fri Nov 29 18:11:18 2002 +@@ -94,6 +94,12 @@ + * XEmacs seems to be relying on it... + */ + ++void intent_release(struct dentry *de, struct lookup_intent *it) ++{ ++ if (de->d_op && de->d_op->d_intent_release) ++ de->d_op->d_intent_release(de, it); ++} ++ + /* In order to reduce some races, while at the same time doing additional + * checking and hopefully speeding things up, we copy filenames to the + * kernel data space before using them.. +@@ -260,10 +266,19 @@ + * Internal lookup() using the new generic dcache. + * SMP-safe + */ +-static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, int flags) ++static struct dentry *cached_lookup(struct dentry *parent, struct qstr *name, ++ int flags, struct lookup_intent *it) + { + struct dentry * dentry = d_lookup(parent, name); + ++ if (dentry && dentry->d_op && dentry->d_op->d_revalidate2) { ++ if (!dentry->d_op->d_revalidate2(dentry, flags, it) && ++ !d_invalidate(dentry)) { ++ dput(dentry); ++ dentry = NULL; ++ } ++ return dentry; ++ } else + if (dentry && dentry->d_op && dentry->d_op->d_revalidate) { + if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) { + dput(dentry); +@@ -281,7 +296,8 @@ + * make sure that nobody added the entry to the dcache in the meantime.. + * SMP-safe + */ +-static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, int flags) ++static struct dentry *real_lookup(struct dentry *parent, struct qstr *name, ++ int flags, struct lookup_intent *it) + { + struct dentry * result; + struct inode *dir = parent->d_inode; +@@ -300,6 +316,9 @@ + result = ERR_PTR(-ENOMEM); + if (dentry) { + lock_kernel(); ++ if (dir->i_op->lookup2) ++ result = dir->i_op->lookup2(dir, dentry, it); ++ else + result = dir->i_op->lookup(dir, dentry); + unlock_kernel(); + if (result) +@@ -321,6 +340,12 @@ + dput(result); + result = ERR_PTR(-ENOENT); + } ++ } else if (result->d_op && result->d_op->d_revalidate2) { ++ if (!result->d_op->d_revalidate2(result, flags, it) && ++ !d_invalidate(result)) { ++ dput(result); ++ result = ERR_PTR(-ENOENT); ++ } + } + return result; + } +@@ -332,7 +357,8 @@ + * Without that kind of total limit, nasty chains of consecutive + * symlinks can cause almost arbitrarily long lookups. + */ +-static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd) ++static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd, ++ struct lookup_intent *it) + { + int err; + if (current->link_count >= 5) +@@ -346,10 +372,14 @@ + current->link_count++; + current->total_link_count++; + UPDATE_ATIME(dentry->d_inode); +- err = dentry->d_inode->i_op->follow_link(dentry, nd); ++ if (dentry->d_inode->i_op->follow_link2) ++ err = dentry->d_inode->i_op->follow_link2(dentry, nd, it); ++ else ++ err = dentry->d_inode->i_op->follow_link(dentry, nd); + current->link_count--; + return err; + loop: ++ intent_release(dentry, it); + path_release(nd); + return -ELOOP; + } +@@ -445,7 +475,8 @@ + * + * We expect 'base' to be positive and a directory. + */ +-int link_path_walk(const char * name, struct nameidata *nd) ++int link_path_walk_it(const char *name, struct nameidata *nd, ++ struct lookup_intent *it) + { + struct dentry *dentry; + struct inode *inode; +@@ -518,9 +549,9 @@ + break; + } + /* This does the actual lookups.. */ +- dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE); ++ dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE, NULL); + if (!dentry) { +- dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE); ++ dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE, NULL); + err = PTR_ERR(dentry); + if (IS_ERR(dentry)) + break; +@@ -537,8 +568,8 @@ + if (!inode->i_op) + goto out_dput; + +- if (inode->i_op->follow_link) { +- err = do_follow_link(dentry, nd); ++ if (inode->i_op->follow_link || inode->i_op->follow_link2) { ++ err = do_follow_link(dentry, nd, it); + dput(dentry); + if (err) + goto return_err; +@@ -554,7 +585,7 @@ + nd->dentry = dentry; + } + err = -ENOTDIR; +- if (!inode->i_op->lookup) ++ if (!inode->i_op->lookup && !inode->i_op->lookup2) + break; + continue; + /* here ends the main loop */ +@@ -581,9 +612,9 @@ + if (err < 0) + break; + } +- dentry = cached_lookup(nd->dentry, &this, 0); ++ dentry = cached_lookup(nd->dentry, &this, 0, it); + if (!dentry) { +- dentry = real_lookup(nd->dentry, &this, 0); ++ dentry = real_lookup(nd->dentry, &this, 0, it); + err = PTR_ERR(dentry); + if (IS_ERR(dentry)) + break; +@@ -591,9 +622,9 @@ + while (d_mountpoint(dentry) && __follow_down(&nd->mnt, &dentry)) + ; + inode = dentry->d_inode; +- if ((lookup_flags & LOOKUP_FOLLOW) +- && inode && inode->i_op && inode->i_op->follow_link) { +- err = do_follow_link(dentry, nd); ++ if ((lookup_flags & LOOKUP_FOLLOW) && inode && inode->i_op && ++ (inode->i_op->follow_link || inode->i_op->follow_link2)) { ++ err = do_follow_link(dentry, nd, it); + dput(dentry); + if (err) + goto return_err; +@@ -607,7 +638,8 @@ + goto no_inode; + if (lookup_flags & LOOKUP_DIRECTORY) { + err = -ENOTDIR; +- if (!inode->i_op || !inode->i_op->lookup) ++ if (!inode->i_op || ++ (!inode->i_op->lookup && !inode->i_op->lookup2)) + break; + } + goto return_base; +@@ -636,10 +668,21 @@ + return err; + } + ++int link_path_walk(const char * name, struct nameidata *nd) ++{ ++ return link_path_walk_it(name, nd, NULL); ++} ++ ++int path_walk_it(const char * name, struct nameidata *nd, struct lookup_intent *it) ++{ ++ current->total_link_count = 0; ++ return link_path_walk_it(name, nd, it); ++} ++ + int path_walk(const char * name, struct nameidata *nd) + { + current->total_link_count = 0; +- return link_path_walk(name, nd); ++ return link_path_walk_it(name, nd, NULL); + } + + /* SMP-safe */ +@@ -742,7 +785,8 @@ + * needs parent already locked. Doesn't follow mounts. + * SMP-safe. + */ +-struct dentry * lookup_hash(struct qstr *name, struct dentry * base) ++struct dentry * lookup_hash_it(struct qstr *name, struct dentry * base, ++ struct lookup_intent *it) + { + struct dentry * dentry; + struct inode *inode; +@@ -765,13 +809,16 @@ + goto out; + } + +- dentry = cached_lookup(base, name, 0); ++ dentry = cached_lookup(base, name, 0, it); + if (!dentry) { + struct dentry *new = d_alloc(base, name); + dentry = ERR_PTR(-ENOMEM); + if (!new) + goto out; + lock_kernel(); ++ if (inode->i_op->lookup2) ++ dentry = inode->i_op->lookup2(inode, new, it); ++ else + dentry = inode->i_op->lookup(inode, new); + unlock_kernel(); + if (!dentry) +@@ -783,6 +830,12 @@ + return dentry; + } + ++struct dentry * lookup_hash(struct qstr *name, struct dentry * base) ++{ ++ return lookup_hash_it(name, base, NULL); ++} ++ ++ + /* SMP-safe */ + struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) + { +@@ -804,7 +857,7 @@ + } + this.hash = end_name_hash(hash); + +- return lookup_hash(&this, base); ++ return lookup_hash_it(&this, base, NULL); + access: + return ERR_PTR(-EACCES); + } +@@ -836,6 +889,23 @@ + return err; + } + ++int __user_walk_it(const char *name, unsigned flags, struct nameidata *nd, ++ struct lookup_intent *it) ++{ ++ char *tmp; ++ int err; ++ ++ tmp = getname(name); ++ err = PTR_ERR(tmp); ++ if (!IS_ERR(tmp)) { ++ err = 0; ++ if (path_init(tmp, flags, nd)) ++ err = path_walk_it(tmp, nd, it); ++ putname(tmp); ++ } ++ return err; ++} ++ + /* + * It's inline, so penalty for filesystems that don't use sticky bit is + * minimal. +@@ -970,7 +1040,8 @@ + * for symlinks (where the permissions are checked later). + * SMP-safe + */ +-int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) ++int open_namei_it(const char *pathname, int flag, int mode, ++ struct nameidata *nd, struct lookup_intent *it) + { + int acc_mode, error = 0; + struct inode *inode; +@@ -985,7 +1056,7 @@ + */ + if (!(flag & O_CREAT)) { + if (path_init(pathname, lookup_flags(flag), nd)) +- error = path_walk(pathname, nd); ++ error = path_walk_it(pathname, nd, it); + if (error) + return error; + dentry = nd->dentry; +@@ -995,6 +1066,10 @@ + /* + * Create - we need to know the parent. + */ ++ if (it) { ++ it->it_mode = mode; ++ it->it_op |= IT_CREAT; ++ } + if (path_init(pathname, LOOKUP_PARENT, nd)) + error = path_walk(pathname, nd); + if (error) +@@ -1011,7 +1086,7 @@ + + dir = nd->dentry; + down(&dir->d_inode->i_sem); +- dentry = lookup_hash(&nd->last, nd->dentry); ++ dentry = lookup_hash_it(&nd->last, nd->dentry, it); + + do_last: + error = PTR_ERR(dentry); +@@ -1020,6 +1095,7 @@ + goto exit; + } + ++ it->it_mode = mode; + /* Negative dentry, just create the file */ + if (!dentry->d_inode) { + if (!IS_POSIX_ACL(dir->d_inode)) +@@ -1054,7 +1130,8 @@ + error = -ENOENT; + if (!dentry->d_inode) + goto exit_dput; +- if (dentry->d_inode->i_op && dentry->d_inode->i_op->follow_link) ++ if (dentry->d_inode->i_op && (dentry->d_inode->i_op->follow_link || ++ dentry->d_inode->i_op->follow_link2)) + goto do_link; + + dput(nd->dentry); +@@ -1140,8 +1217,10 @@ + return 0; + + exit_dput: ++ intent_release(dentry, it); + dput(dentry); + exit: ++ intent_release(nd->dentry, it); + path_release(nd); + return error; + +@@ -1160,7 +1239,12 @@ + * are done. Procfs-like symlinks just set LAST_BIND. + */ + UPDATE_ATIME(dentry->d_inode); +- error = dentry->d_inode->i_op->follow_link(dentry, nd); ++ if (dentry->d_inode->i_op->follow_link2) ++ error = dentry->d_inode->i_op->follow_link2(dentry, nd, it); ++ else ++ error = dentry->d_inode->i_op->follow_link(dentry, nd); ++ if (error) ++ intent_release(dentry, it); + dput(dentry); + if (error) + return error; +@@ -1182,13 +1266,20 @@ + } + dir = nd->dentry; + down(&dir->d_inode->i_sem); +- dentry = lookup_hash(&nd->last, nd->dentry); ++ dentry = lookup_hash_it(&nd->last, nd->dentry, it); + putname(nd->last.name); + goto do_last; + } + ++int open_namei(const char *pathname, int flag, int mode, struct nameidata *nd) ++{ ++ return open_namei_it(pathname, flag, mode, nd, NULL); ++} ++ ++ + /* SMP-safe */ +-static struct dentry *lookup_create(struct nameidata *nd, int is_dir) ++static struct dentry *lookup_create(struct nameidata *nd, int is_dir, ++ struct lookup_intent *it) + { + struct dentry *dentry; + +@@ -1196,7 +1287,7 @@ + dentry = ERR_PTR(-EEXIST); + if (nd->last_type != LAST_NORM) + goto fail; +- dentry = lookup_hash(&nd->last, nd->dentry); ++ dentry = lookup_hash_it(&nd->last, nd->dentry, it); + if (IS_ERR(dentry)) + goto fail; + if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode) +@@ -1242,6 +1333,7 @@ + char * tmp; + struct dentry * dentry; + struct nameidata nd; ++ struct lookup_intent it = { .it_op = IT_MKNOD, .it_mode = mode }; + + if (S_ISDIR(mode)) + return -EPERM; +@@ -1253,7 +1345,7 @@ + error = path_walk(tmp, &nd); + if (error) + goto out; +- dentry = lookup_create(&nd, 0); ++ dentry = lookup_create(&nd, 0, &it); + error = PTR_ERR(dentry); + + if (!IS_POSIX_ACL(nd.dentry->d_inode)) +@@ -1272,6 +1364,7 @@ + default: + error = -EINVAL; + } ++ intent_release(dentry, &it); + dput(dentry); + } + up(&nd.dentry->d_inode->i_sem); +@@ -1312,6 +1405,7 @@ + { + int error = 0; + char * tmp; ++ struct lookup_intent it = { .it_op = IT_MKDIR, .it_mode = mode }; + + tmp = getname(pathname); + error = PTR_ERR(tmp); +@@ -1323,12 +1417,13 @@ + error = path_walk(tmp, &nd); + if (error) + goto out; +- dentry = lookup_create(&nd, 1); ++ dentry = lookup_create(&nd, 1, &it); + error = PTR_ERR(dentry); + if (!IS_ERR(dentry)) { + if (!IS_POSIX_ACL(nd.dentry->d_inode)) + mode &= ~current->fs->umask; + error = vfs_mkdir(nd.dentry->d_inode, dentry, mode); ++ intent_release(dentry, &it); + dput(dentry); + } + up(&nd.dentry->d_inode->i_sem); +@@ -1410,6 +1505,7 @@ + char * name; + struct dentry *dentry; + struct nameidata nd; ++ struct lookup_intent it = { .it_op = IT_RMDIR }; + + name = getname(pathname); + if(IS_ERR(name)) +@@ -1432,10 +1528,11 @@ + goto exit1; + } + down(&nd.dentry->d_inode->i_sem); +- dentry = lookup_hash(&nd.last, nd.dentry); ++ dentry = lookup_hash_it(&nd.last, nd.dentry, &it); + error = PTR_ERR(dentry); + if (!IS_ERR(dentry)) { + error = vfs_rmdir(nd.dentry->d_inode, dentry); ++ intent_release(dentry, &it); + dput(dentry); + } + up(&nd.dentry->d_inode->i_sem); +@@ -1479,6 +1576,7 @@ + char * name; + struct dentry *dentry; + struct nameidata nd; ++ struct lookup_intent it = { .it_op = IT_UNLINK }; + + name = getname(pathname); + if(IS_ERR(name)) +@@ -1492,7 +1590,7 @@ + if (nd.last_type != LAST_NORM) + goto exit1; + down(&nd.dentry->d_inode->i_sem); +- dentry = lookup_hash(&nd.last, nd.dentry); ++ dentry = lookup_hash_it(&nd.last, nd.dentry, &it); + error = PTR_ERR(dentry); + if (!IS_ERR(dentry)) { + /* Why not before? Because we want correct error value */ +@@ -1500,6 +1598,7 @@ + goto slashes; + error = vfs_unlink(nd.dentry->d_inode, dentry); + exit2: ++ intent_release(dentry, &it); + dput(dentry); + } + up(&nd.dentry->d_inode->i_sem); +@@ -1546,6 +1645,7 @@ + int error = 0; + char * from; + char * to; ++ struct lookup_intent it = { .it_op = IT_SYMLINK }; + + from = getname(oldname); + if(IS_ERR(from)) +@@ -1560,10 +1660,12 @@ + error = path_walk(to, &nd); + if (error) + goto out; +- dentry = lookup_create(&nd, 0); ++ it.it_data = from; ++ dentry = lookup_create(&nd, 0, &it); + error = PTR_ERR(dentry); + if (!IS_ERR(dentry)) { + error = vfs_symlink(nd.dentry->d_inode, dentry, from); ++ intent_release(dentry, &it); + dput(dentry); + } + up(&nd.dentry->d_inode->i_sem); +@@ -1629,6 +1731,7 @@ + int error; + char * from; + char * to; ++ struct lookup_intent it = { .it_op = IT_LINK }; + + from = getname(oldname); + if(IS_ERR(from)) +@@ -1641,7 +1744,7 @@ + + error = 0; + if (path_init(from, LOOKUP_POSITIVE, &old_nd)) +- error = path_walk(from, &old_nd); ++ error = path_walk_it(from, &old_nd, &it); + if (error) + goto exit; + if (path_init(to, LOOKUP_PARENT, &nd)) +@@ -1651,10 +1754,12 @@ + error = -EXDEV; + if (old_nd.mnt != nd.mnt) + goto out_release; +- new_dentry = lookup_create(&nd, 0); ++ it.it_op = IT_LINK2; ++ new_dentry = lookup_create(&nd, 0, &it); + error = PTR_ERR(new_dentry); + if (!IS_ERR(new_dentry)) { + error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry); ++ intent_release(new_dentry, &it); + dput(new_dentry); + } + up(&nd.dentry->d_inode->i_sem); +@@ -1697,7 +1802,8 @@ + * locking]. + */ + int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, +- struct inode *new_dir, struct dentry *new_dentry) ++ struct inode *new_dir, struct dentry *new_dentry, ++ struct lookup_intent *it) + { + int error; + struct inode *target; +@@ -1757,6 +1863,7 @@ + error = -EBUSY; + else + error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry); ++ intent_release(new_dentry, it); + if (target) { + if (!error) + target->i_flags |= S_DEAD; +@@ -1778,7 +1885,8 @@ + } + + int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry, +- struct inode *new_dir, struct dentry *new_dentry) ++ struct inode *new_dir, struct dentry *new_dentry, ++ struct lookup_intent *it) + { + int error; + +@@ -1809,6 +1917,7 @@ + error = -EBUSY; + else + error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry); ++ intent_release(new_dentry, it); + double_up(&old_dir->i_zombie, &new_dir->i_zombie); + if (error) + return error; +@@ -1820,13 +1929,14 @@ + } + + int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, +- struct inode *new_dir, struct dentry *new_dentry) ++ struct inode *new_dir, struct dentry *new_dentry, ++ struct lookup_intent *it) + { + int error; + if (S_ISDIR(old_dentry->d_inode->i_mode)) +- error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry); ++ error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry,it); + else +- error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry); ++ error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry,it); + if (!error) { + if (old_dir == new_dir) + inode_dir_notify(old_dir, DN_RENAME); +@@ -1843,6 +1953,7 @@ + int error = 0; + struct dentry * old_dir, * new_dir; + struct dentry * old_dentry, *new_dentry; ++ struct lookup_intent it = { .it_op = IT_RENAME }; + struct nameidata oldnd, newnd; + + if (path_init(oldname, LOOKUP_PARENT, &oldnd)) +@@ -1871,7 +1982,7 @@ + + double_lock(new_dir, old_dir); + +- old_dentry = lookup_hash(&oldnd.last, old_dir); ++ old_dentry = lookup_hash_it(&oldnd.last, old_dir, &it); + error = PTR_ERR(old_dentry); + if (IS_ERR(old_dentry)) + goto exit3; +@@ -1887,18 +1998,21 @@ + if (newnd.last.name[newnd.last.len]) + goto exit4; + } +- new_dentry = lookup_hash(&newnd.last, new_dir); ++ it.it_op = IT_RENAME2; ++ new_dentry = lookup_hash_it(&newnd.last, new_dir, &it); + error = PTR_ERR(new_dentry); + if (IS_ERR(new_dentry)) + goto exit4; + + lock_kernel(); + error = vfs_rename(old_dir->d_inode, old_dentry, +- new_dir->d_inode, new_dentry); ++ new_dir->d_inode, new_dentry, &it); + unlock_kernel(); + ++ intent_release(new_dentry, NULL); + dput(new_dentry); + exit4: ++ intent_release(old_dentry, &it); + dput(old_dentry); + exit3: + double_up(&new_dir->d_inode->i_sem, &old_dir->d_inode->i_sem); +@@ -1947,7 +2061,8 @@ + } + + static inline int +-__vfs_follow_link(struct nameidata *nd, const char *link) ++__vfs_follow_link(struct nameidata *nd, const char *link, ++ struct lookup_intent *it) + { + int res = 0; + char *name; +@@ -1960,7 +2075,7 @@ + /* weird __emul_prefix() stuff did it */ + goto out; + } +- res = link_path_walk(link, nd); ++ res = link_path_walk_it(link, nd, it); + out: + if (current->link_count || res || nd->last_type!=LAST_NORM) + return res; +@@ -1982,7 +2097,13 @@ + + int vfs_follow_link(struct nameidata *nd, const char *link) + { +- return __vfs_follow_link(nd, link); ++ return __vfs_follow_link(nd, link, NULL); ++} ++ ++int vfs_follow_link_it(struct nameidata *nd, const char *link, ++ struct lookup_intent *it) ++{ ++ return __vfs_follow_link(nd, link, it); + } + + /* get the link contents into pagecache */ +@@ -2024,7 +2145,7 @@ + { + struct page *page = NULL; + char *s = page_getlink(dentry, &page); +- int res = __vfs_follow_link(nd, s); ++ int res = __vfs_follow_link(nd, s, NULL); + if (page) { + kunmap(page); + page_cache_release(page); +--- linux-pristine/./fs/open.c Thu Dec 5 10:49:20 2002 ++++ linux/./fs/open.c Fri Nov 29 18:06:21 2002 +@@ -19,6 +19,9 @@ + #include + + #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m)) ++extern int path_walk_it(const char *name, struct nameidata *nd, ++ struct lookup_intent *it); ++extern void intent_release(struct dentry *de, struct lookup_intent *it); + + int vfs_statfs(struct super_block *sb, struct statfs *buf) + { +@@ -94,12 +97,13 @@ + struct nameidata nd; + struct inode * inode; + int error; ++ struct lookup_intent it = { .it_op = IT_SETATTR }; + + error = -EINVAL; + if (length < 0) /* sorry, but loff_t says... */ + goto out; + +- error = user_path_walk(path, &nd); ++ error = user_path_walk_it(path, &nd, &it); + if (error) + goto out; + inode = nd.dentry->d_inode; +@@ -144,6 +148,7 @@ + put_write_access(inode); + + dput_and_out: ++ intent_release(nd.dentry, &it); + path_release(&nd); + out: + return error; +@@ -235,8 +240,9 @@ + struct nameidata nd; + struct inode * inode; + struct iattr newattrs; ++ struct lookup_intent it = { .it_op = IT_SETATTR }; + +- error = user_path_walk(filename, &nd); ++ error = user_path_walk_it(filename, &nd, &it); + if (error) + goto out; + inode = nd.dentry->d_inode; +@@ -262,6 +268,7 @@ + } + error = notify_change(nd.dentry, &newattrs); + dput_and_out: ++ intent_release(nd.dentry, &it); + path_release(&nd); + out: + return error; +@@ -279,8 +286,9 @@ + struct nameidata nd; + struct inode * inode; + struct iattr newattrs; ++ struct lookup_intent it = { .it_op = IT_SETATTR }; + +- error = user_path_walk(filename, &nd); ++ error = user_path_walk_it(filename, &nd, &it); + + if (error) + goto out; +@@ -307,6 +315,7 @@ + } + error = notify_change(nd.dentry, &newattrs); + dput_and_out: ++ intent_release(nd.dentry, &it); + path_release(&nd); + out: + return error; +@@ -323,6 +332,7 @@ + int old_fsuid, old_fsgid; + kernel_cap_t old_cap; + int res; ++ struct lookup_intent it = { .it_op = IT_GETATTR }; + + if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */ + return -EINVAL; +@@ -340,13 +350,14 @@ + else + current->cap_effective = current->cap_permitted; + +- res = user_path_walk(filename, &nd); ++ res = user_path_walk_it(filename, &nd, &it); + if (!res) { + res = permission(nd.dentry->d_inode, mode); + /* SuS v2 requires we report a read only fs too */ + if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode) + && !special_file(nd.dentry->d_inode->i_mode)) + res = -EROFS; ++ intent_release(nd.dentry, &it); + path_release(&nd); + } + +@@ -362,6 +373,7 @@ + int error; + struct nameidata nd; + char *name; ++ struct lookup_intent it = { .it_op = IT_GETATTR }; + + name = getname(filename); + error = PTR_ERR(name); +@@ -370,7 +382,7 @@ + + error = 0; + if (path_init(name,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd)) +- error = path_walk(name, &nd); ++ error = path_walk_it(name, &nd, &it); + putname(name); + if (error) + goto out; +@@ -382,6 +394,7 @@ + set_fs_pwd(current->fs, nd.mnt, nd.dentry); + + dput_and_out: ++ intent_release(nd.dentry, &it); + path_release(&nd); + out: + return error; +@@ -422,6 +435,7 @@ + int error; + struct nameidata nd; + char *name; ++ struct lookup_intent it = { .it_op = IT_GETATTR }; + + name = getname(filename); + error = PTR_ERR(name); +@@ -430,7 +444,7 @@ + + path_init(name, LOOKUP_POSITIVE | LOOKUP_FOLLOW | + LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd); +- error = path_walk(name, &nd); ++ error = path_walk_it(name, &nd, &it); + putname(name); + if (error) + goto out; +@@ -447,6 +461,7 @@ + set_fs_altroot(); + error = 0; + dput_and_out: ++ intent_release(nd.dentry, &it); + path_release(&nd); + out: + return error; +@@ -491,8 +506,9 @@ + struct inode * inode; + int error; + struct iattr newattrs; ++ struct lookup_intent it = { .it_op = IT_SETATTR }; + +- error = user_path_walk(filename, &nd); ++ error = user_path_walk_it(filename, &nd, &it); + if (error) + goto out; + inode = nd.dentry->d_inode; +@@ -512,6 +528,7 @@ + error = notify_change(nd.dentry, &newattrs); + + dput_and_out: ++ intent_release(nd.dentry, &it); + path_release(&nd); + out: + return error; +@@ -581,10 +598,12 @@ + { + struct nameidata nd; + int error; ++ struct lookup_intent it = { .it_op = IT_SETATTR }; + +- error = user_path_walk(filename, &nd); ++ error = user_path_walk_it(filename, &nd, &it); + if (!error) { + error = chown_common(nd.dentry, user, group); ++ intent_release(nd.dentry, &it); + path_release(&nd); + } + return error; +@@ -594,10 +613,12 @@ + { + struct nameidata nd; + int error; ++ struct lookup_intent it = { .it_op = IT_SETATTR }; + +- error = user_path_walk_link(filename, &nd); ++ error = user_path_walk_link_it(filename, &nd, &it); + if (!error) { + error = chown_common(nd.dentry, user, group); ++ intent_release(nd.dentry, &it); + path_release(&nd); + } + return error; +@@ -631,10 +652,16 @@ + * for the internal routines (ie open_namei()/follow_link() etc). 00 is + * used by symlinks. + */ ++extern int open_namei_it(const char *filename, int namei_flags, int mode, ++ struct nameidata *nd, struct lookup_intent *it); ++struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt, ++ int flags, struct lookup_intent *it); ++ + struct file *filp_open(const char * filename, int flags, int mode) + { + int namei_flags, error; + struct nameidata nd; ++ struct lookup_intent it = { .it_op = IT_OPEN }; + + namei_flags = flags; + if ((namei_flags+1) & O_ACCMODE) +@@ -642,14 +669,15 @@ + if (namei_flags & O_TRUNC) + namei_flags |= 2; + +- error = open_namei(filename, namei_flags, mode, &nd); +- if (!error) +- return dentry_open(nd.dentry, nd.mnt, flags); ++ error = open_namei_it(filename, namei_flags, mode, &nd, &it); ++ if (error) ++ return ERR_PTR(error); + +- return ERR_PTR(error); ++ return dentry_open_it(nd.dentry, nd.mnt, flags, &it); + } + +-struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags) ++struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt, ++ int flags, struct lookup_intent *it) + { + struct file * f; + struct inode *inode; +@@ -692,6 +720,7 @@ + } + f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); + ++ intent_release(dentry, it); + return f; + + cleanup_all: +@@ -706,11 +735,17 @@ + cleanup_file: + put_filp(f); + cleanup_dentry: ++ intent_release(dentry, it); + dput(dentry); + mntput(mnt); + return ERR_PTR(error); + } + ++struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags) ++{ ++ return dentry_open_it(dentry, mnt, flags, NULL); ++} ++ + /* + * Find an empty file descriptor entry, and mark it busy. + */ +--- linux-pristine/./fs/stat.c Thu Dec 5 10:49:22 2002 ++++ linux/./fs/stat.c Fri Nov 29 18:06:21 2002 +@@ -13,6 +13,7 @@ + + #include + ++extern void intent_release(struct dentry *de, struct lookup_intent *it); + /* + * Revalidate the inode. This is required for proper NFS attribute caching. + */ +@@ -135,13 +136,15 @@ + asmlinkage long sys_stat(char * filename, struct __old_kernel_stat * statbuf) + { + struct nameidata nd; ++ struct lookup_intent it = { .it_op = IT_GETATTR }; + int error; + +- error = user_path_walk(filename, &nd); ++ error = user_path_walk_it(filename, &nd, &it); + if (!error) { + error = do_revalidate(nd.dentry); + if (!error) + error = cp_old_stat(nd.dentry->d_inode, statbuf); ++ intent_release(nd.dentry, &it); + path_release(&nd); + } + return error; +@@ -151,13 +154,15 @@ + asmlinkage long sys_newstat(char * filename, struct stat * statbuf) + { + struct nameidata nd; ++ struct lookup_intent it = { .it_op = IT_GETATTR }; + int error; + +- error = user_path_walk(filename, &nd); ++ error = user_path_walk_it(filename, &nd, &it); + if (!error) { + error = do_revalidate(nd.dentry); + if (!error) + error = cp_new_stat(nd.dentry->d_inode, statbuf); ++ intent_release(nd.dentry, &it); + path_release(&nd); + } + return error; +@@ -172,13 +177,15 @@ + asmlinkage long sys_lstat(char * filename, struct __old_kernel_stat * statbuf) + { + struct nameidata nd; ++ struct lookup_intent it = { .it_op = IT_GETATTR }; + int error; + +- error = user_path_walk_link(filename, &nd); ++ error = user_path_walk_link_it(filename, &nd, &it); + if (!error) { + error = do_revalidate(nd.dentry); + if (!error) + error = cp_old_stat(nd.dentry->d_inode, statbuf); ++ intent_release(nd.dentry, &it); + path_release(&nd); + } + return error; +@@ -189,13 +196,15 @@ + asmlinkage long sys_newlstat(char * filename, struct stat * statbuf) + { + struct nameidata nd; ++ struct lookup_intent it = { .it_op = IT_GETATTR }; + int error; + +- error = user_path_walk_link(filename, &nd); ++ error = user_path_walk_link_it(filename, &nd, &it); + if (!error) { + error = do_revalidate(nd.dentry); + if (!error) + error = cp_new_stat(nd.dentry->d_inode, statbuf); ++ intent_release(nd.dentry, &it); + path_release(&nd); + } + return error; +@@ -247,20 +256,21 @@ + { + struct nameidata nd; + int error; ++ struct lookup_intent it = { .it_op = IT_READLINK }; + + if (bufsiz <= 0) + return -EINVAL; + +- error = user_path_walk_link(path, &nd); ++ error = user_path_walk_link_it(path, &nd, &it); + if (!error) { + struct inode * inode = nd.dentry->d_inode; +- + error = -EINVAL; + if (inode->i_op && inode->i_op->readlink && + !(error = do_revalidate(nd.dentry))) { + UPDATE_ATIME(inode); + error = inode->i_op->readlink(nd.dentry, buf, bufsiz); + } ++ intent_release(nd.dentry, &it); + path_release(&nd); + } + return error; +@@ -333,12 +343,14 @@ + { + struct nameidata nd; + int error; ++ struct lookup_intent it = { .it_op = IT_GETATTR }; + +- error = user_path_walk(filename, &nd); ++ error = user_path_walk_it(filename, &nd, &it); + if (!error) { + error = do_revalidate(nd.dentry); + if (!error) + error = cp_new_stat64(nd.dentry->d_inode, statbuf); ++ intent_release(nd.dentry, &it); + path_release(&nd); + } + return error; +@@ -348,12 +360,14 @@ + { + struct nameidata nd; + int error; ++ struct lookup_intent it = { .it_op = IT_GETATTR }; + +- error = user_path_walk_link(filename, &nd); ++ error = user_path_walk_link_it(filename, &nd, &it); + if (!error) { + error = do_revalidate(nd.dentry); + if (!error) + error = cp_new_stat64(nd.dentry->d_inode, statbuf); ++ intent_release(nd.dentry, &it); + path_release(&nd); + } + return error; +--- linux-pristine/./mm/slab.c Thu Dec 5 10:50:02 2002 ++++ linux/./mm/slab.c Fri Nov 29 18:06:21 2002 +@@ -1187,6 +1187,59 @@ + * Called with the cache-lock held. + */ + ++extern struct page *check_get_page(unsigned long kaddr); ++struct page *page_mem_map(struct page *page); ++static int kmem_check_cache_obj (kmem_cache_t * cachep, ++ slab_t *slabp, void * objp) ++{ ++ int i; ++ unsigned int objnr; ++ ++#if DEBUG ++ if (cachep->flags & SLAB_RED_ZONE) { ++ objp -= BYTES_PER_WORD; ++ if ( *(unsigned long *)objp != RED_MAGIC2) ++ /* Either write before start, or a double free. */ ++ return 0; ++ if (*(unsigned long *)(objp+cachep->objsize - ++ BYTES_PER_WORD) != RED_MAGIC2) ++ /* Either write past end, or a double free. */ ++ return 0; ++ } ++#endif ++ ++ objnr = (objp-slabp->s_mem)/cachep->objsize; ++ if (objnr >= cachep->num) ++ return 0; ++ if (objp != slabp->s_mem + objnr*cachep->objsize) ++ return 0; ++ ++ /* Check slab's freelist to see if this obj is there. */ ++ for (i = slabp->free; i != BUFCTL_END; i = slab_bufctl(slabp)[i]) { ++ if (i == objnr) ++ return 0; ++ } ++ return 1; ++} ++ ++ ++int kmem_cache_validate(kmem_cache_t *cachep, void *objp) ++{ ++ struct page *page = check_get_page((unsigned long)objp); ++ ++ if (!VALID_PAGE(page)) ++ return 0; ++ ++ if (!PageSlab(page)) ++ return 0; ++ ++ /* XXX check for freed slab objects ? */ ++ if (!kmem_check_cache_obj(cachep, GET_PAGE_SLAB(page), objp)) ++ return 0; ++ ++ return (cachep == GET_PAGE_CACHE(page)); ++} ++ + #if DEBUG + static int kmem_extra_free_checks (kmem_cache_t * cachep, + slab_t *slabp, void * objp) diff --git a/lustre/patches/patch-2.4.18-um b/lustre/patches/patch-2.4.18-um index 6e1e345..80c19a1 100644 --- a/lustre/patches/patch-2.4.18-um +++ b/lustre/patches/patch-2.4.18-um @@ -47,3 +47,14 @@ return(0); } +--- /usr/src/lum/include/asm/pgtable.h.orig 2002-12-04 01:58:36.000000000 -0700 ++++ /usr/src/lum/include/asm/pgtable.h 2002-12-04 01:58:54.000000000 -0700 +@@ -200,7 +200,7 @@ static inline void pgd_clear(pgd_t * pgd + * called on a highmem page. + */ + +-#define page_address(page) ({ if (!(page)->virtual) BUG(); (page)->virtual; }) ++//#define page_address(page) ({ if (!(page)->virtual) BUG(); (page)->virtual; }) + #define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT)) + + extern struct page *pte_mem_map(pte_t pte); diff --git a/lustre/ptlrpc/client.c b/lustre/ptlrpc/client.c index 4ab7903..af371d8 100644 --- a/lustre/ptlrpc/client.c +++ b/lustre/ptlrpc/client.c @@ -349,13 +349,14 @@ static int __ptlrpc_req_finished(struct ptlrpc_request *request, int locked) if (request == NULL) RETURN(1); + DEBUG_REQ(D_INFO, request, "refcount now %u", + atomic_read(&request->rq_refcount) - 1); + if (atomic_dec_and_test(&request->rq_refcount)) { __ptlrpc_free_req(request, locked); RETURN(1); } - DEBUG_REQ(D_INFO, request, "refcount now %u", - atomic_read(&request->rq_refcount)); RETURN(0); } @@ -444,7 +445,7 @@ void ptlrpc_free_committed(struct obd_import *imp) struct ptlrpc_request *req; ENTRY; -#ifndef __arch_um__ +#ifdef CONFIG_SMP LASSERT(spin_is_locked(&imp->imp_lock)); #endif diff --git a/lustre/ptlrpc/service.c b/lustre/ptlrpc/service.c index 1688ff9..d497668 100644 --- a/lustre/ptlrpc/service.c +++ b/lustre/ptlrpc/service.c @@ -242,6 +242,7 @@ static void ptlrpc_daemonize(void) current->tty = NULL; exit_files(current); + reparent_to_init(); } static int ptlrpc_main(void *arg) diff --git a/lustre/tests/Makefile.am b/lustre/tests/Makefile.am index f09b85c..77c3039 100644 --- a/lustre/tests/Makefile.am +++ b/lustre/tests/Makefile.am @@ -24,7 +24,7 @@ noinst_SCRIPTS += fs.sh intent-test.sh intent-test2.sh leak_finder.pl \ runtests runvmstat snaprun.sh tbox.sh common.sh noinst_PROGRAMS = openunlink testreq truncate directio openme writeme mcreate noinst_PROGRAMS += munlink tchmod toexcl fsx test_brw openclose createdestroy -noinst_PROGRAMS += lovstripe stat createmany mkdirmany setuid # ldaptest +noinst_PROGRAMS += lovstripe stat createmany mkdirmany multifstat # ldaptest # ldaptest_SOURCES = ldaptest.c tchmod_SOURCES = tchmod.c @@ -45,6 +45,6 @@ lovstripe_SOURCES = lovstripe.c stat_SOURCES = stat.c createmany_SOURCES = createmany.c mkdirmany_SOURCES = mkdirmany.c -setuid_SOURCES = setuid.c +multifstat_SOURCES = multifstat.c include $(top_srcdir)/Rules diff --git a/lustre/tests/fsx.c b/lustre/tests/fsx.c index 717b8d4..aba33d5 100644 --- a/lustre/tests/fsx.c +++ b/lustre/tests/fsx.c @@ -213,14 +213,14 @@ logdump(void) opnum = i+1 + (logcount/LOGSIZE)*LOGSIZE; lp = &oplog[i]; - prt("%d(%d mod 256): %lu.%lu ", opnum, opnum%256, + prt("%d(%d mod 256): %lu.%06lu ", opnum, opnum%256, lp->tv.tv_sec, lp->tv.tv_usec); if ((closeopen = lp->operation < 0)) lp->operation = ~ lp->operation; switch (lp->operation) { case OP_MAPREAD: - prt("MAPREAD\t0x%x thru 0x%x\t(0x%x bytes)", + prt("MAPREAD\t0x%x thru 0x%x (0x%x bytes)", lp->args[0], lp->args[0] + lp->args[1] - 1, lp->args[1]); if (badoff >= lp->args[0] && badoff < @@ -228,7 +228,7 @@ logdump(void) prt("\t***RRRR***"); break; case OP_MAPWRITE: - prt("MAPWRITE 0x%x thru 0x%x\t(0x%x bytes)", + prt("MAPWRITE 0x%x thru 0x%x (0x%x bytes)", lp->args[0], lp->args[0] + lp->args[1] - 1, lp->args[1]); if (badoff >= lp->args[0] && badoff < @@ -236,7 +236,7 @@ logdump(void) prt("\t******WWWW"); break; case OP_READ: - prt("READ\t0x%x thru 0x%x\t(0x%x bytes)", + prt("READ\t0x%x thru 0x%x (0x%x bytes)", lp->args[0], lp->args[0] + lp->args[1] - 1, lp->args[1]); if (badoff >= lp->args[0] && @@ -244,7 +244,7 @@ logdump(void) prt("\t***RRRR***"); break; case OP_WRITE: - prt("WRITE\t0x%x thru 0x%x\t(0x%x bytes)", + prt("WRITE\t0x%x thru 0x%x (0x%x bytes)", lp->args[0], lp->args[0] + lp->args[1] - 1, lp->args[1]); if (lp->args[0] > lp->args[2]) @@ -458,7 +458,7 @@ doread(unsigned offset, unsigned size) (monitorstart == -1 || (offset + size > monitorstart && (monitorend == -1 || offset <= monitorend)))))) - prt("%lu %lu.%lu read\t0x%x thru\t0x%x\t(0x%x bytes)\n", + prt("%06lu %lu.%06lu read %#08x thru %#08x\t(0x%x bytes)\n", testcalls, t.tv_sec, t.tv_usec, offset, offset + size - 1, size); ret = lseek(fd, (off_t)offset, SEEK_SET); @@ -467,6 +467,13 @@ doread(unsigned offset, unsigned size) report_failure(140); } iret = read(fd, temp_buf, size); + if (!quiet && (debug > 1 && + (monitorstart == -1 || + (offset + size > monitorstart && + (monitorend == -1 || offset <= monitorend))))) { + gettimeofday(&t, NULL); + prt(" %lu.%06lu read done\n", t.tv_sec, t.tv_usec); + } if (iret != size) { if (iret == -1) prterr("doread: read"); @@ -513,7 +520,7 @@ domapread(unsigned offset, unsigned size) (monitorstart == -1 || (offset + size > monitorstart && (monitorend == -1 || offset <= monitorend)))))) - prt("%lu %lu.%lu mapread\t0x%x thru\t0x%x\t(0x%x bytes)\n", + prt("%06lu %lu.%06lu mapread %#08x thru %#08x\t(0x%x bytes)\n", testcalls, t.tv_sec, t.tv_usec, offset, offset + size - 1, size); @@ -526,10 +533,24 @@ domapread(unsigned offset, unsigned size) report_failure(190); } memcpy(temp_buf, p + pg_offset, size); + if (!quiet && (debug > 1 && + (monitorstart == -1 || + (offset + size > monitorstart && + (monitorend == -1 || offset <= monitorend))))) { + gettimeofday(&t, NULL); + prt(" %lu.%06lu memcpy done\n", t.tv_sec, t.tv_usec); + } if (munmap(p, map_size) != 0) { prterr("domapread: munmap"); report_failure(191); } + if (!quiet && (debug > 1 && + (monitorstart == -1 || + (offset + size > monitorstart && + (monitorend == -1 || offset <= monitorend))))) { + gettimeofday(&t, NULL); + prt(" %lu.%06lu munmap done\n", t.tv_sec, t.tv_usec); + } check_buffers(offset, size); } @@ -585,7 +606,7 @@ dowrite(unsigned offset, unsigned size) (monitorstart == -1 || (offset + size > monitorstart && (monitorend == -1 || offset <= monitorend)))))) - prt("%lu %lu.%lu write\t0x%x thru\t0x%x\t(0x%x bytes)\n", + prt("%06lu %lu.%06lu write %#08x thru %#08x\t(0x%x bytes)\n", testcalls, t.tv_sec, t.tv_usec, offset, offset + size - 1, size); ret = lseek(fd, (off_t)offset, SEEK_SET); @@ -594,6 +615,13 @@ dowrite(unsigned offset, unsigned size) report_failure(150); } iret = write(fd, good_buf + offset, size); + if (!quiet && (debug > 1 && + (monitorstart == -1 || + (offset + size > monitorstart && + (monitorend == -1 || offset <= monitorend))))) { + gettimeofday(&t, NULL); + prt(" %lu.%06lu write done\n", t.tv_sec, t.tv_usec); + } if (iret != size) { if (iret == -1) prterr("dowrite: write"); @@ -646,7 +674,7 @@ domapwrite(unsigned offset, unsigned size) (monitorstart == -1 || (offset + size > monitorstart && (monitorend == -1 || offset <= monitorend)))))) - prt("%lu %lu.%lu mapwrite\t0x%x thru\t0x%x\t(0x%x bytes)\n", + prt("%06lu %lu.%06lu mapwrite %#08x thru %#08x\t(0x%x bytes)\n", testcalls, t.tv_sec, t.tv_usec, offset, offset + size - 1, size); @@ -666,14 +694,35 @@ domapwrite(unsigned offset, unsigned size) report_failure(202); } memcpy(p + pg_offset, good_buf + offset, size); + if (!quiet && (debug > 1 && + (monitorstart == -1 || + (offset + size > monitorstart && + (monitorend == -1 || offset <= monitorend))))) { + gettimeofday(&t, NULL); + prt(" %lu.%06lu memcpy done\n", t.tv_sec, t.tv_usec); + } if (msync(p, map_size, 0) != 0) { prterr("domapwrite: msync"); report_failure(203); } + if (!quiet && (debug > 1 && + (monitorstart == -1 || + (offset + size > monitorstart && + (monitorend == -1 || offset <= monitorend))))) { + gettimeofday(&t, NULL); + prt(" %lu.%06lu msync done\n", t.tv_sec, t.tv_usec); + } if (munmap(p, map_size) != 0) { prterr("domapwrite: munmap"); report_failure(204); } + if (!quiet && (debug > 1 && + (monitorstart == -1 || + (offset + size > monitorstart && + (monitorend == -1 || offset <= monitorend))))) { + gettimeofday(&t, NULL); + prt(" %lu.%06lu munmap done\n", t.tv_sec, t.tv_usec); + } } @@ -703,13 +752,17 @@ dotruncate(unsigned size) if ((progressinterval && testcalls % progressinterval == 0) || (debug && (monitorstart == -1 || monitorend == -1 || size <= monitorend))) - prt("%lu %lu.%lu trunc\tfrom 0x%x to 0x%x\n", + prt("%06lu %lu.%06lu trunc from %#08x to %#08x\n", testcalls, t.tv_sec, t.tv_usec, oldsize, size); if (ftruncate(fd, (off_t)size) == -1) { prt("ftruncate1: %x\n", size); prterr("dotruncate: ftruncate"); report_failure(160); } + if (!quiet && debug > 1) { + gettimeofday(&t, NULL); + prt(" %lu.%06lu trunc done\n", t.tv_sec, t.tv_usec); + } } @@ -751,16 +804,25 @@ docloseopen(void) gettimeofday(&t, NULL); if (debug) - prt("%lu %lu.%lu close/open\n", testcalls, t.tv_sec, t.tv_usec); + prt("%06lu %lu.%06lu close/open\n", testcalls, t.tv_sec, + t.tv_usec); if (close(fd)) { prterr("docloseopen: close"); report_failure(180); } + if (!quiet && debug > 1) { + gettimeofday(&t, NULL); + prt(" %lu.%06lu close done\n", t.tv_sec, t.tv_usec); + } fd = open(fname, O_RDWR, 0); if (fd < 0) { prterr("docloseopen: open"); report_failure(181); } + if (!quiet && debug > 1) { + gettimeofday(&t, NULL); + prt(" %lu.%06lu opendone\n", t.tv_sec, t.tv_usec); + } } @@ -857,7 +919,7 @@ truncbdy] [-w writebdy] [-D startingop] [-N numops] [-P dirpath] [-S seed] fname\n\ -b opnum: beginning operation number (default 1)\n\ -c P: 1 in P chance of file close+open at each op (default infinity)\n\ - -d: debug output for all operations\n\ + -d: debug output for all operations [-d -d = more debugging]\n\ -l flen: the upper bound on file size (default 262144)\n\ -m startop:endop: monitor (print debug output) specified byte range (default 0:infinity)\n\ @@ -961,7 +1023,7 @@ main(int argc, char **argv) usage(); break; case 'd': - debug = 1; + debug++; break; case 'l': maxfilelen = getnum(optarg, &endp); diff --git a/lustre/tests/llmount2-hackcleanup.sh b/lustre/tests/llmount2-hackcleanup.sh new file mode 100644 index 0000000..21c915d --- /dev/null +++ b/lustre/tests/llmount2-hackcleanup.sh @@ -0,0 +1,21 @@ +#!/bin/sh +# suggested boilerplate for test script + +LCONF=${LCONF:-../utils/lconf} +NAME=${NAME:-local2-hack} + +config=$NAME.xml + +umount /mnt/lustre1 +umount /mnt/lustre2 +../utils/lctl < + + + + + + + + + + + + + localhost + 988 + + + + extN + /tmp/mds1 + yes + + + + + extN + /tmp/ost1 + yes + + + + + + + + + + + + + /mnt/lustre1 + + diff --git a/lustre/tests/multifstat.c b/lustre/tests/multifstat.c new file mode 100644 index 0000000..56948d9 --- /dev/null +++ b/lustre/tests/multifstat.c @@ -0,0 +1,62 @@ +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + int fd1, fd2; + struct stat st1, st2; + + if (argc != 3) { + printf("Usage %s file1 file2\n", argv[0]); + return 1; + } + + + fd1 = open(argv[1], O_CREAT| O_RDWR, 0666); + if (fd1 == -1) { + printf("Error opening %s: %s\n", argv[1], strerror(errno)); + return errno; + } + + fd2 = open(argv[2], O_RDONLY); + if (fd2 == -1) { + printf("Error opening %s: %s\n", argv[2], strerror(errno)); + return errno; + } + + sleep(1); + + if ( write(fd1, "hello", strlen("hello")) != strlen("hello")) { + printf("Error writing: %s\n", strerror(errno)); + return errno; + } + + if ( fstat(fd1, &st1) ) { + printf("Error statting %s: %s\n", argv[1], strerror(errno)); + return errno; + } + + if ( fstat(fd2, &st2) ) { + printf("Error statting %s: %s\n", argv[2], strerror(errno)); + return errno; + } + + if ( st1.st_size != st2.st_size ) { + printf("Sizes don't match %ld, %ld\n", + st1.st_size, st2.st_size); + return 1; + } + + if ( st1.st_mtime != st2.st_mtime ) { + printf("Mtimes don't match %ld, %ld\n", + st1.st_mtime, st2.st_mtime); + return 1; + } + + return 0; +} diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index da72bda..cf305a4 100644 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -13,21 +13,37 @@ start() { } START=start +error () { + echo FAIL + exit 1 +} + +pass() { + echo PASS +} + echo '== touch .../f ; rm .../f ======================== test 0' touch /mnt/lustre/f +[ -f /mnt/lustre/f ] || error rm /mnt/lustre/f +[ ! -f /mnt/lustre/f ] || error +pass $CLEAN $START echo '== mkdir .../d1; mkdir .../d1/d2 ================= test 1' mkdir /mnt/lustre/d1 mkdir /mnt/lustre/d1/d2 +[ -d /mnt/lustre/d1/d2 ] || error +pass $CLEAN $START echo '== rmdir .../d1/d2; rmdir .../d1 ================= test 1b' rmdir /mnt/lustre/d1/d2 rmdir /mnt/lustre/d1 +[ ! -d /mnt/lustre/d1 ] || error +pass $CLEAN $START @@ -198,14 +214,13 @@ cat /mnt/lustre/d21/dangle $CLEAN $START -# echo '== unpack tar archive as nonroot user =========== test 22' -echo '== please fix test 22' -# mkdir /mnt/lustre/d22 -# chown 4711 /mnt/lustre/d22 -# (./setuid 4711 ; tar cf - /etc/hosts /etc/sysconfig/network | tar xfC - /mnt/lustre/d22 ; ./setuid 0) -# ls -lR /mnt/lustre/d22/etc -# $CLEAN -# $START +echo '== unpack tar archive as nonroot user =========== test 22' +mkdir /mnt/lustre/d22 +chown 4711 /mnt/lustre/d22 +sudo -u \#4711 tar cf - /etc/hosts /etc/sysconfig/network | sudo -u \#4711 tar xfC - /mnt/lustre/d22 +ls -lR /mnt/lustre/d22/etc +$CLEAN +$START echo '== O_CREAT|O_EXCL in subdir ===================== test 23' mkdir /mnt/lustre/d23 @@ -214,5 +229,79 @@ mkdir /mnt/lustre/d23 $CLEAN $START +echo '== rename sanity ============================= test24' +echo '-- same directory rename' +echo '-- test 24-R1: touch a ; rename a b' +mkdir /mnt/lustre/R1 +touch /mnt/lustre/R1/f +mv /mnt/lustre/R1/f /mnt/lustre/R1/g +$CLEAN +$START + +echo '-- test 24-R2: touch a b ; rename a b;' +mkdir /mnt/lustre/R2 +touch /mnt/lustre/R2/{f,g} +mv /mnt/lustre/R2/f /mnt/lustre/R2/g +$CLEAN +$START + +echo '-- test 24-R3: mkdir a ; rename a b;' +mkdir /mnt/lustre/R3 +mkdir /mnt/lustre/R3/f +mv /mnt/lustre/R3/f /mnt/lustre/R3/g +$CLEAN +$START + +echo '-- test 24-R4: mkdir a b ; rename a b;' +mkdir /mnt/lustre/R4 +mkdir /mnt/lustre/R4/{f,g} +perl -e 'rename "/mnt/lustre/R3/f", "/mnt/lustre/R3/g";' +$CLEAN +$START + +echo '-- cross directory renames --' +echo '-- test 24-R5: touch a ; rename a b' +mkdir /mnt/lustre/R5{a,b} +touch /mnt/lustre/R5a/f +mv /mnt/lustre/R5a/f /mnt/lustre/R5b/g +$CLEAN +$START + +echo '-- test 24-R6: touch a ; rename a b' +mkdir /mnt/lustre/R6{a,b} +touch /mnt/lustre/R6a/f /mnt/lustre/R6b/g +mv /mnt/lustre/R6a/f /mnt/lustre/R6b/g +$CLEAN +$START + +echo '-- test 24-R7: touch a ; rename a b' +mkdir /mnt/lustre/R7{a,b} +mkdir /mnt/lustre/R7a/f +mv /mnt/lustre/R7a/f /mnt/lustre/R7b/g +$CLEAN +$START + +echo '-- test 24-R8: touch a ; rename a b' +mkdir /mnt/lustre/R8{a,b} +mkdir /mnt/lustre/R8a/f /mnt/lustre/R8b/g +perl -e 'rename "/mnt/lustre/R8a/f", "/mnt/lustre/R8b/g";' +$CLEAN +$START + +echo "-- rename error cases" +echo "-- test 24-R9 target error: touch f ; mkdir a ; rename f a" +mkdir /mnt/lustre/R9 +mkdir /mnt/lustre/R9/a +touch /mnt/lustre/R9/f +perl -e 'rename "/mnt/lustre/R9/f", "/mnt/lustre/R9/a";' +$CLEAN +$START + +echo "--test 24-R10 source does not exist" +mkdir /mnt/lustre/R10 +mv /mnt/lustre/R10/f /mnt/lustre/R10/g +$CLEAN +$START + echo '======================= finished =======================' exit diff --git a/lustre/tests/sanityN.sh b/lustre/tests/sanityN.sh new file mode 100644 index 0000000..b1536cc --- /dev/null +++ b/lustre/tests/sanityN.sh @@ -0,0 +1,63 @@ +#!/bin/bash + +export NAME=$NAME +clean() { + echo -n "cleanup..." + sh llmount2-hackcleanup.sh > /dev/null +} + +CLEAN=clean +start() { + echo -n "mounting..." + sh llmount2-hack.sh > /dev/null + echo -n "mounted" +} +START=start + +error () { + echo $1 + exit 1 +} + +echo -n "test 1: check create on 2 mtpt's..." +touch /mnt/lustre1/f1 +[ -f /mnt/lustre2/f1 ] || error "test 1 failure" +echo "pass" + +echo -n "test 2: check attribute updates on 2 mtpt's..." +chmod a+x /mnt/lustre2/f1 +[ -x /mnt/lustre1/f1 ] || error "test 2 failure" +echo "pass" + +echo -n "test 3: check after remount attribute updates on 2 mtpt's..." +chmod a-x /mnt/lustre2/f1 +$CLEAN +$START + +[ ! -x /mnt/lustre1/f1 ] || error "test 3 failure" +echo "pass" + +echo -n "test 4: symlink on one mtpt, readlink on another..." +( cd /mnt/lustre1 ; ln -s this/is/good lnk ) + +[ "Xthis/is/good" = X`perl -e 'print readlink("/mnt/lustre2/lnk");'` ] || error "test 4 fails" +echo "pass" + +echo -n "test 5: fstat validation on multiple mount points..." +./multifstat /mnt/lustre1/fstatfile /mnt/lustre2/fstatfile || error "test 5 fails" +echo "pass" + +echo -n "test 9: remove of open file on other node..." +touch /mnt/lustre1/f9 +tail -f /mnt/lustre/f9 & +rm /mnt/lustre2/f9 +kill %1 +cat /mnt/lustre1/f9 && error "test 9 fails" +echo "pass" + +$CLEAN +$START + + + +exit diff --git a/lustre/tests/setuid.c b/lustre/tests/setuid.c deleted file mode 100644 index 04dba5e..0000000 --- a/lustre/tests/setuid.c +++ /dev/null @@ -1,27 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -int main(int argc, char ** argv) -{ - int rc, fsuid; - - if (argc < 2) { - printf("Usage %s fsuid\n", argv[0]); - return 1; - } - - fsuid = strtoul(argv[2], NULL, 0); - rc = setfsuid(fsuid); - if (rc) { - printf("mknod(%s) error: %s\n", argv[1], strerror(errno)); - } - return rc; -} diff --git a/lustre/utils/lconf b/lustre/utils/lconf index 08ba66e..d460503 100755 --- a/lustre/utils/lconf +++ b/lustre/utils/lconf @@ -513,10 +513,17 @@ def is_block(path): def mkfs(fstype, dev): if(fstype in ('ext3', 'extN')): mkfs = 'mkfs.ext2 -j -b 4096' + elif (fstype == 'reiserfs'): + mkfs = 'mkfs.reiserfs -f' else: print 'unsupported fs type: ', fstype if not is_block(dev): - force = '-F' + if(fstype in ('ext3', 'extN')): + force = '-F' + elif (fstype == 'reiserfs'): + force = '' + else: + print 'unsupported fs type: ', fstype else: force = '' (ret, out) = run (mkfs, force, dev) diff --git a/lustre/utils/lfind.c b/lustre/utils/lfind.c index d0b4c49..26f6a3f 100644 --- a/lustre/utils/lfind.c +++ b/lustre/utils/lfind.c @@ -24,7 +24,7 @@ char * cmd; struct option longOpts[] = { {"help", 0, 0, 'h'}, {"obd", 1, 0, 'o'}, - {"query", 0, 0, 'o'}, + {"query", 0, 0, 'q'}, {"verbose", 0, 0, 'v'}, {0, 0, 0, 0} }; @@ -217,8 +217,8 @@ processFile(const char *path, const struct stat *sp, int flag, struct FTW *ftwp) close(fd); - if (query || verbose) - printf("\n%s:\n", path); + if (query || verbose || lmm->lmm_objects[obdindex].l_object_id) + printf("%s\n", path); if (verbose) { printf("lmm_magic: 0x%x\n", lmm->lmm_magic); @@ -232,24 +232,26 @@ processFile(const char *path, const struct stat *sp, int flag, struct FTW *ftwp) count = lmm->lmm_ost_count; if (query || verbose) { - struct lov_object_id *loi; - __u64 oid; - - loi = lmm->lmm_objects; - - printf("obdidx\tobjid\n"); - - for (i = 0; i < count; i++, loi++) - if ((oid = loi->l_object_id)) - printf("%6d\t%5lld\n", i, (long long)oid); + long long oid; + int ost = lmm->lmm_stripe_offset; + int header = 1; + + for (i = 0; i < count; i++, ost++) { + ost %= lmm->lmm_ost_count; + if ((oid = lmm->lmm_objects[ost].l_object_id)) { + if (header) { + printf("\tobdidx\t objid\n"); + header = 0; + } + printf("\t%6u\t%8llu%s\n", + ost, oid, obdindex == ost ? " *" : ""); + } + } if (query) return(0); } - if (lmm->lmm_objects[obdindex].l_object_id) - printf("%s\n", path); - return(0); } @@ -297,7 +299,7 @@ getobdindex(const char *path) obdcount = desc.ld_tgt_count; - if (query) { + if (query || verbose) { printf("OBDS:\n"); for (i = 0, uuidp = uuids; i < obdcount; i++, uuidp++) printf("%4d: %s\n", i, (char *)uuidp); -- 1.8.3.1