Whamcloud - gitweb
r=shaver
authorgreen <green>
Sun, 14 Dec 2003 21:39:09 +0000 (21:39 +0000)
committergreen <green>
Sun, 14 Dec 2003 21:39:09 +0000 (21:39 +0000)
fix for #2319, make osic to be allocated separately and implement proper
refcounting for it.
Also adds a test to sanity.sh that checks for (fixed) crash.

lustre/include/linux/obd.h
lustre/include/linux/obd_class.h
lustre/liblustre/llite_lib.h
lustre/liblustre/rw.c
lustre/llite/rw.c
lustre/obdclass/class_obd.c
lustre/obdclass/genops.c
lustre/tests/sanity.sh

index 8c85be5..2c5155e 100644 (file)
@@ -111,6 +111,7 @@ struct obd_async_page_ops {
 
 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;
index b3a9769..da2dab9 100644 (file)
@@ -66,9 +66,10 @@ struct obd_device * class_find_client_obd(struct obd_uuid *tgt_uuid,
                                           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 */
index f258ec9..9e4340d 100644 (file)
@@ -86,7 +86,7 @@ struct llu_inode_info {
          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;
index 70fd26e..c05a7c9 100644 (file)
@@ -466,6 +466,7 @@ void put_sysio_cookie(struct llu_sysio_cookie *cookie)
 
         I_RELE(cookie->lsc_inode);
 
+        osic_release(cookie->lsc_osic);
         OBD_FREE(cookie, LLU_SYSIO_COOKIE_SIZE(cookie->lsc_npages));
 }
 
@@ -525,7 +526,7 @@ int llu_prep_async_io(struct llu_sysio_cookie *cookie, int cmd,
                 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)
@@ -543,7 +544,7 @@ int llu_start_async_io(struct llu_sysio_cookie *cookie)
         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);
 }
 
 /*
@@ -783,7 +784,7 @@ int llu_iop_iodone(struct ioctx *ioctxp)
         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)
index b8ff805..678c318 100644 (file)
@@ -396,20 +396,22 @@ int ll_commit_write(struct file *file, struct page *page, unsigned from,
                 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");
index 3f72012..68f9442 100644 (file)
@@ -575,6 +575,7 @@ EXPORT_SYMBOL(class_disconnect);
 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);
index 12451d1..dc524cf 100644 (file)
@@ -622,14 +622,28 @@ void class_disconnect_exports(struct obd_device *obd, int flags)
         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;
@@ -637,6 +651,7 @@ void osic_add_one(struct obd_sync_io_container *osic)
         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)
@@ -657,6 +672,7 @@ 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)
index 87e1340..ed059e0 100644 (file)
@@ -1604,6 +1604,24 @@ test_62() {
 }
 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.