#include <linux/iobuf.h>
#endif
#include <asm/div64.h>
+#include <linux/smp_lock.h>
#else
#include <liblustre.h>
#endif
static struct ec_object *
echo_find_object_locked (struct obd_device *obd, obd_id id)
{
- struct echo_client_obd *ec = &obd->u.echo_client;
+ struct echo_client_obd *ec = &obd->u.echocli;
struct ec_object *eco = NULL;
struct list_head *el;
echo_copyin_lsm (struct obd_device *obd, struct lov_stripe_md *lsm,
void *ulsm, int ulsm_nob)
{
- struct echo_client_obd *ec = &obd->u.echo_client;
+ struct echo_client_obd *ec = &obd->u.echocli;
int nob;
if (ulsm_nob < sizeof (*lsm))
static struct ec_object *
echo_allocate_object (struct obd_device *obd)
{
- struct echo_client_obd *ec = &obd->u.echo_client;
+ struct echo_client_obd *ec = &obd->u.echocli;
struct ec_object *eco;
int rc;
echo_free_object (struct ec_object *eco)
{
struct obd_device *obd = eco->eco_device;
- struct echo_client_obd *ec = &obd->u.echo_client;
+ struct echo_client_obd *ec = &obd->u.echocli;
LASSERT (eco->eco_refcount == 0);
obd_free_memmd(ec->ec_exp, &eco->eco_lsm);
struct obdo *oa, void *ulsm, int ulsm_nob,
struct obd_trans_info *oti)
{
- struct echo_client_obd *ec = &obd->u.echo_client;
+ struct echo_client_obd *ec = &obd->u.echocli;
struct ec_object *eco2;
struct ec_object *eco;
struct lov_stripe_md *lsm;
oa->o_id = ++last_object_id;
if (on_target) {
- /* XXX get some filter group constants */
- oa->o_gr = 2;
+ oa->o_gr = FILTER_GROUP_ECHO;
oa->o_valid |= OBD_MD_FLGROUP;
- rc = obd_create(ec->ec_exp, oa, &lsm, oti);
+ rc = obd_create(ec->ec_exp, oa, NULL, 0, &lsm, oti);
if (rc != 0)
goto failed;
echo_get_object (struct ec_object **ecop, struct obd_device *obd,
struct obdo *oa)
{
- struct echo_client_obd *ec = &obd->u.echo_client;
+ struct echo_client_obd *ec = &obd->u.echocli;
struct ec_object *eco;
struct ec_object *eco2;
int rc;
- if ((oa->o_valid & OBD_MD_FLID) == 0)
+ if ((oa->o_valid & OBD_MD_FLID) == 0 ||
+ oa->o_id == 0) /* disallow use of object id 0 */
{
CERROR ("No valid oid\n");
return (-EINVAL);
echo_put_object (struct ec_object *eco)
{
struct obd_device *obd = eco->eco_device;
- struct echo_client_obd *ec = &obd->u.echo_client;
+ struct echo_client_obd *ec = &obd->u.echocli;
/* Release caller's ref on the object.
* delete => mark for deletion when last ref goes
*offp = offset * stripe_size + woffset % stripe_size;
}
+static void
+echo_client_page_debug_setup(struct lov_stripe_md *lsm,
+ struct page *page, int rw, obd_id id,
+ obd_off offset, obd_off count)
+{
+ char *addr;
+ obd_off stripe_off;
+ obd_id stripe_id;
+ int delta;
+
+ /* no partial pages on the client */
+ LASSERT(count == PAGE_SIZE);
+
+ addr = kmap(page);
+
+ for (delta = 0; delta < PAGE_SIZE; delta += OBD_ECHO_BLOCK_SIZE) {
+ if (rw == OBD_BRW_WRITE) {
+ stripe_off = offset + delta;
+ stripe_id = id;
+ echo_get_stripe_off_id(lsm, &stripe_off, &stripe_id);
+ } else {
+ stripe_off = 0xdeadbeef00c0ffeeULL;
+ stripe_id = 0xdeadbeef00c0ffeeULL;
+ }
+ block_debug_setup(addr + delta, OBD_ECHO_BLOCK_SIZE,
+ stripe_off, stripe_id);
+ }
+
+ kunmap(page);
+}
+
+static int
+echo_client_page_debug_check(struct lov_stripe_md *lsm,
+ struct page *page, obd_id id,
+ obd_off offset, obd_off count)
+{
+ obd_off stripe_off;
+ obd_id stripe_id;
+ char *addr;
+ int delta;
+ int rc;
+ int rc2;
+
+ /* no partial pages on the client */
+ LASSERT(count == PAGE_SIZE);
+
+ addr = kmap(page);
+
+ for (rc = delta = 0; delta < PAGE_SIZE; delta += OBD_ECHO_BLOCK_SIZE) {
+ stripe_off = offset + delta;
+ stripe_id = id;
+ echo_get_stripe_off_id (lsm, &stripe_off, &stripe_id);
+
+ rc2 = block_debug_check("test_brw",
+ addr + delta, OBD_ECHO_BLOCK_SIZE,
+ stripe_off, stripe_id);
+ if (rc2 != 0) {
+ CERROR ("Error in echo object "LPX64"\n", id);
+ rc = rc2;
+ }
+ }
+
+ kunmap(page);
+ return rc;
+}
+
static int echo_client_kbrw(struct obd_device *obd, int rw, struct obdo *oa,
struct lov_stripe_md *lsm, obd_off offset,
obd_size count, struct obd_trans_info *oti)
{
- struct echo_client_obd *ec = &obd->u.echo_client;
+ struct echo_client_obd *ec = &obd->u.echocli;
obd_count npages;
struct brw_page *pga;
struct brw_page *pgp;
obd_off off;
int i;
int rc;
- int verify;
+ int verify = 0;
int gfp_mask;
- /* oa_id == 0 => speed test (no verification) else...
- * oa & 1 => use HIGHMEM
- */
- verify = (oa->o_id != 0);
- gfp_mask = ((oa->o_id & 1) == 0) ? GFP_KERNEL : GFP_HIGHUSER;
+ verify = ((oa->o_id) != ECHO_PERSISTENT_OBJID &&
+ (oa->o_valid & OBD_MD_FLFLAGS) != 0 &&
+ (oa->o_flags & OBD_FL_DEBUG_CHECK) != 0);
+
+ gfp_mask = ((oa->o_id & 2) == 0) ? GFP_KERNEL : GFP_HIGHUSER;
LASSERT(rw == OBD_BRW_WRITE || rw == OBD_BRW_READ);
goto out;
pgp->count = PAGE_SIZE;
- pgp->off = off;
+ pgp->disk_offset = pgp->page_offset = off;
pgp->flag = 0;
- if (verify) {
- void *addr = kmap(pgp->pg);
- obd_off stripe_off = off;
- obd_id stripe_id = oa->o_id;
-
- if (rw == OBD_BRW_WRITE) {
- echo_get_stripe_off_id(lsm, &stripe_off,
- &stripe_id);
- page_debug_setup(addr, pgp->count,
- stripe_off, stripe_id);
- } else {
- page_debug_setup(addr, pgp->count,
- 0xdeadbeef00c0ffeeULL,
- 0xdeadbeef00c0ffeeULL);
- }
- kunmap(pgp->pg);
- }
+ if (verify)
+ echo_client_page_debug_setup(lsm, pgp->pg, rw,
+ oa->o_id, off, pgp->count);
}
rc = obd_brw(rw, ec->ec_exp, oa, lsm, npages, pga, oti);
out:
- if (rc != 0)
+ if (rc != 0 || rw != OBD_BRW_READ)
verify = 0;
for (i = 0, pgp = pga; i < npages; i++, pgp++) {
continue;
if (verify) {
- void *addr = kmap(pgp->pg);
- obd_off stripe_off = pgp->off;
- obd_id stripe_id = oa->o_id;
- int vrc;
-
- echo_get_stripe_off_id (lsm, &stripe_off, &stripe_id);
- vrc = page_debug_check("test_brw", addr, pgp->count,
- stripe_off, stripe_id);
+ int vrc;
+ vrc = echo_client_page_debug_check(lsm, pgp->pg, oa->o_id,
+ pgp->page_offset,
+ pgp->count);
if (vrc != 0 && rc == 0)
rc = vrc;
-
- kunmap(pgp->pg);
}
__free_pages(pgp->pg, 0);
}
obd_off offset, obd_size count, char *buffer,
struct obd_trans_info *oti)
{
- struct echo_client_obd *ec = &obd->u.echo_client;
+ struct echo_client_obd *ec = &obd->u.echocli;
obd_count npages;
struct brw_page *pga;
struct brw_page *pgp;
for (i = 0, off = offset, pgp = pga;
i < npages;
i++, off += PAGE_SIZE, pgp++) {
- pgp->off = off;
+ pgp->disk_offset = pgp->page_offset = off;
pgp->pg = kiobuf->maplist[i];
pgp->count = PAGE_SIZE;
pgp->flag = 0;
struct list_head eap_item;
};
+#define EAP_FROM_COOKIE(c) \
+ (LASSERT(((struct echo_async_page *)(c))->eap_magic == EAP_MAGIC), \
+ (struct echo_async_page *)(c))
+
struct echo_async_state {
spinlock_t eas_lock;
obd_off eas_next_offset;
wait_queue_head_t eas_waitq;
struct list_head eas_avail;
struct obdo eas_oa;
+ struct lov_stripe_md *eas_lsm;
};
static int eas_should_wake(struct echo_async_state *eas)
return rc;
};
-struct echo_async_page *eap_from_cookie(void *cookie)
-{
- struct echo_async_page *eap = cookie;
- if (eap->eap_magic != EAP_MAGIC)
- return ERR_PTR(-EINVAL);
- return eap;
-};
-
static int ec_ap_make_ready(void *data, int cmd)
{
/* our pages are issued ready */
}
static void ec_ap_fill_obdo(void *data, int cmd, struct obdo *oa)
{
- struct echo_async_page *eap;
- eap = eap_from_cookie(data);
- if (IS_ERR(eap))
- return;
+ struct echo_async_page *eap = EAP_FROM_COOKIE(data);
memcpy(oa, &eap->eap_eas->eas_oa, sizeof(*oa));
}
-static void ec_ap_completion(void *data, int cmd, int rc)
+
+static void ec_ap_completion(void *data, int cmd, struct obdo *oa, int rc)
{
- struct echo_async_page *eap = eap_from_cookie(data);
+ struct echo_async_page *eap = EAP_FROM_COOKIE(data);
struct echo_async_state *eas;
unsigned long flags;
- if (IS_ERR(eap))
- return;
eas = eap->eap_eas;
+ if (cmd == OBD_BRW_READ &&
+ eas->eas_oa.o_id != ECHO_PERSISTENT_OBJID &&
+ (eas->eas_oa.o_valid & OBD_MD_FLFLAGS) != 0 &&
+ (eas->eas_oa.o_flags & OBD_FL_DEBUG_CHECK) != 0)
+ echo_client_page_debug_check(eas->eas_lsm, eap->eap_page,
+ eas->eas_oa.o_id, eap->eap_off,
+ PAGE_SIZE);
+
spin_lock_irqsave(&eas->eas_lock, flags);
if (rc && !eas->eas_rc)
eas->eas_rc = rc;
init_waitqueue_head(&eas.eas_waitq);
eas.eas_in_flight = 0;
eas.eas_rc = 0;
+ eas.eas_lsm = lsm;
INIT_LIST_HEAD(&eas.eas_avail);
/* prepare the group of pages that we're going to be keeping
if (page == NULL)
GOTO(out, rc = -ENOMEM);
- list_add_tail(&page->list, &pages);
+ page->private = 0;
+ list_add_tail(&PAGE_LIST(page), &pages);
OBD_ALLOC(eap, sizeof(*eap));
if (eap == NULL)
eap->eap_magic = EAP_MAGIC;
eap->eap_page = page;
eap->eap_eas = &eas;
- eap->eap_cookie = ERR_PTR(-ENOENT);
+ page->private = (unsigned long)eap;
list_add_tail(&eap->eap_item, &eas.eas_avail);
}
spin_unlock_irqrestore(&eas.eas_lock, flags);
/* unbind the eap from its old page offset */
- if (!IS_ERR(eap->eap_cookie)) {
+ if (eap->eap_cookie != NULL) {
obd_teardown_async_page(exp, lsm, NULL,
eap->eap_cookie);
- eap->eap_cookie = ERR_PTR(-ENOENT);
+ eap->eap_cookie = NULL;
}
eas.eas_next_offset += PAGE_SIZE;
eap->eap_off = eas.eas_next_offset;
- rc = obd_prep_async_page(exp, lsm, NULL, eap->eap_page,
- eap->eap_off, &ec_async_page_ops,
+ rc = obd_prep_async_page(exp, lsm, NULL, eap->eap_page,
+ eap->eap_off, &ec_async_page_ops,
eap, &eap->eap_cookie);
if (rc) {
spin_lock_irqsave(&eas.eas_lock, flags);
break;
}
+ if (oa->o_id != ECHO_PERSISTENT_OBJID &&
+ (oa->o_valid & OBD_MD_FLFLAGS) != 0 &&
+ (oa->o_flags & OBD_FL_DEBUG_CHECK) != 0)
+ echo_client_page_debug_setup(lsm, eap->eap_page, rw,
+ oa->o_id,
+ eap->eap_off, PAGE_SIZE);
+
/* always asserts urgent, which isn't quite right */
- rc = obd_queue_async_io(exp, lsm, NULL, eap->eap_cookie,
- rw, 0, PAGE_SIZE, 0,
+ rc = obd_queue_async_io(exp, lsm, NULL, eap->eap_cookie,
+ rw, 0, PAGE_SIZE, 0,
ASYNC_READY | ASYNC_URGENT |
ASYNC_COUNT_STABLE);
spin_lock_irqsave(&eas.eas_lock, flags);
out:
list_for_each_safe(pos, n, &pages) {
- struct page *page = list_entry(pos, struct page, list);
+ struct page *page = list_entry(pos, struct page,
+ PAGE_LIST_ENTRY);
- list_del(&page->list);
- if (page->private) {
+ list_del(&PAGE_LIST(page));
+ if (page->private != 0) {
eap = (struct echo_async_page *)page->private;
- if (!IS_ERR(eap->eap_cookie))
+ if (eap->eap_cookie != NULL)
obd_teardown_async_page(exp, lsm, NULL,
eap->eap_cookie);
OBD_FREE(eap, sizeof(*eap));
struct niobuf_remote *rnb;
obd_off off;
obd_size npages, tot_pages;
- int i, ret = 0, err = 0;
+ int i, ret = 0;
ENTRY;
if (count <= 0 || (count & (PAGE_SIZE - 1)) != 0 ||
GOTO(out, ret = -ENOMEM);
obdo_to_ioobj(oa, &ioo);
- ioo.ioo_bufcnt = npages;
off = offset;
/* XXX this can't be the best.. */
memset(oti, 0, sizeof(*oti));
+ ioo.ioo_bufcnt = npages;
ret = obd_preprw(rw, exp, oa, 1, &ioo, npages, rnb, lnb, oti);
if (ret != 0)
for (i = 0; i < npages; i++) {
struct page *page = lnb[i].page;
- void *addr;
/* read past eof? */
- if (page == NULL && lnb[i].rc == 0)
+ if (page == NULL && lnb[i].rc == 0)
continue;
- addr = kmap(lnb[i].page);
+ if (oa->o_id == ECHO_PERSISTENT_OBJID ||
+ (oa->o_valid & OBD_MD_FLFLAGS) == 0 ||
+ (oa->o_flags & OBD_FL_DEBUG_CHECK) == 0)
+ continue;
- if (rw == OBD_BRW_WRITE)
- page_debug_setup(addr, PAGE_SIZE,
- rnb[i].offset, oa->o_id);
- else
- err = page_debug_check("prep_commit", addr,
- PAGE_SIZE, rnb[i].offset,
- oa->o_id);
- kunmap(lnb[i].page);
+ if (rw == OBD_BRW_WRITE)
+ echo_client_page_debug_setup(lsm, page, rw,
+ oa->o_id,
+ rnb[i].offset,
+ rnb[i].len);
+ else
+ echo_client_page_debug_check(lsm, page,
+ oa->o_id,
+ rnb[i].offset,
+ rnb[i].len);
}
- ret = obd_commitrw(rw, exp, oa, 1, &ioo, npages, lnb, oti);
+ ret = obd_commitrw(rw, exp, oa, 1, &ioo, npages, lnb, oti, ret);
if (ret != 0)
GOTO(out, ret);
- if (err)
- GOTO(out, ret = err);
}
out:
RETURN(ret);
}
-int echo_client_brw_ioctl(int rw, struct obd_export *exp,
+int echo_client_brw_ioctl(int rw, struct obd_export *exp,
struct obd_ioctl_data *data)
{
struct obd_device *obd = class_exp2obd(exp);
- struct echo_client_obd *ec = &obd->u.echo_client;
+ struct echo_client_obd *ec = &obd->u.echocli;
struct obd_trans_info dummy_oti;
struct ec_object *eco;
int rc;
data->ioc_obdo1.o_valid &= ~OBD_MD_FLHANDLE;
data->ioc_obdo1.o_valid |= OBD_MD_FLGROUP;
- data->ioc_obdo1.o_gr = 2;
+ data->ioc_obdo1.o_gr = FILTER_GROUP_ECHO;
switch((long)data->ioc_pbuf1) {
case 1:
void *data, int flag)
{
struct ec_object *eco = (struct ec_object *)data;
- struct echo_client_obd *ec = &(eco->eco_device->u.echo_client);
+ struct echo_client_obd *ec = &(eco->eco_device->u.echocli);
struct lustre_handle lockh;
struct list_head *el;
int found = 0;
int mode, obd_off offset, obd_size nob)
{
struct obd_device *obd = exp->exp_obd;
- struct echo_client_obd *ec = &obd->u.echo_client;
+ struct echo_client_obd *ec = &obd->u.echocli;
struct lustre_handle *ulh = obdo_handle (oa);
struct ec_object *eco;
struct ec_lock *ecl;
ecl->ecl_mode = mode;
ecl->ecl_object = eco;
- ecl->ecl_extent.start = offset;
- ecl->ecl_extent.end = (nob == 0) ? ((obd_off) -1) : (offset + nob - 1);
+ ecl->ecl_policy.l_extent.start = offset;
+ ecl->ecl_policy.l_extent.end =
+ (nob == 0) ? ((obd_off) -1) : (offset + nob - 1);
flags = 0;
- rc = obd_enqueue(ec->ec_exp, eco->eco_lsm, NULL, LDLM_EXTENT,
- &ecl->ecl_extent,sizeof(ecl->ecl_extent), mode,
- &flags, echo_ldlm_callback, eco,
- &ecl->ecl_lock_handle);
+ rc = obd_enqueue(ec->ec_exp, eco->eco_lsm, LDLM_EXTENT,
+ &ecl->ecl_policy, mode, &flags, echo_ldlm_callback,
+ ldlm_completion_ast, NULL, eco, sizeof(struct ost_lvb),
+ lustre_swab_ost_lvb, &ecl->ecl_lock_handle);
if (rc != 0)
goto failed_1;
echo_client_cancel(struct obd_export *exp, struct obdo *oa)
{
struct obd_device *obd = exp->exp_obd;
- struct echo_client_obd *ec = &obd->u.echo_client;
+ struct echo_client_obd *ec = &obd->u.echocli;
struct lustre_handle *ulh = obdo_handle (oa);
struct ec_lock *ecl = NULL;
int found = 0;
int i;
ENTRY;
+ unlock_kernel();
+
memset(&dummy_oti, 0, sizeof(dummy_oti));
obd = exp->exp_obd;
- ec = &obd->u.echo_client;
+ ec = &obd->u.echocli;
switch (cmd) {
case OBD_IOC_CREATE: /* may create echo object */
rc = echo_get_object (&eco, obd, &data->ioc_obdo1);
if (rc == 0) {
oa = &data->ioc_obdo1;
- oa->o_gr = 2;
+ oa->o_gr = FILTER_GROUP_ECHO;
oa->o_valid |= OBD_MD_FLGROUP;
rc = obd_destroy(ec->ec_exp, oa, eco->eco_lsm,
&dummy_oti);
ldlm_lock_decref(&ack_lock->lock, ack_lock->mode);
}
+ lock_kernel();
+
return rc;
}
echo_client_setup(struct obd_device *obddev, obd_count len, void *buf)
{
struct lustre_cfg* lcfg = buf;
- struct echo_client_obd *ec = &obddev->u.echo_client;
+ struct echo_client_obd *ec = &obddev->u.echocli;
struct obd_device *tgt;
struct lustre_handle conn = {0, };
struct obd_uuid echo_uuid = { "ECHO_UUID" };
INIT_LIST_HEAD (&ec->ec_objects);
ec->ec_unique = 0;
- rc = obd_connect(&conn, tgt, &echo_uuid);
+ rc = obd_connect(&conn, tgt, &echo_uuid, NULL, FILTER_GROUP_ECHO);
if (rc) {
CERROR("fail to connect to device %s\n", lcfg->lcfg_inlbuf1);
return (rc);
{
struct list_head *el;
struct ec_object *eco;
- struct echo_client_obd *ec = &obddev->u.echo_client;
+ struct echo_client_obd *ec = &obddev->u.echocli;
int rc;
ENTRY;
}
static int echo_client_connect(struct lustre_handle *conn,
- struct obd_device *src, struct obd_uuid *cluuid)
+ struct obd_device *src,
+ struct obd_uuid *cluuid,
+ struct obd_connect_data *data,
+ unsigned long flags)
{
struct obd_export *exp;
int rc;
RETURN (rc);
}
-static int echo_client_disconnect(struct obd_export *exp, int flags)
+static int echo_client_disconnect(struct obd_export *exp,
+ unsigned long flags)
{
struct obd_device *obd;
struct echo_client_obd *ec;
GOTO(out, rc = -EINVAL);
obd = exp->exp_obd;
- ec = &obd->u.echo_client;
+ ec = &obd->u.echocli;
/* no more contention on export's lock list */
while (!list_empty (&exp->exp_ec_data.eced_locks)) {
}
static struct obd_ops echo_obd_ops = {
- o_owner: THIS_MODULE,
- o_setup: echo_client_setup,
- o_cleanup: echo_client_cleanup,
- o_iocontrol: echo_client_iocontrol,
- o_connect: echo_client_connect,
- o_disconnect: echo_client_disconnect
+ .o_owner = THIS_MODULE,
+ .o_setup = echo_client_setup,
+ .o_cleanup = echo_client_cleanup,
+ .o_iocontrol = echo_client_iocontrol,
+ .o_connect = echo_client_connect,
+ .o_disconnect = echo_client_disconnect
};
int echo_client_init(void)
struct lprocfs_static_vars lvars;
lprocfs_init_vars(echo, &lvars);
- return class_register_type(&echo_obd_ops, lvars.module_vars,
+ return class_register_type(&echo_obd_ops, NULL, lvars.module_vars,
OBD_ECHO_CLIENT_DEVICENAME);
}