libceph: use memalloc flags for net IO
authorMike Christie <michaelc@cs.wisc.edu>
Thu, 16 Oct 2014 06:50:19 +0000 (01:50 -0500)
committerIlya Dryomov <idryomov@redhat.com>
Thu, 30 Oct 2014 10:11:50 +0000 (13:11 +0300)
This patch has ceph's lib code use the memalloc flags.

If the VM layer needs to write data out to free up memory to handle new
allocation requests, the block layer must be able to make forward progress.
To handle that requirement we use structs like mempools to reserve memory for
objects like bios and requests.

The problem is when we send/receive block layer requests over the network
layer, net skb allocations can fail and the system can lock up.
To solve this, the memalloc related flags were added. NBD, iSCSI
and NFS uses these flags to tell the network/vm layer that it should
use memory reserves to fullfill allcation requests for structs like
skbs.

I am running ceph in a bunch of VMs in my laptop, so this patch was
not tested very harshly.

Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Reviewed-by: Ilya Dryomov <idryomov@redhat.com>
net/ceph/messenger.c

index 559c9f619c2027e33f733469b2a8a59eda582f89..8d1653caffdb4104d893c2bcbac939ed465a8bc9 100644 (file)
@@ -484,7 +484,7 @@ static int ceph_tcp_connect(struct ceph_connection *con)
                               IPPROTO_TCP, &sock);
        if (ret)
                return ret;
-       sock->sk->sk_allocation = GFP_NOFS;
+       sock->sk->sk_allocation = GFP_NOFS | __GFP_MEMALLOC;
 
 #ifdef CONFIG_LOCKDEP
        lockdep_set_class(&sock->sk->sk_lock, &socket_class);
@@ -509,6 +509,9 @@ static int ceph_tcp_connect(struct ceph_connection *con)
 
                return ret;
        }
+
+       sk_set_memalloc(sock->sk);
+
        con->sock = sock;
        return 0;
 }
@@ -2769,8 +2772,11 @@ static void con_work(struct work_struct *work)
 {
        struct ceph_connection *con = container_of(work, struct ceph_connection,
                                                   work.work);
+       unsigned long pflags = current->flags;
        bool fault;
 
+       current->flags |= PF_MEMALLOC;
+
        mutex_lock(&con->mutex);
        while (true) {
                int ret;
@@ -2824,6 +2830,8 @@ static void con_work(struct work_struct *work)
                con_fault_finish(con);
 
        con->ops->put(con);
+
+       tsk_restore_flags(current, pflags, PF_MEMALLOC);
 }
 
 /*