#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 *
if (p) {
memset(p, 0, sizeof(*p));
INIT_LIST_HEAD(&p->wb_list);
- init_waitqueue_head(&p->wb_wait);
}
return 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)
{
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;
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));
/* Release struct file or cached credential */
nfs_clear_request(req);
+ put_nfs_open_context(req->wb_context);
nfs_page_free(req);
}
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));
}
/**
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;
* 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,