From 26969941d8be6bef2ce1d48ddf8cb3432343192a Mon Sep 17 00:00:00 2001 From: pschwan Date: Tue, 17 Dec 2002 05:50:04 +0000 Subject: [PATCH] land b_md onto HEAD. almost entirely small cleanups and miscellaneous fixes, plus: - fix lock order deadlock on OST (O/R i_sem before journal ops, 478) - fix follow_symlink bugs (437) - preparation for some ldlm race fixes (419) --- lustre/ChangeLog | 1 + lustre/configure.in | 2 +- lustre/include/linux/lustre_dlm.h | 8 ++- lustre/ldlm/ldlm_lock.c | 115 ++++++++++++++++++-------------------- lustre/ldlm/ldlm_lockd.c | 1 + lustre/ldlm/ldlm_resource.c | 60 ++++++++++++-------- lustre/llite/dir.c | 2 +- lustre/llite/symlink.c | 20 ++++--- lustre/mds/handler.c | 2 +- lustre/mds/mds_reint.c | 22 +++++--- lustre/obdclass/class_obd.c | 2 +- lustre/ost/ost_handler.c | 2 +- lustre/ptlrpc/client.c | 2 +- lustre/ptlrpc/niobuf.c | 5 +- lustre/tests/.cvsignore | 1 + lustre/tests/acceptance-small.sh | 10 +++- lustre/tests/checkstat.c | 59 ++++++++++--------- lustre/tests/fsx.c | 25 +++------ lustre/tests/multifstat.c | 30 +++++----- lustre/tests/sanity.sh | 65 ++++++++++++++++++--- lustre/tests/sanityN.sh | 8 +-- 21 files changed, 257 insertions(+), 185 deletions(-) diff --git a/lustre/ChangeLog b/lustre/ChangeLog index 8da1889..fc930e2d 100644 --- a/lustre/ChangeLog +++ b/lustre/ChangeLog @@ -19,6 +19,7 @@ TBA - bulk descriptors were free()d too soon (511) - fix paths in lconf, which would load incorrect modules (451, 507) - fix confusing lconf 'host not found' error message (386) + - fix lock order deadlock on OST (O/R i_sem before journal ops, 478) 2002-12-02 Andreas Dilger * version v0_5_18 diff --git a/lustre/configure.in b/lustre/configure.in index 47c3d35..bd378b7 100644 --- a/lustre/configure.in +++ b/lustre/configure.in @@ -60,7 +60,7 @@ CPPFLAGS="$KINCFLAGS $ARCHCPPFLAGS" portalsdir_def='$(top_srcdir)/../portals' AC_ARG_WITH(portals, [ --with-portals=[path] set path to Portals source (default=../portals)], enable_portalsdir=$withval) -AC_ARG_ENABLE(portalsdir, [ --enable-portalsdir=[path] (deprecated) set path to Portals source (default=$(top_srcdir)/../portals)],, enable_portalsdir=$portalsdir_def) +AC_ARG_ENABLE(portalsdir, [ --enable-portalsdir=[path] (deprecated) set path to Portals source (default=$portalsdir_def],, enable_portalsdir=$portalsdir_def) PORTALS=$enable_portalsdir if test $PORTALS = $portalsdir_def; then diff --git a/lustre/include/linux/lustre_dlm.h b/lustre/include/linux/lustre_dlm.h index 916db86..c1382a9 100644 --- a/lustre/include/linux/lustre_dlm.h +++ b/lustre/include/linux/lustre_dlm.h @@ -12,6 +12,7 @@ #include #include #include +#include struct obd_ops; struct obd_device; @@ -151,9 +152,9 @@ struct ldlm_lock { struct list_head l_children; struct list_head l_childof; struct list_head l_lru; - struct list_head l_res_link; /*position in one of three res lists*/ - struct list_head l_export_chain; /* per-export chain of locks */ - struct list_head l_pending_chain; /* locks with callbacks pending*/ + struct list_head l_res_link; // position in one of three res lists + struct list_head l_export_chain; // per-export chain of locks + struct list_head l_pending_chain; // locks with callbacks pending unsigned long l_callback_timeout; ldlm_mode_t l_req_mode; @@ -373,6 +374,7 @@ void ldlm_cancel_locks_for_export(struct obd_export *export); void ldlm_run_ast_work(struct list_head *rpc_list); void ldlm_reprocess_all(struct ldlm_resource *res); void ldlm_lock_dump(struct ldlm_lock *lock); +void ldlm_lock_dump_handle(struct lustre_handle *); /* ldlm_test.c */ int ldlm_test(struct obd_device *device, struct lustre_handle *connh); diff --git a/lustre/ldlm/ldlm_lock.c b/lustre/ldlm/ldlm_lock.c index 9742eec..81b3b5d 100644 --- a/lustre/ldlm/ldlm_lock.c +++ b/lustre/ldlm/ldlm_lock.c @@ -141,10 +141,7 @@ void ldlm_unregister_intent(void) */ struct ldlm_lock *ldlm_lock_get(struct ldlm_lock *lock) { - l_lock(&lock->l_resource->lr_namespace->ns_lock); atomic_inc(&lock->l_refc); - ldlm_resource_getref(lock->l_resource); - l_unlock(&lock->l_resource->lr_namespace->ns_lock); return lock; } @@ -153,34 +150,25 @@ void ldlm_lock_put(struct ldlm_lock *lock) struct ldlm_namespace *ns = lock->l_resource->lr_namespace; ENTRY; - l_lock(&ns->ns_lock); - atomic_dec(&lock->l_refc); - LASSERT(atomic_read(&lock->l_refc) >= 0); - - if (ldlm_resource_putref(lock->l_resource)) { - LASSERT(atomic_read(&lock->l_refc) == 0); - lock->l_resource = NULL; - } - if (lock->l_parent) - LDLM_LOCK_PUT(lock->l_parent); - - if (atomic_read(&lock->l_refc) == 0) { - LASSERT(lock->l_destroyed); - l_unlock(&ns->ns_lock); + if (atomic_dec_and_test(&lock->l_refc)) { + l_lock(&ns->ns_lock); LDLM_DEBUG(lock, "final lock_put on destroyed lock, freeing"); + LASSERT(lock->l_destroyed); + LASSERT(list_empty(&lock->l_res_link)); spin_lock(&ns->ns_counter_lock); ns->ns_locks--; spin_unlock(&ns->ns_counter_lock); + ldlm_resource_putref(lock->l_resource); lock->l_resource = NULL; - lock->l_random = DEAD_HANDLE_MAGIC; - memset(lock, 0x5a, sizeof(*lock)); - kmem_cache_free(ldlm_lock_slab, lock); - CDEBUG(D_MALLOC, "kfreed 'lock': %d at %p (tot 0).\n", - sizeof(*lock), lock); - } else + + if (lock->l_parent) + LDLM_LOCK_PUT(lock->l_parent); + + PORTAL_SLAB_FREE(lock, ldlm_lock_slab, sizeof(*lock)); l_unlock(&ns->ns_lock); + } EXIT; } @@ -227,27 +215,35 @@ void ldlm_lock_destroy(struct ldlm_lock *lock) } lock->l_destroyed = 1; - list_del(&lock->l_export_chain); - lock->l_export = NULL; + list_del_init(&lock->l_export_chain); ldlm_lock_remove_from_lru(lock); +#if 0 /* Wake anyone waiting for this lock */ /* FIXME: I should probably add yet another flag, instead of using * l_export to only call this on clients */ + lock->l_export = NULL; if (lock->l_export && lock->l_completion_ast) lock->l_completion_ast(lock, 0); +#endif l_unlock(&lock->l_resource->lr_namespace->ns_lock); LDLM_LOCK_PUT(lock); EXIT; } +/* this is called by portals_handle2object with the handle lock taken */ +static void lock_handle_addref(void *lock) +{ + ldlm_lock_get(lock); +} + /* - usage: pass in a resource on which you have done get - pass in a parent lock on which you have done a get - do not put the resource or the parent - returns: lock with refcount 1 -*/ + * usage: pass in a resource on which you have done ldlm_resource_get + * pass in a parent lock on which you have done a ldlm_lock_get + * after return, ldlm_*_put the resource and parent + * returns: lock with refcount 1 + */ static struct ldlm_lock *ldlm_lock_new(struct ldlm_lock *parent, struct ldlm_resource *resource) { @@ -257,17 +253,14 @@ static struct ldlm_lock *ldlm_lock_new(struct ldlm_lock *parent, if (resource == NULL) LBUG(); - lock = kmem_cache_alloc(ldlm_lock_slab, SLAB_KERNEL); + PORTAL_SLAB_ALLOC(lock, ldlm_lock_slab, sizeof(*lock)); if (lock == NULL) RETURN(NULL); - memset(lock, 0, sizeof(*lock)); get_random_bytes(&lock->l_random, sizeof(__u64)); + lock->l_resource = ldlm_resource_getref(resource); - lock->l_resource = resource; - /* this refcount matches the one of the resource passed - in which is not being put away */ - atomic_set(&lock->l_refc, 1); + atomic_set(&lock->l_refc, 2); INIT_LIST_HEAD(&lock->l_children); INIT_LIST_HEAD(&lock->l_res_link); INIT_LIST_HEAD(&lock->l_lru); @@ -281,15 +274,11 @@ static struct ldlm_lock *ldlm_lock_new(struct ldlm_lock *parent, if (parent != NULL) { l_lock(&parent->l_resource->lr_namespace->ns_lock); - lock->l_parent = parent; + lock->l_parent = LDLM_LOCK_GET(parent); list_add(&lock->l_childof, &parent->l_children); l_unlock(&parent->l_resource->lr_namespace->ns_lock); } - CDEBUG(D_MALLOC, "kmalloced 'lock': %d at " - "%p (tot %d).\n", sizeof(*lock), lock, 1); - /* this is the extra refcount, to prevent the lock from evaporating */ - LDLM_LOCK_GET(lock); RETURN(lock); } @@ -297,7 +286,6 @@ int ldlm_lock_change_resource(struct ldlm_lock *lock, __u64 new_resid[3]) { struct ldlm_namespace *ns = lock->l_resource->lr_namespace; struct ldlm_resource *oldres = lock->l_resource; - int i, refc; ENTRY; l_lock(&ns->ns_lock); @@ -320,17 +308,8 @@ int ldlm_lock_change_resource(struct ldlm_lock *lock, __u64 new_resid[3]) RETURN(-ENOMEM); } - /* move references over */ - refc = atomic_read(&lock->l_refc); - for (i = 0; i < refc; i++) { - int rc; - ldlm_resource_getref(lock->l_resource); - rc = ldlm_resource_putref(oldres); - if (rc == 1 && i != refc - 1) - LBUG(); - } - /* compensate for the initial get above.. */ - ldlm_resource_putref(lock->l_resource); + /* ...and the flowers are still standing! */ + ldlm_resource_putref(oldres); l_unlock(&ns->ns_lock); RETURN(0); @@ -398,8 +377,6 @@ struct ldlm_lock *__ldlm_handle2lock(struct lustre_handle *handle, int strict, lock->l_flags |= flags; retval = LDLM_LOCK_GET(lock); - if (!retval) - CERROR("lock disappeared below us!!! %p\n", lock); EXIT; out: l_unlock(&lock->l_resource->lr_namespace->ns_lock); @@ -720,10 +697,12 @@ struct ldlm_lock *ldlm_lock_create(struct ldlm_namespace *ns, RETURN(NULL); lock = ldlm_lock_new(parent_lock, res); - if (lock == NULL) { - ldlm_resource_putref(res); + ldlm_resource_putref(res); + if (parent_lock != NULL) + LDLM_LOCK_PUT(parent_lock); + + if (lock == NULL) RETURN(NULL); - } lock->l_req_mode = mode; lock->l_data = data; @@ -785,7 +764,7 @@ ldlm_error_t ldlm_lock_enqueue(struct ldlm_lock * lock, * We do exactly the same thing during recovery, when the server is * more or less trusting the clients not to lie. * - * FIXME (bug 629283): Detect obvious lies by checking compatibility in + * FIXME (bug 268): Detect obvious lies by checking compatibility in * granted/converting queues. */ ldlm_resource_unlink_lock(lock); if (local || (*flags & LDLM_FL_REPLAY)) { @@ -926,8 +905,11 @@ void ldlm_lock_cancel(struct ldlm_lock *lock) ns = res->lr_namespace; l_lock(&ns->ns_lock); - if (lock->l_readers || lock->l_writers) + if (lock->l_readers || lock->l_writers) { LDLM_DEBUG(lock, "lock still has references"); + ldlm_lock_dump(lock); + //LBUG(); + } ldlm_cancel_callback(lock); @@ -1057,3 +1039,16 @@ void ldlm_lock_dump(struct ldlm_lock *lock) (unsigned long long)lock->l_extent.start, (unsigned long long)lock->l_extent.end); } + +void ldlm_lock_dump_handle(struct lustre_handle *lockh) +{ + struct ldlm_lock *lock; + + lock = ldlm_handle2lock(lockh); + if (lock == NULL) + return; + + ldlm_lock_dump(lock); + + LDLM_LOCK_PUT(lock); +} diff --git a/lustre/ldlm/ldlm_lockd.c b/lustre/ldlm/ldlm_lockd.c index cbf67d0..b76fbcd 100644 --- a/lustre/ldlm/ldlm_lockd.c +++ b/lustre/ldlm/ldlm_lockd.c @@ -790,6 +790,7 @@ EXPORT_SYMBOL(ldlm_test); EXPORT_SYMBOL(ldlm_regression_start); EXPORT_SYMBOL(ldlm_regression_stop); EXPORT_SYMBOL(ldlm_lock_dump); +EXPORT_SYMBOL(ldlm_lock_dump_handle); EXPORT_SYMBOL(ldlm_namespace_new); EXPORT_SYMBOL(ldlm_namespace_cleanup); EXPORT_SYMBOL(ldlm_namespace_free); diff --git a/lustre/ldlm/ldlm_resource.c b/lustre/ldlm/ldlm_resource.c index 8bb5aa3..d1f5b61 100644 --- a/lustre/ldlm/ldlm_resource.c +++ b/lustre/ldlm/ldlm_resource.c @@ -24,7 +24,7 @@ int ldlm_proc_setup(struct obd_device *obd) { ENTRY; LASSERT(ldlm_ns_proc_dir == NULL); - ldlm_ns_proc_dir=obd->obd_type->typ_procroot; + ldlm_ns_proc_dir = obd->obd_type->typ_procroot; RETURN(0); } @@ -33,11 +33,20 @@ void ldlm_proc_cleanup(struct obd_device *obd) ldlm_ns_proc_dir = NULL; } +static int lprocfs_uint_rd(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + unsigned int *temp = (unsigned int *)data; + int len; + len = snprintf(page, count, "%u\n", *temp); + return len; +} + #define MAX_STRING_SIZE 100 void ldlm_proc_namespace(struct ldlm_namespace *ns) { struct lprocfs_vars lock_vars[2]; - char lock_names[MAX_STRING_SIZE+1]; + char lock_names[MAX_STRING_SIZE + 1]; memset(lock_vars, 0, sizeof(lock_vars)); snprintf(lock_names, MAX_STRING_SIZE, "%s/resource_count", ns->ns_name); @@ -57,6 +66,15 @@ void ldlm_proc_namespace(struct ldlm_namespace *ns) lock_vars[0].data = &ns->ns_locks; lprocfs_add_vars(ldlm_ns_proc_dir, lock_vars, 0); + memset(lock_vars, 0, sizeof(lock_vars)); + snprintf(lock_names, MAX_STRING_SIZE, "%s/lock_unused_count", + ns->ns_name); + lock_names[MAX_STRING_SIZE] = '\0'; + lock_vars[0].name = lock_names; + lock_vars[0].read_fptr = lprocfs_uint_rd; + lock_vars[0].write_fptr = NULL; + lock_vars[0].data = &ns->ns_nr_unused; + lprocfs_add_vars(ldlm_ns_proc_dir, lock_vars, 0); } #undef MAX_STRING_SIZE @@ -307,26 +325,21 @@ struct ldlm_resource *ldlm_resource_get(struct ldlm_namespace *ns, struct ldlm_resource *parent, __u64 *name, __u32 type, int create) { - struct list_head *bucket; - struct list_head *tmp = bucket; + struct list_head *bucket, *tmp; struct ldlm_resource *res = NULL; ENTRY; - if (ns == NULL || ns->ns_hash == NULL) { - LBUG(); - RETURN(NULL); - } + LASSERT(ns != NULL); + LASSERT(ns->ns_hash != NULL); l_lock(&ns->ns_lock); bucket = ns->ns_hash + ldlm_hash_fn(parent, name); list_for_each(tmp, bucket) { - struct ldlm_resource *chk; - chk = list_entry(tmp, struct ldlm_resource, lr_hash); + res = list_entry(tmp, struct ldlm_resource, lr_hash); - if (memcmp(chk->lr_name, name, sizeof(chk->lr_name)) == 0) { - res = chk; - atomic_inc(&res->lr_refcount); + if (memcmp(res->lr_name, name, sizeof(res->lr_name)) == 0) { + ldlm_resource_getref(res); l_unlock(&ns->ns_lock); RETURN(res); } @@ -334,6 +347,9 @@ struct ldlm_resource *ldlm_resource_get(struct ldlm_namespace *ns, if (create) res = ldlm_resource_add(ns, parent, name, type); + else + res = NULL; + l_unlock(&ns->ns_lock); RETURN(res); @@ -351,12 +367,16 @@ struct ldlm_resource *ldlm_resource_getref(struct ldlm_resource *res) int ldlm_resource_putref(struct ldlm_resource *res) { int rc = 0; + ENTRY; + + CDEBUG(D_INFO, "putref res: %p count: %d\n", res, + atomic_read(&res->lr_refcount) - 1); + LASSERT(atomic_read(&res->lr_refcount) > 0); + LASSERT(atomic_read(&res->lr_refcount) < 0x5a5a5a5a); if (atomic_dec_and_test(&res->lr_refcount)) { struct ldlm_namespace *ns = res->lr_namespace; ENTRY; - CDEBUG(D_INFO, "putref res: %p count: %d\n", res, - atomic_read(&res->lr_refcount)); l_lock(&ns->ns_lock); @@ -387,8 +407,8 @@ int ldlm_resource_putref(struct ldlm_resource *res) } ns->ns_refcount--; - list_del(&res->lr_hash); - list_del(&res->lr_childof); + list_del_init(&res->lr_hash); + list_del_init(&res->lr_childof); memset(res, 0x5a, sizeof(*res)); kmem_cache_free(ldlm_resource_slab, res); @@ -399,11 +419,7 @@ int ldlm_resource_putref(struct ldlm_resource *res) spin_unlock(&ns->ns_counter_lock); rc = 1; - } else { - ENTRY; - CDEBUG(D_INFO, "putref res: %p count: %d\n", res, - atomic_read(&res->lr_refcount)); - LASSERT(atomic_read(&res->lr_refcount) >= 0); + EXIT; } RETURN(rc); diff --git a/lustre/llite/dir.c b/lustre/llite/dir.c index 6f67f4b..ab9596f 100644 --- a/lustre/llite/dir.c +++ b/lustre/llite/dir.c @@ -91,7 +91,7 @@ static int ll_dir_readpage(struct file *file, struct page *page) unlock_page(page); RETURN(rc); } - ldlm_lock_dump((void *)(unsigned long)lockh.addr); + ldlm_lock_dump_handle(&lockh); if (PageUptodate(page)) { CERROR("Explain this please?\n"); diff --git a/lustre/llite/symlink.c b/lustre/llite/symlink.c index a89ca2a..ef86d58 100644 --- a/lustre/llite/symlink.c +++ b/lustre/llite/symlink.c @@ -89,24 +89,28 @@ static int ll_follow_link(struct dentry *dentry, struct nameidata *nd, struct inode *inode = dentry->d_inode; struct ll_inode_info *lli = ll_i2info(inode); struct ptlrpc_request *request; - int op, mode; + int op, mode, rc; char *symname; - int rc; ENTRY; - op = it->it_op; - mode = it->it_mode; + if (it != NULL) { + op = it->it_op; + mode = it->it_mode; - ll_intent_release(dentry, it); - down(&lli->lli_open_sem); + ll_intent_release(dentry, it); + } - it->it_op = op; - it->it_mode = mode; + down(&lli->lli_open_sem); rc = ll_readlink_internal(inode, &request, &symname); if (rc) GOTO(out, rc); + if (it != NULL) { + it->it_op = op; + it->it_mode = mode; + } + rc = vfs_follow_link_it(nd, symname, it); out: up(&lli->lli_open_sem); diff --git a/lustre/mds/handler.c b/lustre/mds/handler.c index dea3f57..ea30d51 100644 --- a/lustre/mds/handler.c +++ b/lustre/mds/handler.c @@ -703,7 +703,7 @@ static int mds_getattr_name(int offset, struct ptlrpc_request *req) GOTO(out_create_de, rc = -EIO); } } - ldlm_lock_dump((void *)(unsigned long)lockh.addr); + ldlm_lock_dump_handle(&lockh); down(&dir->i_sem); dchild = lookup_one_len(name, de, namelen - 1); diff --git a/lustre/mds/mds_reint.c b/lustre/mds/mds_reint.c index 689e424..9151326 100644 --- a/lustre/mds/mds_reint.c +++ b/lustre/mds/mds_reint.c @@ -220,7 +220,7 @@ static int mds_reint_create(struct mds_update_record *rec, int offset, 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); + ldlm_lock_dump_handle(&lockh); down(&dir->i_sem); dchild = lookup_one_len(rec->ur_name, de, rec->ur_namelen - 1); @@ -571,8 +571,9 @@ static int mds_reint_link(struct mds_update_record *rec, int offset, CERROR("lock enqueue: err: %d\n", rc); GOTO(out_link_src_put, rc = -EIO); } - } else - ldlm_lock_dump((void *)(unsigned long)srclockh.addr); + } else { + ldlm_lock_dump_handle(&srclockh); + } de_tgt_dir = mds_fid2dentry(mds, rec->ur_fid2, NULL); if (IS_ERR(de_tgt_dir)) { @@ -595,8 +596,9 @@ static int mds_reint_link(struct mds_update_record *rec, int offset, CERROR("lock enqueue: err: %d\n", rc); GOTO(out_link_tgt_dir_put, rc = -EIO); } - } else - ldlm_lock_dump((void *)(unsigned long)tgtlockh.addr); + } else { + ldlm_lock_dump_handle(&tgtlockh); + } down(&de_tgt_dir->d_inode->i_sem); dchild = lookup_one_len(rec->ur_name, de_tgt_dir, rec->ur_namelen - 1); @@ -706,8 +708,9 @@ static int mds_reint_rename(struct mds_update_record *rec, int offset, CERROR("lock enqueue: err: %d\n", rc); GOTO(out_rename_srcput, rc = -EIO); } - } else - ldlm_lock_dump((void *)(unsigned long)srclockh.addr); + } else { + ldlm_lock_dump_handle(&srclockh); + } de_tgtdir = mds_fid2dentry(mds, rec->ur_fid2, NULL); if (IS_ERR(de_tgtdir)) @@ -730,8 +733,9 @@ static int mds_reint_rename(struct mds_update_record *rec, int offset, CERROR("lock enqueue: err: %d\n", rc); GOTO(out_rename_tgtput, rc = -EIO); } - } else - ldlm_lock_dump((void *)(unsigned long)tgtlockh.addr); + } else { + ldlm_lock_dump_handle(&tgtlockh); + } #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) double_lock(de_tgtdir, de_srcdir); diff --git a/lustre/obdclass/class_obd.c b/lustre/obdclass/class_obd.c index 03faf17..4769d61 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 != 4) +#if (LUSTRE_KERNEL_VERSION != 5) # error Cannot continue: Your Lustre kernel patch is out of date #endif diff --git a/lustre/ost/ost_handler.c b/lustre/ost/ost_handler.c index 3dea05f..6ccb240 100644 --- a/lustre/ost/ost_handler.c +++ b/lustre/ost/ost_handler.c @@ -613,7 +613,7 @@ static int ost_setup(struct obd_device *obddev, obd_count len, void *buf) "self", ost_handle, "ost"); if (!ost->ost_service) { CERROR("failed to start service\n"); - GOTO(error_disc, err = -EINVAL); + GOTO(error_disc, err = -ENOMEM); } for (i = 0; i < OST_NUM_THREADS; i++) { diff --git a/lustre/ptlrpc/client.c b/lustre/ptlrpc/client.c index 09b0662..b909b75 100644 --- a/lustre/ptlrpc/client.c +++ b/lustre/ptlrpc/client.c @@ -262,7 +262,7 @@ struct ptlrpc_request *ptlrpc_prep_req(struct obd_import *imp, int opcode, int rc; ENTRY; - LASSERT(imp); + LASSERT((unsigned long)imp > 0x1000); conn = imp->imp_connection; OBD_ALLOC(request, sizeof(*request)); diff --git a/lustre/ptlrpc/niobuf.c b/lustre/ptlrpc/niobuf.c index bfd11bc..5cbdbc5 100644 --- a/lustre/ptlrpc/niobuf.c +++ b/lustre/ptlrpc/niobuf.c @@ -280,6 +280,8 @@ int ptlrpc_abort_bulk(struct ptlrpc_bulk_desc *desc) void obd_brw_set_add(struct obd_brw_set *set, struct ptlrpc_bulk_desc *desc) { + LASSERT(list_empty(&desc->bd_set_chain)); + ptlrpc_bulk_addref(desc); atomic_inc(&set->brw_refcount); desc->bd_brw_set = set; @@ -385,7 +387,8 @@ int ptl_send_rpc(struct ptlrpc_request *request) /* request->rq_repmsg is set only when the reply comes in, in * client_packet_callback() */ if (request->rq_reply_md.start) { - PtlMEUnlink(request->rq_reply_me_h); + rc = PtlMEUnlink(request->rq_reply_me_h); + LASSERT (rc == PTL_OK); OBD_FREE(request->rq_reply_md.start, request->rq_replen); /* If we're resending, rq_repmsg needs to be NULLed out diff --git a/lustre/tests/.cvsignore b/lustre/tests/.cvsignore index e34f984..a6d15c2d 100644 --- a/lustre/tests/.cvsignore +++ b/lustre/tests/.cvsignore @@ -28,3 +28,4 @@ lovstripe stat setuid multifstat +checkstat diff --git a/lustre/tests/acceptance-small.sh b/lustre/tests/acceptance-small.sh index 06c4a84..5202052 100755 --- a/lustre/tests/acceptance-small.sh +++ b/lustre/tests/acceptance-small.sh @@ -22,14 +22,16 @@ for NAME in $CONFIGS; do sh runtests fi - mount | grep $MNT || sh llmount.sh [ "$SANITY" != "no" ] && sh sanity.sh + if [ "$DBENCH" != "no" ]; then + mount | grep $MNT || sh llmount.sh $DEBUG_OFF sh rundbench 1 sh llmountcleanup.sh sh llrmount.sh if [ $THREADS -gt 1 ]; then + $DEBUG_OFF sh rundbench $THREADS sh llmountcleanup.sh sh llrmount.sh @@ -38,6 +40,7 @@ for NAME in $CONFIGS; do fi chown $UID $MNT && chmod 700 $MNT if [ "$BONNIE" != "no" ]; then + mount | grep $MNT || sh llmount.sh $DEBUG_OFF bonnie++ -s 0 -n 10 -u $UID -d $MNT sh llmountcleanup.sh @@ -46,12 +49,14 @@ for NAME in $CONFIGS; do IOZONE_OPTS="-i 0 -i 1 -i 2 -+d -r $RSIZE -s $SIZE" IOZONE_FILE="-f $MNT/iozone" if [ "$IOZONE" != "no" ]; then + mount | grep $MNT || sh llmount.sh $DEBUG_OFF iozone $IOZONE_OPTS $IOZONE_FILE sh llmountcleanup.sh sh llrmount.sh fi if [ "$IOZONE_DIR" != "no" ]; then + mount | grep $MNT || sh llmount.sh $DEBUG_OFF iozone -I $IOZONE_OPTS $IOZONE_FILE.odir IOZVER=`iozone -v | awk '/Revision:/ { print $3 }' | tr -d '.'` @@ -75,8 +80,9 @@ for NAME in $CONFIGS; do fi fi if [ "$FSX" != "no" ]; then + mount | grep $MNT || sh llmount.sh $DEBUG_OFF - ./fsx -c 50 -p 1000 -P $TMP -l 1024000 -N $(($COUNT * 100)) $MNT/fsxfile + ./fsx -W -c 50 -p 1000 -P $TMP -l 1024000 -N $(($COUNT * 100)) $MNT/fsxfile sh llmountcleanup.sh #sh llrmount.sh fi diff --git a/lustre/tests/checkstat.c b/lustre/tests/checkstat.c index ed97bd6..f09fde9 100644 --- a/lustre/tests/checkstat.c +++ b/lustre/tests/checkstat.c @@ -15,17 +15,17 @@ usage (char *argv0, int help) if (progname == NULL) progname = argv0; - + fprintf (help ? stdout : stderr, "Usage: %s [flags] file[s]\n", progname); - + if (!help) { fprintf (stderr, " or try '-h' for help\n"); exit (1); } - + printf ("Check given files have...\n"); printf (" -p permission file must have required permissions\n"); printf (" -t dir|file|link file must be of the specified type\n"); @@ -55,7 +55,7 @@ main (int argc, char **argv) long long size = -1; int follow = 0; char *term; - + while ((c = getopt (argc, argv, "p:t:l:s:u:g:avfh")) != -1) switch (c) { @@ -92,7 +92,7 @@ main (int argc, char **argv) } } else { struct passwd *pw = getpwnam (optarg); - + if (pw == NULL) { fprintf (stderr, "Can't find user %s\n", optarg); @@ -113,7 +113,7 @@ main (int argc, char **argv) } } else { struct group *gr = getgrnam (optarg); - + if (gr == NULL) { fprintf (stderr, "Can't find group %s\n", optarg); @@ -122,7 +122,7 @@ main (int argc, char **argv) uid = gr->gr_gid; } break; - + case 't': type = optarg; break; @@ -134,33 +134,33 @@ main (int argc, char **argv) case 'v': verbose++; break; - + case 'f': follow++; break; - + case 'h': usage (argv[0], 1); return (0); - + default: usage (argv[0], 0); } if (optind == argc) usage (argv[0], 0); - + do { char *fname = argv[optind]; int rc = follow ? stat64 (fname, &buf) : lstat64 (fname, &buf); - + if (rc != 0) { if (!(absent && errno == ENOENT)) { if (verbose) - printf ("Can't %sstat %s: %s\n", + printf ("Can't %sstat %s: %s\n", follow ? "" : "l", fname, strerror (errno)); return (1); @@ -177,38 +177,38 @@ main (int argc, char **argv) printf ("%s exists\n", fname); return (1); } - + if (type != NULL) { - if (!strcmp (type, "d") || + if (!strcmp (type, "d") || !strcmp (type, "dir")) { if (!S_ISDIR (buf.st_mode)) { if (verbose) - printf ("%s is not a directory\n", + printf ("%s is not a directory\n", fname); return (1); } } - else if (!strcmp (type, "f") || + else if (!strcmp (type, "f") || !strcmp (type, "file")) { if (!S_ISREG (buf.st_mode)) { if (verbose) - printf ("%s is not a regular file\n", + printf ("%s is not a regular file\n", fname); return (1); } } - else if (!strcmp (type, "l") || + else if (!strcmp (type, "l") || !strcmp (type, "link")) { if (!S_ISLNK (buf.st_mode)) { if (verbose) - printf ("%s is not a link\n", + printf ("%s is not a link\n", fname); return (1); } @@ -218,7 +218,7 @@ main (int argc, char **argv) fprintf (stderr, "Can't parse file type %s\n", type); return (1); } - + if (verbose) printf ("%s has type %s OK\n", fname, type); } @@ -247,11 +247,11 @@ main (int argc, char **argv) fname, (long long)buf.st_size, size); return (1); } - + if (verbose) printf ("%s has size %Ld OK\n", fname, size); } - + if (checklink != NULL) { static char lname[4<<10]; @@ -265,7 +265,7 @@ main (int argc, char **argv) fname, strerror (errno)); return (1); } - + lname[rc] = 0; if (strcmp (checklink, lname)) { @@ -274,7 +274,7 @@ main (int argc, char **argv) fname, lname, checklink); return (1); } - + if (verbose) printf ("%s links to %s OK\n", fname, checklink); } @@ -288,12 +288,12 @@ main (int argc, char **argv) fname, (long)buf.st_uid, (long)uid); return (1); } - + if (verbose) printf ("%s is owned by user #%ld OK\n", fname, (long)uid); } - + if (gid != (gid_t)-1) { if (buf.st_gid != gid) @@ -303,13 +303,12 @@ main (int argc, char **argv) fname, (long)buf.st_gid, (long)gid); return (1); } - + if (verbose) printf ("%s is owned by group #%ld OK\n", fname, (long)gid); } - } while (++optind < argc); - + return (0); } diff --git a/lustre/tests/fsx.c b/lustre/tests/fsx.c index 859f40a..a2b1d5e 100644 --- a/lustre/tests/fsx.c +++ b/lustre/tests/fsx.c @@ -127,7 +127,6 @@ int mapped_reads = 1; /* -R flag disables it */ int fsxgoodfd = 0; FILE * fsxlogf = NULL; int badoff = -1; -int closeopen = 0; void @@ -182,8 +181,6 @@ log4(int operation, int arg0, int arg1, int arg2, struct timeval *tv) le = &oplog[logptr]; le->tv = *tv; le->operation = operation; - if (closeopen) - le->operation = ~ le->operation; le->args[0] = arg0; le->args[1] = arg1; le->args[2] = arg2; @@ -213,14 +210,12 @@ logdump(void) opnum = i+1 + (logcount/LOGSIZE)*LOGSIZE; lp = &oplog[i]; - prt("%d(%d mod 256): %lu.%06lu ", opnum, opnum%256, + prt("%d: %lu.%06lu ", opnum, 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 (0x%x bytes)", + prt("MAPREAD 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 +231,7 @@ logdump(void) prt("\t******WWWW"); break; case OP_READ: - prt("READ\t0x%x thru 0x%x (0x%x bytes)", + prt("READ 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] && @@ -244,7 +239,7 @@ logdump(void) prt("\t***RRRR***"); break; case OP_WRITE: - prt("WRITE\t0x%x thru 0x%x (0x%x bytes)", + prt("WRITE 0x%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]) @@ -263,6 +258,9 @@ logdump(void) badoff < lp->args[!!down]) prt("\t******WWWW"); break; + case OP_CLOSEOPEN: + prt("CLOSE/OPEN"); + break; case OP_SKIPPED: prt("SKIPPED (no operation)"); break; @@ -270,8 +268,6 @@ logdump(void) prt("BOGUS LOG ENTRY (operation code = %d)!", lp->operation); } - if (closeopen) - prt("\n\t\tCLOSE/OPEN"); prt("\n"); i++; if (i == LOGSIZE) @@ -821,9 +817,9 @@ docloseopen(void) if (testcalls <= simulatedopcount) return; + gettimeofday(&t, NULL); log4(OP_CLOSEOPEN, file_size, (unsigned)file_size, 0, &t); - gettimeofday(&t, NULL); if (debug) prt("%06lu %lu.%06lu close/open\n", testcalls, t.tv_sec, t.tv_usec); @@ -865,9 +861,6 @@ test(void) testcalls++; - if (closeprob) - closeopen = (rv >> 3) < (1 << 28) / closeprob; - if (debugstart > 0 && testcalls >= debugstart) debug = 1; @@ -914,7 +907,7 @@ test(void) } if (sizechecks && testcalls > simulatedopcount) check_size(); - if (closeopen) + if (closeprob && (rv >> 3) < (1 << 28) / closeprob) docloseopen(); } diff --git a/lustre/tests/multifstat.c b/lustre/tests/multifstat.c index 56948d9..fa510bc 100644 --- a/lustre/tests/multifstat.c +++ b/lustre/tests/multifstat.c @@ -8,55 +8,55 @@ int main(int argc, char **argv) { - int fd1, fd2; + int fd1, fd2; struct stat st1, st2; - - if (argc != 3) { + + 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) { + if (fd1 == -1) { printf("Error opening %s: %s\n", argv[1], strerror(errno)); - return errno; + return errno; } fd2 = open(argv[2], O_RDONLY); - if (fd2 == -1) { + if (fd2 == -1) { printf("Error opening %s: %s\n", argv[2], strerror(errno)); - return errno; + return errno; } sleep(1); - if ( write(fd1, "hello", strlen("hello")) != strlen("hello")) { + if ( write(fd1, "hello", strlen("hello")) != strlen("hello")) { printf("Error writing: %s\n", strerror(errno)); return errno; } - if ( fstat(fd1, &st1) ) { + if ( fstat(fd1, &st1) ) { printf("Error statting %s: %s\n", argv[1], strerror(errno)); return errno; } - if ( fstat(fd2, &st2) ) { + 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", + 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", + 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 cbd17ca..626461a 100644 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -6,14 +6,14 @@ CHECKSTAT=${CHECKSTAT:-"./checkstat -v"} MOUNT=${MOUNT:-/mnt/lustre} export NAME=$NAME clean() { - echo -n "cleanup..." + echo -n "cln.." sh llmountcleanup.sh > /dev/null } CLEAN=${CLEAN:-clean} start() { - echo -n "mounting..." + echo -n "mnt.." sh llrmount.sh > /dev/null - echo -n "mounted" + echo -n "done" } START=${START:-start} @@ -26,6 +26,8 @@ pass() { echo PASS } +mount | grep $MOUNT || $START + echo '== touch .../f ; rm .../f ======================== test 0' touch $MOUNT/f $CHECKSTAT -t file $MOUNT/f || error @@ -144,7 +146,7 @@ $CLEAN $START -echo '== mkdir .../d10; mkdir .../d10/d2; touch .../d10/d2/f = test 10' +echo '== mkdir .../d10 .../d10/d2; touch .../d10/d2/f = test 10' mkdir $MOUNT/d10 mkdir $MOUNT/d10/d2 touch $MOUNT/d10/d2/f @@ -153,7 +155,7 @@ pass $CLEAN $START -echo '== mkdir .../d11 d11/d2; chmod .../d11/d2 .../d11/d2 == test 11' +echo '== mkdir .../d11 d11/d2; chmod .../d11/d2 ======= test 11' mkdir $MOUNT/d11 mkdir $MOUNT/d11/d2 chmod 0666 $MOUNT/d11/d2 @@ -163,7 +165,7 @@ pass $CLEAN $START -echo '== mkdir .../d12; touch .../d12/f; chmod .../d12/f d12/f == test 12' +echo '== mkdir .../d12; touch .../d12/f; chmod .../d12/f == test 12' mkdir $MOUNT/d12 touch $MOUNT/d12/f chmod 0666 $MOUNT/d12/f @@ -229,14 +231,14 @@ pass $CLEAN $START -echo "== touch $MOUNT/f ; ls $MOUNT ==================== test 18" +echo "== touch .../f ; ls ... ========================= test 18" touch $MOUNT/f ls $MOUNT || error pass $CLEAN $START -echo "== touch $MOUNT/f ; ls -l $MOUNT ================= test 19" +echo "== touch .../f ; ls -l ... ====================== test 19" touch $MOUNT/f ls -l $MOUNT rm $MOUNT/f @@ -245,7 +247,7 @@ pass $CLEAN $START -echo "== touch $MOUNT/f ; ls -l $MOUNT ================= test 20" +echo "== touch .../f ; ls -l ... ====================== test 20" touch $MOUNT/f rm $MOUNT/f echo "1 done" @@ -397,5 +399,50 @@ pass $CLEAN $START +echo '== symlink sanity ================================ test25' +echo "--test 25.1 create file in symlinked directory" +mkdir $MOUNT/d25 +ln -s d25 $MOUNT/s25 +touch $MOUNT/s25/foo +pass +$CLEAN +$START + +echo "--test 25.2 lookup file in symlinked directory" +$CHECKSTAT -a $MOUNT/s25/foo +pass +$CLEAN +$START + +echo "--test 26 multiple component symlink" +mkdir $MOUNT/d26 +mkdir $MOUNT/d26/d26-2 +ln -s d26/d26-2 $MOUNT/s26 +touch $MOUNT/s26/foo +pass +$CLEAN +$START + +echo "--test 26.1 multiple component symlink at the end of a lookup" +ln -s d26/d26-2/foo $MOUNT/s26-2 +touch $MOUNT/s26-2 +pass +$CLEAN +$START + +echo "--test 26.2 a chain of symlinks" +mkdir $MOUNT/d26.2 +touch $MOUNT/d26.2/foo +ln -s d26.2 $MOUNT/s26.2-1 +ln -s s26.2-1 $MOUNT/s26.2-2 +ln -s s26.2-2 $MOUNT/s26.2-3 +chmod 0666 $MOUNT/s26.2-3/foo +pass +$CLEAN +$START + +echo '== cleanup =========================================' +rm -r $MOUNT/[Rdfs][1-9]* + echo '======================= finished =======================' exit diff --git a/lustre/tests/sanityN.sh b/lustre/tests/sanityN.sh index b1536cc..9c50574 100644 --- a/lustre/tests/sanityN.sh +++ b/lustre/tests/sanityN.sh @@ -19,6 +19,9 @@ error () { exit 1 } +mkdir -p /mnt/lustre2 +mount | grep /mnt/lustre2 || $START + echo -n "test 1: check create on 2 mtpt's..." touch /mnt/lustre1/f1 [ -f /mnt/lustre2/f1 ] || error "test 1 failure" @@ -49,15 +52,12 @@ echo "pass" echo -n "test 9: remove of open file on other node..." touch /mnt/lustre1/f9 -tail -f /mnt/lustre/f9 & +tail -f /mnt/lustre1/f9 & rm /mnt/lustre2/f9 kill %1 cat /mnt/lustre1/f9 && error "test 9 fails" echo "pass" $CLEAN -$START - - exit -- 1.8.3.1