vserver 1.9.3
[linux-2.6.git] / fs / nfs / pagelist.c
index c82fc85..4f1ba72 100644 (file)
 
 #define NFS_PARANOIA 1
 
-/*
- * Spinlock
- */
-spinlock_t nfs_wreq_lock = SPIN_LOCK_UNLOCKED;
-
 static kmem_cache_t *nfs_page_cachep;
 
 static inline struct nfs_page *
@@ -36,7 +31,6 @@ nfs_page_alloc(void)
        if (p) {
                memset(p, 0, sizeof(*p));
                INIT_LIST_HEAD(&p->wb_list);
-               init_waitqueue_head(&p->wb_wait);
        }
        return p;
 }
@@ -62,7 +56,7 @@ nfs_page_free(struct nfs_page *p)
  * User should ensure it is safe to sleep in this function.
  */
 struct nfs_page *
-nfs_create_request(struct file *file, struct inode *inode,
+nfs_create_request(struct nfs_open_context *ctx, struct inode *inode,
                   struct page *page,
                   unsigned int offset, unsigned int count)
 {
@@ -94,33 +88,38 @@ nfs_create_request(struct file *file, struct inode *inode,
        req->wb_offset  = offset;
        req->wb_pgbase  = offset;
        req->wb_bytes   = count;
-       req->wb_inode   = inode;
-       req->wb_count   = 1;
-       server->rpc_ops->request_init(req, file);
+       atomic_set(&req->wb_count, 1);
+       req->wb_context = get_nfs_open_context(ctx);
 
        return req;
 }
 
+/**
+ * nfs_unlock_request - Unlock request and wake up sleepers.
+ * @req:
+ */
+void nfs_unlock_request(struct nfs_page *req)
+{
+       if (!NFS_WBACK_BUSY(req)) {
+               printk(KERN_ERR "NFS: Invalid unlock attempted\n");
+               BUG();
+       }
+       smp_mb__before_clear_bit();
+       clear_bit(PG_BUSY, &req->wb_flags);
+       smp_mb__after_clear_bit();
+       wake_up_all(&req->wb_context->waitq);
+       nfs_release_request(req);
+}
+
 /**
  * nfs_clear_request - Free up all resources allocated to the request
  * @req:
  *
- * Release all resources associated with a write request after it
+ * Release page resources associated with a write request after it
  * has completed.
  */
 void nfs_clear_request(struct nfs_page *req)
 {
-       if (req->wb_state)
-               req->wb_state = NULL;
-       /* Release struct file or cached credential */
-       if (req->wb_file) {
-               fput(req->wb_file);
-               req->wb_file = NULL;
-       }
-       if (req->wb_cred) {
-               put_rpccred(req->wb_cred);
-               req->wb_cred = NULL;
-       }
        if (req->wb_page) {
                page_cache_release(req->wb_page);
                req->wb_page = NULL;
@@ -137,12 +136,8 @@ void nfs_clear_request(struct nfs_page *req)
 void
 nfs_release_request(struct nfs_page *req)
 {
-       spin_lock(&nfs_wreq_lock);
-       if (--req->wb_count) {
-               spin_unlock(&nfs_wreq_lock);
+       if (!atomic_dec_and_test(&req->wb_count))
                return;
-       }
-       spin_unlock(&nfs_wreq_lock);
 
 #ifdef NFS_PARANOIA
        BUG_ON (!list_empty(&req->wb_list));
@@ -151,6 +146,7 @@ nfs_release_request(struct nfs_page *req)
 
        /* Release struct file or cached credential */
        nfs_clear_request(req);
+       put_nfs_open_context(req->wb_context);
        nfs_page_free(req);
 }
 
@@ -194,12 +190,12 @@ nfs_list_add_request(struct nfs_page *req, struct list_head *head)
 int
 nfs_wait_on_request(struct nfs_page *req)
 {
-       struct inode    *inode = req->wb_inode;
+       struct inode    *inode = req->wb_context->dentry->d_inode;
         struct rpc_clnt        *clnt = NFS_CLIENT(inode);
 
        if (!NFS_WBACK_BUSY(req))
                return 0;
-       return nfs_wait_event(clnt, req->wb_wait, !NFS_WBACK_BUSY(req));
+       return nfs_wait_event(clnt, req->wb_context->waitq, !NFS_WBACK_BUSY(req));
 }
 
 /**
@@ -224,7 +220,11 @@ nfs_coalesce_requests(struct list_head *head, struct list_head *dst,
 
                req = nfs_list_entry(head->next);
                if (prev) {
-                       if (req->wb_cred != prev->wb_cred)
+                       if (req->wb_context->cred != prev->wb_context->cred)
+                               break;
+                       if (req->wb_context->lockowner != prev->wb_context->lockowner)
+                               break;
+                       if (req->wb_context->state != prev->wb_context->state)
                                break;
                        if (req->wb_index != (prev->wb_index + 1))
                                break;
@@ -254,7 +254,7 @@ nfs_coalesce_requests(struct list_head *head, struct list_head *dst,
  * If the number of requests is set to 0, the entire address_space
  * starting at index idx_start, is scanned.
  * The requests are *not* checked to ensure that they form a contiguous set.
- * You must be holding the nfs_wreq_lock when calling this function
+ * You must be holding the inode's req_lock when calling this function
  */
 int
 nfs_scan_list(struct list_head *head, struct list_head *dst,