- return (rc);
-}
-#else
-static int echo_client_ubrw(struct obd_device *obd, int rw,
- struct obdo *oa, struct lov_stripe_md *lsm,
- obd_off offset, obd_size count, char *buffer,
- struct obd_trans_info *oti)
-{
-#warning "echo_client_ubrw() needs to be ported on 2.6 yet"
- LBUG();
- return 0;
-}
-#endif
-#endif
-
-struct echo_async_state;
-
-#define EAP_MAGIC 79277927
-struct echo_async_page {
- int eap_magic;
- struct page *eap_page;
- void *eap_cookie;
- obd_off eap_off;
- struct echo_async_state *eap_eas;
- struct list_head eap_item;
-};
-
-struct echo_async_state {
- spinlock_t eas_lock;
- obd_off eas_next_offset;
- obd_off eas_end_offset;
- int eas_in_flight;
- int eas_rc;
- 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)
-{
- unsigned long flags;
- int rc = 0;
- spin_lock_irqsave(&eas->eas_lock, flags);
- if (eas->eas_rc == 0 && !list_empty(&eas->eas_avail))
- rc = 1;
- spin_unlock_irqrestore(&eas->eas_lock, flags);
- 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 */
- LBUG();
- return 0;
-}
-static int ec_ap_refresh_count(void *data, int cmd)
-{
- /* our pages are issued with a stable count */
- LBUG();
- return PAGE_SIZE;
-}
-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;
-
- memcpy(oa, &eap->eap_eas->eas_oa, sizeof(*oa));
-}
-
-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_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)
- 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;
- eas->eas_in_flight--;
- list_add(&eap->eap_item, &eas->eas_avail);
- wake_up(&eas->eas_waitq);
- spin_unlock_irqrestore(&eas->eas_lock, flags);
-}
-
-static struct obd_async_page_ops ec_async_page_ops = {
- .ap_make_ready = ec_ap_make_ready,
- .ap_refresh_count = ec_ap_refresh_count,
- .ap_fill_obdo = ec_ap_fill_obdo,
- .ap_completion = ec_ap_completion,
-};
-
-static int echo_client_async_page(struct obd_export *exp, int rw,
- struct obdo *oa, struct lov_stripe_md *lsm,
- obd_off offset, obd_size count,
- obd_size batching)
-{
- obd_count npages, i;
- struct echo_async_page *eap;
- struct echo_async_state eas;
- struct list_head *pos, *n;
- int rc = 0;
- unsigned long flags;
- LIST_HEAD(pages);
-#if 0
- int verify;
- 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;
-#endif
-
- LASSERT(rw == OBD_BRW_WRITE || rw == OBD_BRW_READ);
-
- if (count <= 0 ||
- (count & (PAGE_SIZE - 1)) != 0 ||
- (lsm != NULL &&
- lsm->lsm_object_id != oa->o_id))
- return (-EINVAL);
-
- /* XXX think again with misaligned I/O */
- npages = batching >> PAGE_SHIFT;
-
- memcpy(&eas.eas_oa, oa, sizeof(*oa));
- eas.eas_next_offset = offset;
- eas.eas_end_offset = offset + count;
- spin_lock_init(&eas.eas_lock);
- 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
- * in flight */
- for (i = 0; i < npages; i++) {
- struct page *page = alloc_page(GFP_KERNEL);
- if (page == NULL)
- GOTO(out, rc = -ENOMEM);
-
- page->private = 0;
- list_add_tail(&PAGE_LIST(page), &pages);
-
- OBD_ALLOC(eap, sizeof(*eap));
- if (eap == NULL)
- GOTO(out, rc = -ENOMEM);
-
- eap->eap_magic = EAP_MAGIC;
- eap->eap_page = page;
- eap->eap_eas = &eas;
- page->private = (unsigned long)eap;
- list_add_tail(&eap->eap_item, &eas.eas_avail);
- }
-
- /* first we spin queueing io and being woken by its completion */
- spin_lock_irqsave(&eas.eas_lock, flags);
- for(;;) {
- int rc;
-
- /* sleep until we have a page to send */
- spin_unlock_irqrestore(&eas.eas_lock, flags);
- rc = wait_event_interruptible(eas.eas_waitq,
- eas_should_wake(&eas));
- spin_lock_irqsave(&eas.eas_lock, flags);
- if (rc && !eas.eas_rc)
- eas.eas_rc = rc;
- if (eas.eas_rc)
- break;
- if (list_empty(&eas.eas_avail))
- continue;
- eap = list_entry(eas.eas_avail.next, struct echo_async_page,
- eap_item);
- list_del(&eap->eap_item);
- spin_unlock_irqrestore(&eas.eas_lock, flags);
-
- /* unbind the eap from its old page offset */
- if (eap->eap_cookie != NULL) {
- obd_teardown_async_page(exp, lsm, NULL,
- eap->eap_cookie);
- 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,
- eap, &eap->eap_cookie);
- if (rc) {
- spin_lock_irqsave(&eas.eas_lock, flags);
- eas.eas_rc = rc;
- break;
- }
-
- if (oa->o_id != ECHO_PERSISTENT_OBJID)
- 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,
- ASYNC_READY | ASYNC_URGENT |
- ASYNC_COUNT_STABLE);
- spin_lock_irqsave(&eas.eas_lock, flags);
- if (rc && !eas.eas_rc) {
- eas.eas_rc = rc;
- break;
- }
- eas.eas_in_flight++;
- if (eas.eas_next_offset == eas.eas_end_offset)
- break;
- }
-
- /* still hold the eas_lock here.. */
-
- /* now we just spin waiting for all the rpcs to complete */
- while(eas.eas_in_flight) {
- spin_unlock_irqrestore(&eas.eas_lock, flags);
- wait_event_interruptible(eas.eas_waitq,
- eas.eas_in_flight == 0);
- spin_lock_irqsave(&eas.eas_lock, flags);
- }
- spin_unlock_irqrestore(&eas.eas_lock, flags);
-
-out:
- list_for_each_safe(pos, n, &pages) {
- struct page *page = list_entry(pos, struct page,
- PAGE_LIST_ENTRY);
-
- list_del(&PAGE_LIST(page));
- if (page->private != 0) {
- eap = (struct echo_async_page *)page->private;
- if (eap->eap_cookie != NULL)
- obd_teardown_async_page(exp, lsm, NULL,
- eap->eap_cookie);
- OBD_FREE(eap, sizeof(*eap));
- }
- __free_page(page);
- }
-