- 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 <adilger@clusterfs.com>
* version v0_5_18
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
#include <linux/lustre_lib.h>
#include <linux/lustre_net.h>
#include <linux/lustre_import.h>
+#include <linux/handles.h>
struct obd_ops;
struct obd_device;
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;
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);
*/
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;
}
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;
}
}
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)
{
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);
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);
}
{
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);
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);
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);
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;
* 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)) {
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);
(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);
+}
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);
{
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);
}
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);
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
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);
}
if (create)
res = ldlm_resource_add(ns, parent, name, type);
+ else
+ res = NULL;
+
l_unlock(&ns->ns_lock);
RETURN(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);
}
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);
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);
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");
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);
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);
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);
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)) {
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);
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))
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);
/* Check that we're building against the appropriate version of the Lustre
* kernel patch */
#include <linux/lustre_version.h>
-#if (LUSTRE_KERNEL_VERSION != 4)
+#if (LUSTRE_KERNEL_VERSION != 5)
# error Cannot continue: Your Lustre kernel patch is out of date
#endif
"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++) {
int rc;
ENTRY;
- LASSERT(imp);
+ LASSERT((unsigned long)imp > 0x1000);
conn = imp->imp_connection;
OBD_ALLOC(request, sizeof(*request));
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;
/* 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
stat
setuid
multifstat
+checkstat
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
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
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 '.'`
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
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");
long long size = -1;
int follow = 0;
char *term;
-
+
while ((c = getopt (argc, argv, "p:t:l:s:u:g:avfh")) != -1)
switch (c)
{
}
} else {
struct passwd *pw = getpwnam (optarg);
-
+
if (pw == NULL)
{
fprintf (stderr, "Can't find user %s\n", optarg);
}
} else {
struct group *gr = getgrnam (optarg);
-
+
if (gr == NULL)
{
fprintf (stderr, "Can't find group %s\n", optarg);
uid = gr->gr_gid;
}
break;
-
+
case 't':
type = optarg;
break;
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);
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);
}
fprintf (stderr, "Can't parse file type %s\n", type);
return (1);
}
-
+
if (verbose)
printf ("%s has type %s OK\n", fname, type);
}
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];
fname, strerror (errno));
return (1);
}
-
+
lname[rc] = 0;
if (strcmp (checklink, lname))
{
fname, lname, checklink);
return (1);
}
-
+
if (verbose)
printf ("%s links to %s OK\n", fname, checklink);
}
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)
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);
}
int fsxgoodfd = 0;
FILE * fsxlogf = NULL;
int badoff = -1;
-int closeopen = 0;
void
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;
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 <
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] &&
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])
badoff < lp->args[!!down])
prt("\t******WWWW");
break;
+ case OP_CLOSEOPEN:
+ prt("CLOSE/OPEN");
+ break;
case OP_SKIPPED:
prt("SKIPPED (no operation)");
break;
prt("BOGUS LOG ENTRY (operation code = %d)!",
lp->operation);
}
- if (closeopen)
- prt("\n\t\tCLOSE/OPEN");
prt("\n");
i++;
if (i == LOGSIZE)
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);
testcalls++;
- if (closeprob)
- closeopen = (rv >> 3) < (1 << 28) / closeprob;
-
if (debugstart > 0 && testcalls >= debugstart)
debug = 1;
}
if (sizechecks && testcalls > simulatedopcount)
check_size();
- if (closeopen)
+ if (closeprob && (rv >> 3) < (1 << 28) / closeprob)
docloseopen();
}
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;
}
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}
echo PASS
}
+mount | grep $MOUNT || $START
+
echo '== touch .../f ; rm .../f ======================== test 0'
touch $MOUNT/f
$CHECKSTAT -t file $MOUNT/f || error
$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
$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
$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
$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
$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"
$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
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"
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