#include <net/9p/client.h>
 #include <net/9p/transport.h>
 #include <linux/scatterlist.h>
+#include <linux/swap.h>
 #include <linux/virtio.h>
 #include <linux/virtio_9p.h>
 #include "trans_common.h"
 
 /* a single mutex to manage channel initialization and attachment */
 static DEFINE_MUTEX(virtio_9p_lock);
+static DECLARE_WAIT_QUEUE_HEAD(vp_wq);
+static atomic_t vp_pinned = ATOMIC_INIT(0);
 
 /**
  * struct virtio_chan - per-instance transport information
        struct virtqueue *vq;
        int ring_bufs_avail;
        wait_queue_head_t *vc_wq;
-
+       /* This is global limit. Since we don't have a global structure,
+        * will be placing it in each channel.
+        */
+       int p9_max_pages;
        /* Scatterlist: can be too big for stack. */
        struct scatterlist sg[VIRTQUEUE_NUM];
 
                req = p9_tag_lookup(chan->client, rc->tag);
                if (req->tc->private) {
                        struct trans_rpage_info *rp = req->tc->private;
+                       int p = rp->rp_nr_pages;
                        /*Release pages */
                        p9_release_req_pages(rp);
+                       atomic_sub(p, &vp_pinned);
+                       wake_up(&vp_wq);
                        if (rp->rp_alloc)
                                kfree(rp);
                        req->tc->private = NULL;
                int rpinfo_size = sizeof(struct trans_rpage_info) +
                        sizeof(struct page *) * nr_pages;
 
+               if (atomic_read(&vp_pinned) >= chan->p9_max_pages) {
+                       err = wait_event_interruptible(vp_wq,
+                               atomic_read(&vp_pinned) < chan->p9_max_pages);
+                       if (err  == -ERESTARTSYS)
+                               return err;
+                       P9_DPRINTK(P9_DEBUG_TRANS, "9p: May gup pages now.\n");
+               }
+
                if (rpinfo_size <= (req->tc->capacity - req->tc->size)) {
                        /* We can use sdata */
                        req->tc->private = req->tc->sdata + req->tc->size;
                        if (rpinfo->rp_alloc)
                                kfree(rpinfo);
                        return err;
+               } else {
+                       atomic_add(rpinfo->rp_nr_pages, &vp_pinned);
                }
        }
 
        }
        init_waitqueue_head(chan->vc_wq);
        chan->ring_bufs_avail = 1;
+       /* Ceiling limit to avoid denial of service attacks */
+       chan->p9_max_pages = nr_free_buffer_pages()/4;
 
        mutex_lock(&virtio_9p_lock);
        list_add_tail(&chan->chan_list, &virtio_chan_list);