]> err.no Git - linux-2.6/blobdiff - fs/nfs/direct.c
kbuild: modpost build fix
[linux-2.6] / fs / nfs / direct.c
index 1e3725e51df18688cfb8222b1414ad1fe9c03ee9..3c72b0c072839383950c59955da28c6c098897bf 100644 (file)
@@ -59,7 +59,6 @@
 
 #define NFSDBG_FACILITY                NFSDBG_VFS
 
-static void nfs_free_user_pages(struct page **pages, int npages, int do_dirty);
 static kmem_cache_t *nfs_direct_cachep;
 
 /*
@@ -73,7 +72,6 @@ struct nfs_direct_req {
                                rewrite_list;   /* saved nfs_write_data structs */
        struct nfs_open_context *ctx;           /* file open context info */
        struct kiocb *          iocb;           /* controlling i/o request */
-       wait_queue_head_t       wait;           /* wait for i/o completion */
        struct inode *          inode;          /* target file of i/o */
        unsigned long           user_addr;      /* location of user's buffer */
        size_t                  user_count;     /* total bytes to move */
@@ -86,6 +84,7 @@ struct nfs_direct_req {
        int                     outstanding;    /* i/os we're waiting for */
        ssize_t                 count,          /* bytes actually processed */
                                error;          /* any reported error */
+       struct completion       completion;     /* wait for i/o completion */
 
        /* commit state */
        struct nfs_write_data * commit_data;    /* special write_data for commits */
@@ -113,14 +112,25 @@ static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode
  */
 ssize_t nfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, loff_t pos, unsigned long nr_segs)
 {
-       struct dentry *dentry = iocb->ki_filp->f_dentry;
-
        dprintk("NFS: nfs_direct_IO (%s) off/no(%Ld/%lu) EINVAL\n",
-                       dentry->d_name.name, (long long) pos, nr_segs);
+                       iocb->ki_filp->f_dentry->d_name.name,
+                       (long long) pos, nr_segs);
 
        return -EINVAL;
 }
 
+static void nfs_free_user_pages(struct page **pages, int npages, int do_dirty)
+{
+       int i;
+       for (i = 0; i < npages; i++) {
+               struct page *page = pages[i];
+               if (do_dirty && !PageCompound(page))
+                       set_page_dirty_lock(page);
+               page_cache_release(page);
+       }
+       kfree(pages);
+}
+
 static inline int nfs_get_user_pages(int rw, unsigned long user_addr, size_t size, struct page ***pages)
 {
        int result = -ENOMEM;
@@ -138,31 +148,23 @@ static inline int nfs_get_user_pages(int rw, unsigned long user_addr, size_t siz
                                        page_count, (rw == READ), 0,
                                        *pages, NULL);
                up_read(&current->mm->mmap_sem);
-               /*
-                * If we got fewer pages than expected from get_user_pages(),
-                * the user buffer runs off the end of a mapping; return EFAULT.
-                */
-               if (result >= 0 && result < page_count) {
-                       nfs_free_user_pages(*pages, result, 0);
+               if (result != page_count) {
+                       /*
+                        * If we got fewer pages than expected from
+                        * get_user_pages(), the user buffer runs off the
+                        * end of a mapping; return EFAULT.
+                        */
+                       if (result >= 0) {
+                               nfs_free_user_pages(*pages, result, 0);
+                               result = -EFAULT;
+                       } else
+                               kfree(*pages);
                        *pages = NULL;
-                       result = -EFAULT;
                }
        }
        return result;
 }
 
-static void nfs_free_user_pages(struct page **pages, int npages, int do_dirty)
-{
-       int i;
-       for (i = 0; i < npages; i++) {
-               struct page *page = pages[i];
-               if (do_dirty && !PageCompound(page))
-                       set_page_dirty_lock(page);
-               page_cache_release(page);
-       }
-       kfree(pages);
-}
-
 static inline struct nfs_direct_req *nfs_direct_req_alloc(void)
 {
        struct nfs_direct_req *dreq;
@@ -172,7 +174,7 @@ static inline struct nfs_direct_req *nfs_direct_req_alloc(void)
                return NULL;
 
        kref_init(&dreq->kref);
-       init_waitqueue_head(&dreq->wait);
+       init_completion(&dreq->completion);
        INIT_LIST_HEAD(&dreq->list);
        INIT_LIST_HEAD(&dreq->rewrite_list);
        dreq->iocb = NULL;
@@ -206,7 +208,7 @@ static ssize_t nfs_direct_wait(struct nfs_direct_req *dreq)
        if (dreq->iocb)
                goto out;
 
-       result = wait_event_interruptible(dreq->wait, (dreq->outstanding == 0));
+       result = wait_for_completion_interruptible(&dreq->completion);
 
        if (!result)
                result = dreq->error;
@@ -236,8 +238,8 @@ static void nfs_direct_complete(struct nfs_direct_req *dreq)
                if (!res)
                        res = (long) dreq->count;
                aio_complete(dreq->iocb, res, 0);
-       } else
-               wake_up(&dreq->wait);
+       }
+       complete_all(&dreq->completion);
 
        kref_put(&dreq->kref, nfs_direct_req_release);
 }
@@ -365,7 +367,7 @@ static void nfs_direct_read_schedule(struct nfs_direct_req *dreq)
                rpc_execute(&data->task);
                unlock_kernel();
 
-               dfprintk(VFS, "NFS: %4d initiated direct read call (req %s/%Ld, %u bytes @ offset %Lu)\n",
+               dfprintk(VFS, "NFS: %5u initiated direct read call (req %s/%Ld, %zu bytes @ offset %Lu)\n",
                                data->task.tk_pid,
                                inode->i_sb->s_id,
                                (long long)NFS_FILEID(inode),
@@ -465,7 +467,6 @@ static const struct rpc_call_ops nfs_commit_direct_ops = {
 static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq)
 {
        struct nfs_write_data *data = dreq->commit_data;
-       struct rpc_task *task = &data->task;
 
        data->inode = dreq->inode;
        data->cred = dreq->ctx->cred;
@@ -486,7 +487,7 @@ static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq)
        /* Note: task.tk_ops->rpc_release will free dreq->commit_data */
        dreq->commit_data = NULL;
 
-       dprintk("NFS: %5u initiated commit call\n", task->tk_pid);
+       dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid);
 
        lock_kernel();
        rpc_execute(&data->task);
@@ -686,7 +687,7 @@ static void nfs_direct_write_schedule(struct nfs_direct_req *dreq, int sync)
                rpc_execute(&data->task);
                unlock_kernel();
 
-               dfprintk(VFS, "NFS: %4d initiated direct write call (req %s/%Ld, %u bytes @ offset %Lu)\n",
+               dfprintk(VFS, "NFS: %5u initiated direct write call (req %s/%Ld, %zu bytes @ offset %Lu)\n",
                                data->task.tk_pid,
                                inode->i_sb->s_id,
                                (long long)NFS_FILEID(inode),
@@ -788,13 +789,11 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, char __user *buf, size_t count,
        if (retval)
                goto out;
 
-       page_count = nfs_get_user_pages(READ, (unsigned long) buf,
+       retval = nfs_get_user_pages(READ, (unsigned long) buf,
                                                count, &pages);
-       if (page_count < 0) {
-               nfs_free_user_pages(pages, 0, 0);
-               retval = page_count;
+       if (retval < 0)
                goto out;
-       }
+       page_count = retval;
 
        retval = nfs_direct_read(iocb, (unsigned long) buf, count, pos,
                                                pages, page_count);
@@ -862,13 +861,11 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t
        if (retval)
                goto out;
 
-       page_count = nfs_get_user_pages(WRITE, (unsigned long) buf,
+       retval = nfs_get_user_pages(WRITE, (unsigned long) buf,
                                                count, &pages);
-       if (page_count < 0) {
-               nfs_free_user_pages(pages, 0, 0);
-               retval = page_count;
+       if (retval < 0)
                goto out;
-       }
+       page_count = retval;
 
        retval = nfs_direct_write(iocb, (unsigned long) buf, count,
                                        pos, pages, page_count);
@@ -899,7 +896,8 @@ int nfs_init_directcache(void)
 {
        nfs_direct_cachep = kmem_cache_create("nfs_direct_cache",
                                                sizeof(struct nfs_direct_req),
-                                               0, SLAB_RECLAIM_ACCOUNT,
+                                               0, (SLAB_RECLAIM_ACCOUNT|
+                                                       SLAB_MEM_SPREAD),
                                                NULL, NULL);
        if (nfs_direct_cachep == NULL)
                return -ENOMEM;