-2002-01-02 Andreas Dilger <adilger@clusterfs.com>
+TBA
+ * bug fixes
+ - LRU counters were broken, causing constant lock purge (433, 432)
+ - 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)
+
+2002-12-02 Andreas Dilger <adilger@clusterfs.com>
* version v0_5_18
* bug fixes
- fix many simultaneous client startup (392)
- fix echo client over LOV (409)
- fix dbench 2, extN refcount problem (170, 258, 356, 418)
- fix double-O_EXCL intent crash (424)
- - fix LOV-with-dead-OST bugs (307, 325, 326, 400, 403, 410)
- * Features
+ - avoid sending multiple lock CANCELs (352)
+ * Features
- MDS can do multi-client recovery (modulo bugs in new code)
- * Documentation
+ * Documentation
- many updates, edits, cleanups
2002-11-18 Phil Schwan <phil@clusterfs.com>
#define LDLM_FL_CBPENDING (1 << 4) // this lock is being destroyed
#define LDLM_FL_AST_SENT (1 << 5) // blocking or cancel packet was sent
-#define LDLM_FL_DESTROYED (1 << 6) // this lock is destroyed
-#define LDLM_FL_WAIT_NOREPROC (1 << 7)// not a real lock flag,not saved in lock
-#define LDLM_FL_CANCEL (1 << 8) // cancellation callback already run
+#define LDLM_FL_WAIT_NOREPROC (1 << 6)// not a real lock flag,not saved in lock
+#define LDLM_FL_CANCEL (1 << 7) // cancellation callback already run
/* Lock is being replayed. This could probably be implied by the fact that one
* of BLOCK_{GRANTED,CONV,WAIT} is set, but that is pretty dangerous. */
-#define LDLM_FL_REPLAY (1 << 9)
+#define LDLM_FL_REPLAY (1 << 8)
-#define LDLM_FL_INTENT_ONLY (1 << 10) /* don't grant lock, just do intent */
-#define LDLM_FL_LOCAL_ONLY (1 << 11) /* see ldlm_cli_cancel_unused */
-#define LDLM_FL_NO_CALLBACK (1 << 12) /* see ldlm_cli_cancel_unused */
-#define LDLM_FL_HAS_INTENT (1 << 13) /* lock request has intent */
-#define LDLM_FL_CANCELING (1 << 14) /* lock cancel has already been sent */
+#define LDLM_FL_INTENT_ONLY (1 << 9) /* don't grant lock, just do intent */
+#define LDLM_FL_LOCAL_ONLY (1 << 10) /* see ldlm_cli_cancel_unused */
+#define LDLM_FL_NO_CALLBACK (1 << 11) /* see ldlm_cli_cancel_unused */
+#define LDLM_FL_HAS_INTENT (1 << 12) /* lock request has intent */
+#define LDLM_FL_CANCELING (1 << 13) /* lock cancel has already been sent */
/* The blocking callback is overloaded to perform two functions. These flags
* indicate which operation should be performed. */
struct ldlm_lock {
__u64 l_random;
- int l_refc;
+ atomic_t l_refc;
struct ldlm_resource *l_resource;
struct ldlm_lock *l_parent;
struct list_head l_children;
__u32 l_readers;
__u32 l_writers;
+ __u8 l_destroyed;
/* If the lock is granted, a process sleeps on this waitq to learn when
* it's no longer in use. If the lock is not granted, a process sleeps
int flags);
void ldlm_cancel_callback(struct ldlm_lock *);
int ldlm_lock_set_data(struct lustre_handle *, void *data, int datalen);
+void ldlm_lock_remove_from_lru(struct ldlm_lock *);
static inline struct ldlm_lock *ldlm_handle2lock(struct lustre_handle *h)
{
struct ldlm_resource *parent,
__u64 *name, __u32 type, int create);
struct ldlm_resource *ldlm_resource_getref(struct ldlm_resource *res);
-int ldlm_resource_put(struct ldlm_resource *res);
+int ldlm_resource_putref(struct ldlm_resource *res);
void ldlm_resource_add_lock(struct ldlm_resource *res, struct list_head *head,
struct ldlm_lock *lock);
void ldlm_resource_unlink_lock(struct ldlm_lock *lock);
# include <string.h>
#else
# include <asm/semaphore.h>
-#include <linux/kp30.h> /* XXX just for LASSERT! */
#endif
+#include <linux/kp30.h> /* XXX just for LASSERT! */
#include <linux/portals_lib.h>
#include <linux/lustre_idl.h>
-#if BITS_PER_LONG > 32
-#define LPU64 "%lu"
-#define LPD64 "%ld"
-#define LPX64 "%#lx"
-#else
-#define LPU64 "%Lu"
-#define LPD64 "%Ld"
-#define LPX64 "%#Lx"
-#endif
-
#ifdef __KERNEL__
/* l_net.c */
struct ptlrpc_request;
};
struct obd_ops {
- int (*o_iocontrol)(long cmd, struct lustre_handle *, int len,
+ int (*o_iocontrol)(unsigned int cmd, struct lustre_handle *, int len,
void *karg, void *uarg);
int (*o_get_info)(struct lustre_handle *, obd_count keylen, void *key,
obd_count *vallen, void **val);
RETURN(rc);
}
-static inline int obd_iocontrol(int cmd, struct lustre_handle *conn,
+static inline int obd_iocontrol(unsigned int cmd, struct lustre_handle *conn,
int len, void *karg, void *uarg)
{
struct obd_export *exp;
int snap_deleteobj(obd_id id, obd_gr group, void *data);
int snap_restoreobj(obd_id id, obd_gr group, void *data);
int snap_printobj(obd_id id, obd_gr group, void *data);
-int snap_iocontrol(int cmd, struct lustre_handle *conn, int len, void *karg, void *uarg);
+int snap_iocontrol(unsigned int cmd, struct lustre_handle *conn, int len, void *karg, void *uarg);
/* In the future, this function may have to deal with offsets into the obdmd.
* Currently, we assume we have the whole obdmd struct.
}
extern kmem_cache_t *ldlm_lock_slab;
+struct lustre_lock ldlm_handle_lock;
static int ldlm_plain_compat(struct ldlm_lock *a, struct ldlm_lock *b);
struct ldlm_lock *ldlm_lock_get(struct ldlm_lock *lock)
{
l_lock(&lock->l_resource->lr_namespace->ns_lock);
- lock->l_refc++;
+ atomic_inc(&lock->l_refc);
ldlm_resource_getref(lock->l_resource);
l_unlock(&lock->l_resource->lr_namespace->ns_lock);
return lock;
ENTRY;
l_lock(&ns->ns_lock);
- lock->l_refc--;
- //LDLM_DEBUG(lock, "after refc--");
- if (lock->l_refc < 0)
- LBUG();
+ atomic_dec(&lock->l_refc);
+ LASSERT(atomic_read(&lock->l_refc) >= 0);
- if (ldlm_resource_put(lock->l_resource)) {
- LASSERT(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 (lock->l_refc == 0 && (lock->l_flags & LDLM_FL_DESTROYED)) {
+ if (atomic_read(&lock->l_refc) == 0) {
+ LASSERT(lock->l_destroyed);
l_unlock(&ns->ns_lock);
LDLM_DEBUG(lock, "final lock_put on destroyed lock, freeing");
- //spin_lock(&ldlm_handle_lock);
spin_lock(&ns->ns_counter_lock);
ns->ns_locks--;
spin_unlock(&ns->ns_counter_lock);
ptlrpc_put_connection(lock->l_export->exp_connection);
memset(lock, 0x5a, sizeof(*lock));
kmem_cache_free(ldlm_lock_slab, lock);
- //spin_unlock(&ldlm_handle_lock);
CDEBUG(D_MALLOC, "kfreed 'lock': %d at %p (tot 0).\n",
sizeof(*lock), lock);
} else
EXIT;
}
+void ldlm_lock_remove_from_lru(struct ldlm_lock *lock)
+{
+ ENTRY;
+ l_lock(&lock->l_resource->lr_namespace->ns_lock);
+ if (!list_empty(&lock->l_lru)) {
+ list_del_init(&lock->l_lru);
+ lock->l_resource->lr_namespace->ns_nr_unused--;
+ LASSERT(lock->l_resource->lr_namespace->ns_nr_unused >= 0);
+ }
+ l_unlock(&lock->l_resource->lr_namespace->ns_lock);
+ EXIT;
+}
+
void ldlm_lock_destroy(struct ldlm_lock *lock)
{
ENTRY;
LBUG();
}
- if (lock->l_flags & LDLM_FL_DESTROYED) {
+ if (lock->l_destroyed) {
LASSERT(list_empty(&lock->l_lru));
l_unlock(&lock->l_resource->lr_namespace->ns_lock);
EXIT;
return;
}
+ lock->l_destroyed = 1;
- list_del_init(&lock->l_lru);
list_del(&lock->l_export_chain);
lock->l_export = NULL;
- lock->l_flags |= LDLM_FL_DESTROYED;
+ ldlm_lock_remove_from_lru(lock);
/* Wake anyone waiting for this lock */
/* FIXME: I should probably add yet another flag, instead of using
lock->l_resource = resource;
/* this refcount matches the one of the resource passed
in which is not being put away */
- lock->l_refc = 1;
+ atomic_set(&lock->l_refc, 1);
INIT_LIST_HEAD(&lock->l_children);
INIT_LIST_HEAD(&lock->l_res_link);
INIT_LIST_HEAD(&lock->l_lru);
{
struct ldlm_namespace *ns = lock->l_resource->lr_namespace;
struct ldlm_resource *oldres = lock->l_resource;
- int i;
+ int i, refc;
ENTRY;
l_lock(&ns->ns_lock);
}
/* move references over */
- for (i = 0; i < lock->l_refc; i++) {
+ refc = atomic_read(&lock->l_refc);
+ for (i = 0; i < refc; i++) {
int rc;
ldlm_resource_getref(lock->l_resource);
- rc = ldlm_resource_put(oldres);
- if (rc == 1 && i != lock->l_refc - 1)
+ rc = ldlm_resource_putref(oldres);
+ if (rc == 1 && i != refc - 1)
LBUG();
}
/* compensate for the initial get above.. */
- ldlm_resource_put(lock->l_resource);
+ ldlm_resource_putref(lock->l_resource);
l_unlock(&ns->ns_lock);
RETURN(0);
* Return NULL if flag already set
*/
-struct ldlm_lock *__ldlm_handle2lock(struct lustre_handle *handle,
- int strict, int flags)
+struct ldlm_lock *__ldlm_handle2lock(struct lustre_handle *handle, int strict,
+ int flags)
{
struct ldlm_lock *lock = NULL, *retval = NULL;
ENTRY;
if (!handle->addr)
RETURN(NULL);
- //spin_lock(&ldlm_handle_lock);
lock = (struct ldlm_lock *)(unsigned long)(handle->addr);
if (!kmem_cache_validate(ldlm_lock_slab, (void *)lock)) {
//CERROR("bogus lock %p\n", lock);
}
if (lock->l_random != handle->cookie) {
- //CERROR("bogus cookie: lock %p has "LPX64" vs. handle "LPX64"\n",
- // lock, lock->l_random, handle->cookie);
+ //CERROR("bogus cookie: lock %p has "LPX64" vs. handle "LPX64
+ // "\n", lock, lock->l_random, handle->cookie);
GOTO(out2, NULL);
}
if (!lock->l_resource) {
}
l_lock(&lock->l_resource->lr_namespace->ns_lock);
- if (strict && lock->l_flags & LDLM_FL_DESTROYED) {
+ if (strict && lock->l_destroyed) {
CERROR("lock already destroyed: lock %p\n", lock);
//LDLM_DEBUG(lock, "ldlm_handle2lock(%p)", lock);
GOTO(out, NULL);
out:
l_unlock(&lock->l_resource->lr_namespace->ns_lock);
out2:
- //spin_unlock(&ldlm_handle_lock);
return retval;
}
void ldlm_lock_addref_internal(struct ldlm_lock *lock, __u32 mode)
{
l_lock(&lock->l_resource->lr_namespace->ns_lock);
-
- if (!list_empty(&lock->l_lru)) {
- list_del_init(&lock->l_lru);
- lock->l_resource->lr_namespace->ns_nr_unused--;
- LASSERT(lock->l_resource->lr_namespace->ns_nr_unused >= 0);
- }
-
+ ldlm_lock_remove_from_lru(lock);
if (mode == LCK_NL || mode == LCK_CR || mode == LCK_PR)
lock->l_readers++;
else
if (lock == old_lock)
continue;
- if (lock->l_flags & (LDLM_FL_CBPENDING | LDLM_FL_DESTROYED))
+ if (lock->l_flags & LDLM_FL_CBPENDING)
continue;
if (lock->l_req_mode != mode)
lock->l_extent.end < extent->end))
continue;
+ if (lock->l_destroyed)
+ continue;
+
ldlm_lock_addref_internal(lock, mode);
return lock;
}
EXIT;
out:
- ldlm_resource_put(res);
+ ldlm_resource_putref(res);
l_unlock(&ns->ns_lock);
if (lock) {
lock = ldlm_lock_new(parent_lock, res);
if (lock == NULL) {
- ldlm_resource_put(res);
+ ldlm_resource_putref(res);
RETURN(NULL);
}
LDLM_DEBUG(lock, "export %p", exp);
ldlm_lock_cancel(lock);
ldlm_reprocess_all(res);
- ldlm_resource_put(res);
+ ldlm_resource_putref(res);
}
}
extern kmem_cache_t *ldlm_resource_slab;
extern kmem_cache_t *ldlm_lock_slab;
+extern struct lustre_lock ldlm_handle_lock;
extern struct list_head ldlm_namespace_list;
extern int (*mds_reint_p)(int offset, struct ptlrpc_request *req);
extern int (*mds_getattr_name_p)(int offset, struct ptlrpc_request *req);
return -ENOMEM;
}
+ l_lock_init(&ldlm_handle_lock);
+
return 0;
}
/* Go to sleep until the lock is granted or cancelled. */
rc = l_wait_event(lock->l_waitq,
((lock->l_req_mode == lock->l_granted_mode) ||
- (lock->l_flags & LDLM_FL_DESTROYED)), &lwi);
+ lock->l_destroyed), &lwi);
- if (lock->l_flags & LDLM_FL_DESTROYED) {
+ if (lock->l_destroyed) {
LDLM_DEBUG(lock, "client-side enqueue waking up: destroyed");
RETURN(-EIO);
}
w->w_lock = LDLM_LOCK_GET(lock);
list_add(&w->w_list, &list);
- list_del_init(&lock->l_lru);
+ ldlm_lock_remove_from_lru(lock);
if (--count == 0)
break;
OBD_FREE(w, sizeof(*w));
}
- ldlm_resource_put(res);
+ ldlm_resource_putref(res);
RETURN(0);
}
int flags)
{
int i;
+ ENTRY;
if (res_id)
RETURN(ldlm_cli_cancel_unused_resource(ns, res_id, flags));
if (rc)
CERROR("cancel_unused_res ("LPU64"): %d\n",
res->lr_name[0], rc);
- ldlm_resource_put(res);
+ ldlm_resource_putref(res);
}
}
l_unlock(&ns->ns_lock);
- return ELDLM_OK;
+ RETURN(ELDLM_OK);
}
/* Lock iterators. */
ldlm_resource_getref(res);
rc = ldlm_resource_foreach(res, ldlm_iter_helper,
&helper);
- ldlm_resource_put(res);
+ ldlm_resource_putref(res);
if (rc == LDLM_ITER_STOP)
GOTO(out, rc);
}
* local_only (which is only used by recovery). In that
* case, we probably still have outstanding lock refs
* which reference these resources. -phil */
- if (!ldlm_resource_put(res) && !local_only) {
+ if (!ldlm_resource_putref(res) && !local_only) {
CERROR("Resource refcount nonzero (%d) after "
"lock cleanup; forcing cleanup.\n",
atomic_read(&res->lr_refcount));
ldlm_resource_dump(res);
atomic_set(&res->lr_refcount, 1);
- ldlm_resource_put(res);
+ ldlm_resource_putref(res);
}
}
}
ns->ns_resources++;
spin_unlock(&ns->ns_counter_lock);
+ l_lock(&ns->ns_lock);
memcpy(res->lr_name, name, sizeof(res->lr_name));
res->lr_namespace = ns;
ns->ns_refcount++;
bucket = ns->ns_hash + ldlm_hash_fn(parent, name);
list_add(&res->lr_hash, bucket);
- if (parent == NULL)
+ if (parent == NULL) {
list_add(&res->lr_childof, &ns->ns_root_list);
- else {
+ } else {
res->lr_parent = parent;
list_add(&res->lr_childof, &parent->lr_children);
}
+ l_unlock(&ns->ns_lock);
RETURN(res);
}
struct ldlm_resource *ldlm_resource_getref(struct ldlm_resource *res)
{
atomic_inc(&res->lr_refcount);
+ CDEBUG(D_INFO, "getref res: %p count: %d\n", res,
+ atomic_read(&res->lr_refcount));
return res;
}
/* Returns 1 if the resource was freed, 0 if it remains. */
-int ldlm_resource_put(struct ldlm_resource *res)
+int ldlm_resource_putref(struct ldlm_resource *res)
{
int rc = 0;
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);
if (atomic_read(&res->lr_refcount) != 0) {
/* We lost the race. */
l_unlock(&ns->ns_lock);
- goto out;
+ RETURN(rc);
}
- if (!list_empty(&res->lr_granted))
+ if (!list_empty(&res->lr_granted)) {
+ ldlm_resource_dump(res);
LBUG();
+ }
- if (!list_empty(&res->lr_converting))
+ if (!list_empty(&res->lr_converting)) {
+ ldlm_resource_dump(res);
LBUG();
+ }
- if (!list_empty(&res->lr_waiting))
+ if (!list_empty(&res->lr_waiting)) {
+ ldlm_resource_dump(res);
LBUG();
+ }
- if (!list_empty(&res->lr_children))
+ if (!list_empty(&res->lr_children)) {
+ ldlm_resource_dump(res);
LBUG();
+ }
ns->ns_refcount--;
list_del(&res->lr_hash);
rc = 1;
} else {
ENTRY;
+ CDEBUG(D_INFO, "putref res: %p count: %d\n", res,
+ atomic_read(&res->lr_refcount));
out:
- if (atomic_read(&res->lr_refcount) < 0)
- LBUG();
+ LASSERT(atomic_read(&res->lr_refcount) >= 0);
}
RETURN(rc);
ldlm_resource_dump(res);
ldlm_lock_dump(lock);
- if (!list_empty(&lock->l_res_link))
- LBUG();
+ LASSERT(list_empty(&lock->l_res_link));
list_add(&lock->l_res_link, head);
l_unlock(&res->lr_namespace->ns_lock);
}
offset = 0;
} else {
- struct ll_inode_info *lli = ll_i2info(parent);
obd_flag valid;
int mode;
RETURN(PTR_ERR(inode));
if (it && it->it_disposition) {
- struct ll_inode_info *lli = ll_i2info(inode);
d_instantiate(dentry, inode);
} else {
/* no directory data updates when intents rule */
RETURN(rc);
}
-static int lov_iocontrol(long cmd, struct lustre_handle *conn, int len,
+static int lov_iocontrol(unsigned int cmd, struct lustre_handle *conn, int len,
void *karg, void *uarg)
{
struct obd_device *obddev = class_conn2obd(conn);
struct mds_body *body;
int rc, size = sizeof(*body);
struct ptlrpc_request *req;
+ ENTRY;
req = ptlrpc_prep_req(class_conn2cliimp(conn), MDS_CLOSE, 1, &size,
NULL);
RETURN(0);
}
-extern int mds_iocontrol(long cmd, struct lustre_handle *conn,
+extern int mds_iocontrol(unsigned int cmd, struct lustre_handle *conn,
int len, void *karg, void *uarg);
/* use obd ops to offer management infrastructure */
char *mft_name;
};
-#define MDS_MAX_CLIENTS 1024
+/* This limit is arbitrary, but for now we fit it in 1 page (32k clients) */
+#define MDS_MAX_CLIENTS (PAGE_SIZE * 8)
#define MDS_MAX_CLIENT_WORDS (MDS_MAX_CLIENTS / sizeof(unsigned long))
static unsigned long last_rcvd_slots[MDS_MAX_CLIENT_WORDS];
RETURN(rc);
}
-int mds_iocontrol(long cmd, struct lustre_handle *conn,
+int mds_iocontrol(unsigned int cmd, struct lustre_handle *conn,
int len, void *karg, void *uarg)
{
struct obd_device *obd = class_conn2obd(conn);
include $(top_srcdir)/Rules
lustre_build_version:
perl $(top_srcdir)/scripts/version_tag.pl $(top_srcdir) > tmpver
- diff -u tmpver $(top_builddir)/include/linux/lustre_build_version.h &&\
+ diff -u $(top_builddir)/include/linux/lustre_build_version.h tmpver \
+ 2> /dev/null &&\
$(RM) tmpver || \
mv tmpver $(top_builddir)/include/linux/lustre_build_version.h
struct obd_ioctl_data *data;
struct obd_device *obd = filp->private_data;
struct lustre_handle conn;
- int err = 0, len = 0;
+ int err = 0, len = 0, serialised = 0;
ENTRY;
- down(&obd_conf_sem);
+ switch (cmd) {
+ case OBD_IOC_BRW_WRITE:
+ case OBD_IOC_BRW_READ:
+ case OBD_IOC_GETATTR:
+ break;
+ default:
+ down(&obd_conf_sem);
+ serialised = 1;
+ break;
+ }
if (!obd && cmd != OBD_IOC_DEVICE && cmd != TCGETS &&
cmd != OBD_IOC_LIST && cmd != OBD_GET_VERSION &&
out:
if (buf)
OBD_FREE(buf, len);
- up(&obd_conf_sem);
+ if (serialised)
+ up(&obd_conf_sem);
RETURN(err);
} /* obd_class_ioctl */
#include <linux/lustre_debug.h>
#include <linux/lprocfs_status.h>
-static int echo_iocontrol(long cmd, struct lustre_handle *obdconn, int len,
+static int echo_iocontrol(unsigned int cmd, struct lustre_handle *obdconn, int len,
void *karg, void *uarg)
{
struct obd_device *obd = class_conn2obd(obdconn);
GOTO(out, rc);
}
default:
- return -ENOTTY;
+ CERROR ("echo_ioctl(): unrecognised ioctl %#lx\n", cmd);
+ GOTO (out, rc = -ENOTTY);
}
out:
return rc;
}
-static int osc_iocontrol(long cmd, struct lustre_handle *conn, int len,
+static int osc_iocontrol(unsigned int cmd, struct lustre_handle *conn, int len,
void *karg, void *uarg)
{
struct obd_device *obddev = class_conn2obd(conn);
GOTO(out, err);
}
default:
+ CERROR ("osc_ioctl(): unrecognised ioctl %#lx\n", cmd);
GOTO(out, err = -ENOTTY);
}
out:
DEBUG_REQ(D_ERROR, req, "RESTART:");
GOTO(out, rc = 1);
}
+ EXIT;
out:
DEBUG_REQ(D_NET, req, "rc = %d for", rc);
return rc;
struct ptlrpc_request *req;
ENTRY;
+#ifndef __arch_um__
+ LASSERT(spin_is_locked(&imp->imp_lock));
+#endif
+
CDEBUG(D_HA, "committing for xid "LPU64", last_committed "LPU64"\n",
imp->imp_peer_last_xid, imp->imp_peer_committed_transno);
}
/* not yet committed */
- if (req->rq_transno > imp->imp_peer_committed_transno)
+ if (req->rq_transno > imp->imp_peer_committed_transno) {
+ DEBUG_REQ(D_HA, req, "stopping search");
break;
+ }
- DEBUG_REQ(D_HA, req, "committing (last_committed %Lu)",
+ DEBUG_REQ(D_HA, req, "committing (last_committed "LPU64")",
imp->imp_peer_committed_transno);
__ptlrpc_req_finished(req, 1);
}
RETURN(0);
}
-int connmgr_iocontrol(long cmd, struct lustre_handle *hdl, int len, void *karg,
+int connmgr_iocontrol(unsigned int cmd, struct lustre_handle *hdl, int len, void *karg,
void *uarg)
{
struct ptlrpc_connection *conn = NULL;
localtime($mtime);
$year += 1900;
$mon++;
- my $show_last = $year . $mon . $mday . $hour . $min . $sec;
+ my $show_last = sprintf("%04d%02d%02d%02d%02d%02d", $year, $mon, $mday,
+ $hour, $min, $sec);
print "#define BUILD_VERSION \"";
if ($pristine) {
lovstripe
*.xml
stat
+setuid
[ "$RSIZE" ] || RSIZE=64
[ "$UID" ] || UID=1000
[ "$MNT" ] || MNT=/mnt/lustre
+[ "$TMP" ] || TMP=/tmp
[ "$COUNT" ] || COUNT=1000
[ "$DEBUG_OFF" ] || DEBUG_OFF="eval echo 0 > /proc/sys/portals/debug"
fi
if [ "$FSX" != "no" ]; then
$DEBUG_OFF
- ./fsx -c 50 -p 1000 -l 1024000 -N $(($COUNT * 100)) $MNT/fsxfile
+ ./fsx -c 50 -p 1000 -P $TMP -l 1024000 -N $(($COUNT * 100)) $MNT/fsxfile
sh llmountcleanup.sh
#sh llrmount.sh
fi
# include <limits.h>
# include <time.h>
# include <strings.h>
+# include <sys/time.h>
#endif
#include <fcntl.h>
#include <sys/mman.h>
struct log_entry {
int operation;
+ struct timeval tv;
int args[3];
};
char *good_buf; /* a pointer to the correct data */
char *temp_buf; /* a pointer to the current data */
char *fname; /* name of our test file */
+char logfile[1024]; /* name of our log file */
+char goodfile[1024]; /* name of our test file */
int fd; /* fd for our test file */
off_t file_size = 0;
void
-log4(int operation, int arg0, int arg1, int arg2)
+log4(int operation, int arg0, int arg1, int arg2, struct timeval *tv)
{
struct log_entry *le;
le = &oplog[logptr];
+ le->tv = *tv;
le->operation = operation;
if (closeopen)
le->operation = ~ le->operation;
int opnum;
opnum = i+1 + (logcount/LOGSIZE)*LOGSIZE;
- prt("%d(%d mod 256): ", opnum, opnum%256);
lp = &oplog[i];
+ prt("%d(%d mod 256): %lu.%lu ", opnum, opnum%256,
+ lp->tv.tv_sec, lp->tv.tv_usec);
if ((closeopen = lp->operation < 0))
lp->operation = ~ lp->operation;
if (good_buf) {
save_buffer(good_buf, file_size, fsxgoodfd);
prt("Correct content saved for comparison\n");
- prt("(maybe hexdump \"%s\" vs \"%s.fsxgood\")\n",
- fname, fname);
+ prt("(maybe hexdump \"%s\" vs \"%s\")\n",
+ fname, goodfile);
}
close(fsxgoodfd);
}
void
doread(unsigned offset, unsigned size)
{
+ struct timeval t;
off_t ret;
unsigned iret;
offset -= offset % readbdy;
+ gettimeofday(&t, NULL);
if (size == 0) {
if (!quiet && testcalls > simulatedopcount)
prt("skipping zero size read\n");
- log4(OP_SKIPPED, OP_READ, offset, size);
+ log4(OP_SKIPPED, OP_READ, offset, size, &t);
return;
}
if (size + offset > file_size) {
if (!quiet && testcalls > simulatedopcount)
prt("skipping seek/read past end of file\n");
- log4(OP_SKIPPED, OP_READ, offset, size);
+ log4(OP_SKIPPED, OP_READ, offset, size, &t);
return;
}
- log4(OP_READ, offset, size, 0);
+ log4(OP_READ, offset, size, 0, &t);
if (testcalls <= simulatedopcount)
return;
(monitorstart == -1 ||
(offset + size > monitorstart &&
(monitorend == -1 || offset <= monitorend))))))
- prt("%lu read\t0x%x thru\t0x%x\t(0x%x bytes)\n", testcalls,
- offset, offset + size - 1, size);
+ prt("%lu %lu.%lu read\t0x%x thru\t0x%x\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);
if (ret == (off_t)-1) {
prterr("doread: lseek");
void
domapread(unsigned offset, unsigned size)
{
+ struct timeval t;
unsigned pg_offset;
unsigned map_size;
char *p;
offset -= offset % readbdy;
+ gettimeofday(&t, NULL);
if (size == 0) {
if (!quiet && testcalls > simulatedopcount)
prt("skipping zero size read\n");
- log4(OP_SKIPPED, OP_MAPREAD, offset, size);
+ log4(OP_SKIPPED, OP_MAPREAD, offset, size, &t);
return;
}
if (size + offset > file_size) {
if (!quiet && testcalls > simulatedopcount)
prt("skipping seek/read past end of file\n");
- log4(OP_SKIPPED, OP_MAPREAD, offset, size);
+ log4(OP_SKIPPED, OP_MAPREAD, offset, size, &t);
return;
}
- log4(OP_MAPREAD, offset, size, 0);
+ log4(OP_MAPREAD, offset, size, 0, &t);
if (testcalls <= simulatedopcount)
return;
(monitorstart == -1 ||
(offset + size > monitorstart &&
(monitorend == -1 || offset <= monitorend))))))
- prt("%lu mapread\t0x%x thru\t0x%x\t(0x%x bytes)\n", testcalls,
- offset, offset + size - 1, size);
+ prt("%lu %lu.%lu mapread\t0x%x thru\t0x%x\t(0x%x bytes)\n",
+ testcalls, t.tv_sec, t.tv_usec, offset, offset + size - 1,
+ size);
pg_offset = offset & page_mask;
map_size = pg_offset + size;
- if ((p = (char *)mmap(0, map_size, PROT_READ, MAP_FILE |
-MAP_SHARED, fd,
+ if ((p = (char *)mmap(0, map_size, PROT_READ, MAP_FILE | MAP_SHARED, fd,
(off_t)(offset - pg_offset))) == (char *)-1) {
prterr("domapread: mmap");
report_failure(190);
void
dowrite(unsigned offset, unsigned size)
{
+ struct timeval t;
off_t ret;
unsigned iret;
offset -= offset % writebdy;
+ gettimeofday(&t, NULL);
if (size == 0) {
if (!quiet && testcalls > simulatedopcount)
prt("skipping zero size write\n");
- log4(OP_SKIPPED, OP_WRITE, offset, size);
+ log4(OP_SKIPPED, OP_WRITE, offset, size, &t);
return;
}
- log4(OP_WRITE, offset, size, file_size);
+ log4(OP_WRITE, offset, size, file_size, &t);
gendata(original_buf, good_buf, offset, size);
if (file_size < offset + size) {
(monitorstart == -1 ||
(offset + size > monitorstart &&
(monitorend == -1 || offset <= monitorend))))))
- prt("%lu write\t0x%x thru\t0x%x\t(0x%x bytes)\n", testcalls,
- offset, offset + size - 1, size);
+ prt("%lu %lu.%lu write\t0x%x thru\t0x%x\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);
if (ret == (off_t)-1) {
prterr("dowrite: lseek");
void
domapwrite(unsigned offset, unsigned size)
{
+ struct timeval t;
unsigned pg_offset;
unsigned map_size;
off_t cur_filesize;
char *p;
offset -= offset % writebdy;
+ gettimeofday(&t, NULL);
if (size == 0) {
if (!quiet && testcalls > simulatedopcount)
prt("skipping zero size write\n");
- log4(OP_SKIPPED, OP_MAPWRITE, offset, size);
+ log4(OP_SKIPPED, OP_MAPWRITE, offset, size, &t);
return;
}
cur_filesize = file_size;
- log4(OP_MAPWRITE, offset, size, 0);
+ log4(OP_MAPWRITE, offset, size, 0, &t);
gendata(original_buf, good_buf, offset, size);
if (file_size < offset + size) {
(monitorstart == -1 ||
(offset + size > monitorstart &&
(monitorend == -1 || offset <= monitorend))))))
- prt("%lu mapwrite\t0x%x thru\t0x%x\t(0x%x bytes)\n", testcalls,
- offset, offset + size - 1, size);
+ prt("%lu %lu.%lu mapwrite\t0x%x thru\t0x%x\t(0x%x bytes)\n",
+ testcalls, t.tv_sec, t.tv_usec, offset, offset + size - 1,
+ size);
if (file_size > cur_filesize) {
if (ftruncate(fd, file_size) == -1) {
void
dotruncate(unsigned size)
{
+ struct timeval t;
int oldsize = file_size;
size -= size % truncbdy;
+ gettimeofday(&t, NULL);
if (size > biggest) {
biggest = size;
if (!quiet && testcalls > simulatedopcount)
prt("truncating to largest ever: 0x%x\n", size);
}
- log4(OP_TRUNCATE, size, (unsigned)file_size, 0);
+ log4(OP_TRUNCATE, size, (unsigned)file_size, 0, &t);
if (size > file_size)
memset(good_buf + file_size, '\0', size - file_size);
if ((progressinterval && testcalls % progressinterval == 0) ||
(debug && (monitorstart == -1 || monitorend == -1 ||
size <= monitorend)))
- prt("%lu trunc\tfrom 0x%x to 0x%x\n", testcalls, oldsize,
-size);
+ prt("%lu %lu.%lu trunc\tfrom 0x%x to 0x%x\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");
void
docloseopen(void)
{
+ struct timeval t;
+
if (testcalls <= simulatedopcount)
return;
+ log4(OP_CLOSEOPEN, file_size, (unsigned)file_size, 0, &t);
+
+ gettimeofday(&t, NULL);
if (debug)
- prt("%lu close/open\n", testcalls);
+ prt("%lu %lu.%lu close/open\n", testcalls, t.tv_sec, t.tv_usec);
if (close(fd)) {
prterr("docloseopen: close");
report_failure(180);
}
+static const char *basename(const char *path)
+{
+ char *c = strrchr(path, '/');
+
+ return c ? c++ : path;
+}
+
int
main(int argc, char **argv)
{
int i, style, ch;
char *endp;
- char goodfile[1024];
- char logfile[1024];
+ int dirpath = 0;
goodfile[0] = 0;
logfile[0] = 0;
strcat(goodfile, "/");
strncpy(logfile, optarg, sizeof(logfile));
strcat(logfile, "/");
+ dirpath = 1;
break;
case 'R':
mapped_reads = 0;
prterr(fname);
exit(91);
}
- strncat(goodfile, fname, 256);
+ strncat(goodfile, dirpath ? basename(fname) : fname, 256);
strcat (goodfile, ".fsxgood");
fsxgoodfd = open(goodfile, O_RDWR|O_CREAT|O_TRUNC, 0666);
if (fsxgoodfd < 0) {
prterr(goodfile);
exit(92);
}
- strncat(logfile, fname, 256);
+ strncat(logfile, dirpath ? basename(fname) : fname, 256);
strcat (logfile, ".fsxlog");
fsxlogf = fopen(logfile, "w");
if (fsxlogf == NULL) {
#!/usr/bin/perl -w
+use IO::Handle;
+
+STDOUT->autoflush(1);
+STDERR->autoflush(1);
+
my ($line, $memory);
my $debug_line = 0;
while ($line = <>) {
$debug_line++;
my ($file, $func, $lno, $name, $size, $addr, $type);
- if ($line =~ m/^.*\((.*):(\d+):(.*)\(\) \d+\+\d+\): [vk](.*) '(.*)': (\d+) at (.*) \(tot .*$/) {
+ if ($line =~ m/^.*\((.*):(\d+):(.*)\(\) (\d+ \| )?\d+\+\d+\): [vk](.*) '(.*)': (\d+) at (.*) \(tot .*$/) {
$file = $1;
$lno = $2;
$func = $3;
- $type = $4;
- $name = $5;
- $size = $6;
- $addr = $7;
+ $type = $5;
+ $name = $6;
+ $size = $7;
+ $addr = $8;
printf("%8s %6d bytes at %s called %s (%s:%s:%d)\n", $type, $size,
$addr, $name, $file, $func, $lno);
} else {
$memory->{$addr}->{debug_line} = $debug_line;
} else {
if (!defined($memory->{$addr})) {
- print "*** Free without malloc ($size bytes at $addr, $file:$func:$lno)\n";
+ print STDERR "*** Free without malloc ($size bytes at $addr, $file:$func:$lno)\n";
next;
}
my ($oldname, $oldsize, $oldfile, $oldfunc, $oldlno) = $memory->{$addr};
if ($memory->{$addr}->{size} != $size) {
- print "*** Free different size ($memory->{$addr}->{size} alloced, $size freed).\n";
- print " malloc at $memory->{$addr}->{file}:$memory->{$addr}->{func}:$memory->{$addr}->{lno}, free at $file:$func:$lno\n";
+ print STDERR "*** Free different size ($memory->{$addr}->{size} alloced, $size freed).\n";
+ print STDERR " malloc at $memory->{$addr}->{file}:$memory->{$addr}->{func}:$memory->{$addr}->{lno}, free at $file:$func:$lno\n";
next;
}
}
}
+# Sort leak output by allocation time
+my @sorted = sort {
+ return $memory->{$a}->{debug_line} <=> $memory->{$b}->{debug_line};
+} keys(%{$memory});
+
my $key;
-foreach $key (keys(%{$memory})) {
+foreach $key (@sorted) {
my ($oldname, $oldsize, $oldfile, $oldfunc, $oldlno) = $memory->{$key};
- print "*** Leak: $memory->{$key}->{size} bytes allocated at $key ($memory->{$key}->{file}:$memory->{$key}->{func}:$memory->{$key}->{lno}, debug file line $memory->{$key}->{debug_line})\n";
+ print STDERR "*** Leak: $memory->{$key}->{size} bytes allocated at $key ($memory->{$key}->{file}:$memory->{$key}->{func}:$memory->{$key}->{lno}, debug file line $memory->{$key}->{debug_line})\n";
}
print "Done.\n";
# suggested boilerplate for test script
LCONF=${LCONF:-../utils/lconf}
-NAME=${NAME:-local2}
+NAME=${NAME:-local2-hack}
config=$NAME.xml
-mkconfig=./$NAME.sh
-if [ ! -f $config -o $mkconfig -nt $config ]; then
- sh $mkconfig $config || exit 1
-fi
-
-${LCONF} -v --reformat --gdb $config || exit 2
+${LCONF} --reformat --gdb $config || exit 2
../utils/lctl <<EOF
newdev
+++ /dev/null
-<?xml version='1.0' encoding='UTF-8'?>
-<!DOCTYPE lustre>
-<lustre>
- <ldlm name='ldlm' uuid='ldlm_UUID'/>
- <node name='localhost' uuid='localhost_UUID'>
- <profile>
- <ldlm_ref uuidref='ldlm_UUID'/>
- <network_ref uuidref='NET_localhost_tcp_UUID'/>
- <mds_ref uuidref='mds1_UUID'/>
- <lovconfig_ref uuidref='LVCFG_lov1_UUID'/>
- <obd_ref uuidref='OBD_localhost_UUID'/>
- <ost_ref uuidref='OST_localhost_UUID'/>
- <obd_ref uuidref='OBD_localhost_2_UUID'/>
- <ost_ref uuidref='OST_localhost_2_UUID'/>
- <mountpoint_ref uuidref='MNT_localhost_UUID'/>
- </profile>
- <network name='NET_localhost_tcp' uuid='NET_localhost_tcp_UUID' type='tcp'>
- <server>localhost</server>
- <port>988</port>
- </network>
- </node>
- <mds name='mds1' uuid='mds1_UUID'>
- <fstype>extN</fstype>
- <device size='50000'>/tmp/mds1</device>
- <autoformat>yes</autoformat>
- <network_ref uuidref='NET_localhost_tcp_UUID'/>
- <node_ref uuidref='localhost_UUID'/>
- </mds>
- <lov name='lov1' uuid='lov1_UUID'>
- <mds_ref uuidref='mds1_UUID'/>
- <devices stripecount='0' stripesize='65536' pattern='0'>
- <osc_ref uuidref='OSC_localhost_UUID'/>
- <osc_ref uuidref='OSC_localhost_2_UUID'/>
- </devices>
- </lov>
- <lovconfig name='LVCFG_lov1' uuid='LVCFG_lov1_UUID'>
- <lov_ref uuidref='lov1_UUID'/>
- </lovconfig>
- <obd uuid='OBD_localhost_UUID' name='OBD_localhost' type='obdfilter'>
- <fstype>extN</fstype>
- <device size='100000'>/tmp/ost1</device>
- <autoformat>no</autoformat>
- </obd>
- <osc name='OSC_localhost' uuid='OSC_localhost_UUID'>
- <ost_ref uuidref='OST_localhost_UUID'/>
- <obd_ref uuidref='OBD_localhost_UUID'/>
- </osc>
- <ost name='OST_localhost' uuid='OST_localhost_UUID'>
- <network_ref uuidref='NET_localhost_tcp_UUID'/>
- <obd_ref uuidref='OBD_localhost_UUID'/>
- </ost>
- <obd name='OBD_localhost_2' uuid='OBD_localhost_2_UUID' type='obdfilter'>
- <fstype>extN</fstype>
- <device size='100000'>/tmp/ost2</device>
- <autoformat>no</autoformat>
- </obd>
- <osc name='OSC_localhost_2' uuid='OSC_localhost_2_UUID'>
- <ost_ref uuidref='OST_localhost_2_UUID'/>
- <obd_ref uuidref='OBD_localhost_2_UUID'/>
- </osc>
- <ost name='OST_localhost_2' uuid='OST_localhost_2_UUID'>
- <network_ref uuidref='NET_localhost_tcp_UUID'/>
- <obd_ref uuidref='OBD_localhost_2_UUID'/>
- </ost>
- <mountpoint name='MNT_localhost' uuid='MNT_localhost_UUID'>
- <mds_ref uuidref='mds1_UUID'/>
- <osc_ref uuidref='lov1_UUID'/>
- <path>/mnt/lustre</path>
- </mountpoint>
-</lustre>
{
int rc;
- if (argc < 2) {
+ if (argc < 2) {
printf("Usage %s filename\n", argv[0]);
return 1;
}
- rc = mknod(argv[1], S_IFREG| 0444, 0);
- if (rc) {
+ rc = mknod(argv[1], S_IFREG | 0644, 0);
+ if (rc) {
printf("mknod(%s) error: %s\n", argv[1], strerror(errno));
}
return rc;
-}
+}
int main(int argc, char **argv)
{
- int fd, rc, c, cmd = 0;
+ int fd = 0;
+ int rc = 0;
+ int c = 0;
+ long cmd = 0;
unsigned long arg;
char *short_opts = "h", *name = argv[0];
static struct option long_opts[] = {
if (verbose) {
printf("lmm_magic: 0x%x\n", lmm->lmm_magic);
- printf("lmm_object_id: 0x%llx\n", lmm->lmm_object_id);
+ printf("lmm_object_id: "LPX64"\n", lmm->lmm_object_id);
printf("lmm_stripe_offset: %d\n", lmm->lmm_stripe_offset);
printf("lmm_stripe_count: %d\n", lmm->lmm_stripe_count);
printf("lmm_ost_count: %d\n", lmm->lmm_ost_count);
for (i = 0; i < count; i++, loi++)
if ((oid = loi->l_object_id))
- printf("%6d\t%5lld\n", i, oid);
+ printf("%6d\t%5lld\n", i, (long long)oid);
if (query)
return(0);
sub extractpid
{
- $_ = shift;
+ $line = shift;
# print "$_\n";
- /\(\) ([0-9]*)\+[0-9]*\):/;
- return $1;
+ if ($line =~ m/\(\) ([0-9]*)\+[0-9]*\):/) {
+ return $1;
+ }
+ if ($line =~ m/\(\) ([0-9]*) | [0-9]*\+[0-9]*\):/) {
+ return $1;
+ }
}
sub entering
rc = ioctl(fd, OBD_IOC_DISCONNECT, &data);
if (rc < 0) {
- fprintf(stderr, "error: %s: %x %s\n", cmdname(func),
- OBD_IOC_DISCONNECT, strerror(errno));
+ fprintf(stderr, "error: %s: OPD_IOC_DISCONNECT %s\n",
+ cmdname(func),strerror(errno));
} else {
if (verbose)
printf("%s: disconnected conn "LPX64"\n", cmdname(func),
rc = ioctl(fd, OBD_IOC_CONNECT, &data);
if (rc < 0)
- fprintf(stderr, "error: %s: %x %s\n", cmdname(argv[0]),
- OBD_IOC_CONNECT, strerror(rc = errno));
+ fprintf(stderr, "error: %s: OBD_IOC_CONNECT %s\n",
+ cmdname(argv[0]), strerror(rc = errno));
else {
conn_addr = data.ioc_addr;
conn_cookie = data.ioc_cookie;
IOC_PACK(argv[0], data);
rc = ioctl(fd, OBD_IOC_ATTACH, buf);
if (rc < 0)
- fprintf(stderr, "error: %s: %x %s\n", cmdname(argv[0]),
- OBD_IOC_ATTACH, strerror(rc = errno));
+ fprintf(stderr, "error: %s: OBD_IOC_ATTACH %s\n",
+ cmdname(argv[0]), strerror(rc = errno));
else if (argc == 3) {
char name[1024];
if (strlen(argv[2]) > 128) {
rc = ioctl(fd, OBD_IOC_GETATTR, &data);
SHMEM_BUMP();
if (rc < 0) {
- fprintf(stderr, "error: %s: #"LPD64" - %s\n",
- cmdname(argv[0]), i, strerror(rc = errno));
+ fprintf(stderr, "error: %s: #"LPD64" - %d:%s\n",
+ cmdname(argv[0]), i, errno, strerror(rc = errno));
break;
} else {
if (be_verbose
if (strlen(argv[1]) > sizeof(desc.ld_uuid) - 1) {
fprintf(stderr,
- "error: %s: LOV uuid '%s' longer than %d characters\n",
+ "error: %s: LOV uuid '%s' longer than %zd characters\n",
cmdname(argv[0]), argv[1], sizeof(desc.ld_uuid) - 1);
return -EINVAL;
}
if (strlen(argv[1]) > sizeof(desc.ld_uuid) - 1) {
fprintf(stderr,
- "error: %s: LOV uuid '%s' longer than %d characters\n",
+ "error: %s: LOV uuid '%s' longer than %zd characters\n",
cmdname(argv[0]), argv[1], sizeof(desc.ld_uuid) - 1);
return -EINVAL;
}