Whamcloud - gitweb
b=19529
authordzogin <dzogin>
Wed, 15 Jul 2009 13:21:11 +0000 (13:21 +0000)
committerdzogin <dzogin>
Wed, 15 Jul 2009 13:21:11 +0000 (13:21 +0000)
i=andrew.perepechko
i=adilger
Description: Avoid deadlock for local client writes
Details    : Use new OBD_BRW_MEMALLOC flag to notify OST about writes in the
     memory freeing context. This allows OST threads to set the
     PF_MEMALLOC flag on task structures in order to allocate memory
     from reserved pools and complete IO.
     Use GFP_HIGHUSER for OST allocations for non-local client writes,
     so that the OST threads generate memory pressure and allow
     inactive pages to be reclaimed.

lustre/ChangeLog
lustre/include/liblustre.h
lustre/include/lustre/lustre_idl.h
lustre/obdfilter/filter_io.c
lustre/osc/osc_request.c
lustre/ost/ost_handler.c

index 1cbc24f..33adad7 100644 (file)
@@ -15,6 +15,17 @@ tbd Sun Microsystems, Inc.
          more information, please refer to bugzilla 17630.
 
 Severity   : normal
+Bugzilla   : 19529
+Description: Avoid deadlock for local client writes
+Details    : Use new OBD_BRW_MEMALLOC flag to notify OST about writes in the
+            memory freeing context. This allows OST threads to set the
+            PF_MEMALLOC flag on task structures in order to allocate memory
+            from reserved pools and complete IO.
+            Use GFP_HIGHUSER for OST allocations for non-local client writes,
+            so that the OST threads generate memory pressure and allow
+            inactive pages to be reclaimed.
+
+Severity   : normal
 Frequency  : rare
 Bugzilla   : 18380
 Descriptoin: lock ordering violation between &cli->cl_sem and _lprocfs_lock
index 0f76b89..0522e56 100644 (file)
@@ -742,6 +742,10 @@ typedef struct { volatile int counter; } atomic_t;
 #define unlikely(exp) (exp)
 #endif
 
+#define libcfs_memory_pressure_get() (0) 
+#define libcfs_memory_pressure_set() do {} while (0) 
+#define libcfs_memory_pressure_clr() do {} while (0)
+
 /* FIXME sys/capability will finally included linux/fs.h thus
  * cause numerous trouble on x86-64. as temporary solution for
  * build broken at cary, we copy definition we need from capability.h
index 4b8ddba..51c7868 100644 (file)
@@ -668,6 +668,7 @@ extern void lustre_swab_obd_statfs (struct obd_statfs *os);
 #define OBD_BRW_NOQUOTA        0x100
 #define OBD_BRW_SRVLOCK        0x200 /* Client holds no lock over this page */
 #define OBD_BRW_ASYNC          0x400 /* Server may delay commit to disk */
+#define OBD_BRW_MEMALLOC       0x800 /* Client runs in the "kswapd" context */
 
 #define OBD_OBJECT_EOF 0xffffffffffffffffULL
 
index 76dc70a..adcf7e3 100644 (file)
@@ -263,21 +263,26 @@ long filter_grant(struct obd_export *exp, obd_size current_grant,
 /*
  * the routine is used to request pages from pagecache
  *
- * use GFP_NOFS not allowing to enter FS as the client can run on this node
- * and we might end waiting on a page he sent in the request we're serving.
- *
+ * use GFP_NOFS for requests from a local client not allowing to enter FS
+ * as we might end up waiting on a page he sent in the request we're serving.
  * use __GFP_HIGHMEM so that the pages can use all of the available memory
  * on 32-bit machines
+ * use more agressive GFP_HIGHUSER flags from non-local clients to be able to
+ * generate more memory pressure, but at the same time use __GFP_NOMEMALLOC
+ * in order not to exhaust emergency reserves.
  *
+ * See Bug 19529 and Bug 19917 for details.
  */
 static struct page * filter_get_page(struct obd_device *obd,
                                      struct inode *inode,
-                                     obd_off offset)
+                                     obd_off offset,
+                                     int localreq)
 {
         struct page *page;
 
         page = find_or_create_page(inode->i_mapping, offset >> CFS_PAGE_SHIFT,
-                                   GFP_NOFS | __GFP_HIGHMEM);
+                                   (localreq ? (GFP_NOFS | __GFP_HIGHMEM)
+                                             : (GFP_HIGHUSER | __GFP_NOMEMALLOC)));
         if (unlikely(page == NULL))
                 lprocfs_counter_add(obd->obd_stats, LPROC_FILTER_NO_PAGE, 1);
 
@@ -429,7 +434,7 @@ static int filter_preprw_read(int cmd, struct obd_export *exp, struct obdo *oa,
                          * so it's easy to detect later. */
                         break;
 
-                lnb->page = filter_get_page(obd, inode, lnb->offset);
+                lnb->page = filter_get_page(obd, inode, lnb->offset, 0);
                 if (lnb->page == NULL)
                         GOTO(cleanup, rc = -ENOMEM);
 
@@ -641,11 +646,14 @@ static int filter_preprw_write(int cmd, struct obd_export *exp, struct obdo *oa,
         void *iobuf;
         obd_size left;
         unsigned long now = jiffies, timediff;
-        int rc = 0, i, tot_bytes = 0, cleanup_phase = 0;
+        int rc = 0, i, tot_bytes = 0, cleanup_phase = 0, localreq = 0;
         ENTRY;
         LASSERT(objcount == 1);
         LASSERT(obj->ioo_bufcnt > 0);
 
+        if (exp->exp_connection->c_peer.nid == exp->exp_connection->c_self) 
+                localreq = 1;
+
         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
         iobuf = filter_iobuf_get(&obd->u.filter, oti);
         if (IS_ERR(iobuf))
@@ -751,7 +759,8 @@ static int filter_preprw_write(int cmd, struct obd_export *exp, struct obdo *oa,
                  * needs to keep the pages all aligned properly. */
                 lnb->dentry = dentry;
 
-                lnb->page = filter_get_page(obd, dentry->d_inode, lnb->offset);
+                lnb->page = filter_get_page(obd, dentry->d_inode, lnb->offset,
+                                            localreq);
                 if (lnb->page == NULL)
                         GOTO(cleanup, rc = -ENOMEM);
 
index b1767dd..23ba8d2 100644 (file)
@@ -2923,6 +2923,9 @@ static int osc_queue_async_io(struct obd_export *exp, struct lov_stripe_md *lsm,
         oap->oap_page_off = off;
         oap->oap_count = count;
         oap->oap_brw_flags = brw_flags;
+        /* Give a hint to OST that requests are coming from kswapd - bug19529 */
+        if (libcfs_memory_pressure_get())
+                oap->oap_brw_flags |= OBD_BRW_MEMALLOC;
         spin_lock(&oap->oap_lock);
         oap->oap_async_flags = async_flags;
         spin_unlock(&oap->oap_lock);
@@ -3052,6 +3055,9 @@ static int osc_queue_group_io(struct obd_export *exp, struct lov_stripe_md *lsm,
         oap->oap_page_off = off;
         oap->oap_count = count;
         oap->oap_brw_flags = brw_flags;
+        /* Give a hint to OST that requests are coming from kswapd - bug19529 */
+        if (libcfs_memory_pressure_get())
+                oap->oap_brw_flags |= OBD_BRW_MEMALLOC;
         spin_lock(&oap->oap_lock);
         oap->oap_async_flags = async_flags;
         spin_unlock(&oap->oap_lock);
index f89bcdf..0f103dd 100644 (file)
@@ -925,6 +925,10 @@ static int ost_brw_write(struct ptlrpc_request *req, struct obd_trans_info *oti)
         body = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF, sizeof(*body));
         LASSERT(body != NULL);
 
+        if ((body->oa.o_flags & OBD_BRW_MEMALLOC) &&
+            (exp->exp_connection->c_peer.nid == exp->exp_connection->c_self))
+                libcfs_memory_pressure_set();
+
         objcount = lustre_msg_buflen(req->rq_reqmsg, REQ_REC_OFF + 1) /
                    sizeof(*ioo);
         ioo = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF + 1,
@@ -1189,6 +1193,7 @@ static int ost_brw_write(struct ptlrpc_request *req, struct obd_trans_info *oti)
                       exp->exp_connection->c_remote_uuid.uuid,
                       libcfs_id2str(req->rq_peer));
         }
+        libcfs_memory_pressure_clr();
         RETURN(rc);
 }