struct obd_sync_io_container {
spinlock_t osic_lock;
+ atomic_t osic_refcount;
int osic_pending;
int osic_rc;
wait_queue_head_t osic_waitq;
char * typ_name,
struct obd_uuid *grp_uuid);
-void osic_init(struct obd_sync_io_container *osic);
+void osic_init(struct obd_sync_io_container **osic);
void osic_add_one(struct obd_sync_io_container *osic);
void osic_complete_one(struct obd_sync_io_container *osic, int rc);
+void osic_release(struct obd_sync_io_container *osic);
int osic_wait(struct obd_sync_io_container *osic);
/* config.c */
sizeof(struct page) * (x))
struct llu_sysio_cookie {
- struct obd_sync_io_container lsc_osic;
+ struct obd_sync_io_container *lsc_osic;
struct inode *lsc_inode;
int lsc_npages;
struct ll_async_page *lsc_llap;
I_RELE(cookie->lsc_inode);
+ osic_release(cookie->lsc_osic);
OBD_FREE(cookie, LLU_SYSIO_COOKIE_SIZE(cookie->lsc_npages));
}
llap[i].llap_page = &pages[i];
llap[i].llap_inode = cookie->lsc_inode;
- rc = obd_queue_sync_io(exp, lsm, NULL, &cookie->lsc_osic,
+ rc = obd_queue_sync_io(exp, lsm, NULL, cookie->lsc_osic,
llap[i].llap_cookie, cmd,
pages[i]._offset, pages[i]._count, 0);
if (rc)
struct lov_stripe_md *lsm = llu_i2info(cookie->lsc_inode)->lli_smd;
struct obd_export *exp = llu_i2obdexp(cookie->lsc_inode);
- return obd_trigger_sync_io(exp, lsm, NULL, &cookie->lsc_osic);
+ return obd_trigger_sync_io(exp, lsm, NULL, cookie->lsc_osic);
}
/*
for (i = 0; i < lsca->ncookies; i++) {
cookie = lsca->cookies[i];
if (cookie) {
- err = osic_wait(&cookie->lsc_osic);
+ err = osic_wait(cookie->lsc_osic);
if (err && !rc)
rc = err;
if (!rc)
rc = obd_queue_async_io(exp, lsm, NULL, llap->llap_cookie,
OBD_BRW_WRITE, 0, 0, 0, 0);
if (rc != 0) { /* async failed, try sync.. */
- struct obd_sync_io_container osic;
+ struct obd_sync_io_container *osic;
osic_init(&osic);
- rc = obd_queue_sync_io(exp, lsm, NULL, &osic,
+ rc = obd_queue_sync_io(exp, lsm, NULL, osic,
llap->llap_cookie,
OBD_BRW_WRITE, 0, to, 0);
if (rc)
- GOTO(out, rc);
+ GOTO(free_osic, rc);
- rc = obd_trigger_sync_io(exp, lsm, NULL, &osic);
+ rc = obd_trigger_sync_io(exp, lsm, NULL, osic);
if (rc)
- GOTO(out, rc);
+ GOTO(free_osic, rc);
- rc = osic_wait(&osic);
+ rc = osic_wait(osic);
+free_osic:
+ osic_release(osic);
GOTO(out, rc);
}
LL_CDEBUG_PAGE(page, "write queued\n");
EXPORT_SYMBOL(class_disconnect_exports);
EXPORT_SYMBOL(osic_init);
+EXPORT_SYMBOL(osic_release);
EXPORT_SYMBOL(osic_add_one);
EXPORT_SYMBOL(osic_wait);
EXPORT_SYMBOL(osic_complete_one);
EXIT;
}
-void osic_init(struct obd_sync_io_container *osic)
+void osic_init(struct obd_sync_io_container **osic_out)
{
+ struct obd_sync_io_container *osic;
+ OBD_ALLOC(osic, sizeof(*osic));
spin_lock_init(&osic->osic_lock);
osic->osic_rc = 0;
osic->osic_pending = 0;
+ atomic_set(&osic->osic_refcount, 1);
init_waitqueue_head(&osic->osic_waitq);
+ *osic_out = osic;
};
+static inline void osic_grab(struct obd_sync_io_container *osic)
+{
+ atomic_inc(&osic->osic_refcount);
+}
+void osic_release(struct obd_sync_io_container *osic)
+{
+ if (atomic_dec_and_test(&osic->osic_refcount))
+ OBD_FREE(osic, sizeof(*osic));
+}
+
void osic_add_one(struct obd_sync_io_container *osic)
{
unsigned long flags;
spin_lock_irqsave(&osic->osic_lock, flags);
osic->osic_pending++;
spin_unlock_irqrestore(&osic->osic_lock, flags);
+ osic_grab(osic);
}
void osic_complete_one(struct obd_sync_io_container *osic, int rc)
osic->osic_pending);
if (wake)
wake_up(wake);
+ osic_release(osic);
}
static int osic_done(struct obd_sync_io_container *osic)
}
run_test 62 "verify obd_match failure doesn't LBUG (should -EIO)"
+# bug 2319 - osic_wait() interrupted causes crash because of invalid waitq.
+test_63() {
+ for i in /proc/fs/lustre/osc/*/max_dirty_mb ; do
+ echo 0 > $i
+ done
+ for i in `seq 10` ; do
+ dd if=/dev/zero of=$DIR/syncwrite_testfile bs=8k &
+ sleep 5
+ kill $!
+ sleep 1
+ done
+
+ for i in /proc/fs/lustre/osc/*/max_dirty_mb ; do
+ echo $[ 60 * 1025 *1024 ] > $i
+ done
+}
+run_test 63 "Verify osic_wait interruption does not crash"
+
# on the LLNL clusters, runas will still pick up root's $TMP settings,
# which will not be writable for the runas user, and then you get a CVS
# error message with a corrupt path string (CVS bug) and panic.