Merge branch 'x86/cpu' from tip
[cascardo/linux.git] / fs / nfs / direct.c
index 741a92c..c7326c2 100644 (file)
@@ -87,6 +87,7 @@ struct nfs_direct_req {
        int                     mirror_count;
 
        ssize_t                 count,          /* bytes actually processed */
+                               max_count,      /* max expected count */
                                bytes_left,     /* bytes left to be sent */
                                io_start,       /* start of IO */
                                error;          /* any reported error */
@@ -123,6 +124,8 @@ nfs_direct_good_bytes(struct nfs_direct_req *dreq, struct nfs_pgio_header *hdr)
        int i;
        ssize_t count;
 
+       WARN_ON_ONCE(dreq->count >= dreq->max_count);
+
        if (dreq->mirror_count == 1) {
                dreq->mirrors[hdr->pgio_mirror_idx].count += hdr->good_bytes;
                dreq->count += hdr->good_bytes;
@@ -275,7 +278,7 @@ static void nfs_direct_release_pages(struct page **pages, unsigned int npages)
 void nfs_init_cinfo_from_dreq(struct nfs_commit_info *cinfo,
                              struct nfs_direct_req *dreq)
 {
-       cinfo->lock = &dreq->inode->i_lock;
+       cinfo->inode = dreq->inode;
        cinfo->mds = &dreq->mds_cinfo;
        cinfo->ds = &dreq->ds_cinfo;
        cinfo->dreq = dreq;
@@ -350,10 +353,12 @@ static ssize_t nfs_direct_wait(struct nfs_direct_req *dreq)
 
        result = wait_for_completion_killable(&dreq->completion);
 
+       if (!result) {
+               result = dreq->count;
+               WARN_ON_ONCE(dreq->count < 0);
+       }
        if (!result)
                result = dreq->error;
-       if (!result)
-               result = dreq->count;
 
 out:
        return (ssize_t) result;
@@ -383,8 +388,10 @@ static void nfs_direct_complete(struct nfs_direct_req *dreq, bool write)
 
        if (dreq->iocb) {
                long res = (long) dreq->error;
-               if (!res)
+               if (dreq->count != 0) {
                        res = (long) dreq->count;
+                       WARN_ON_ONCE(dreq->count < 0);
+               }
                dreq->iocb->ki_complete(dreq->iocb, res, 0);
        }
 
@@ -591,7 +598,7 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, struct iov_iter *iter)
                goto out_unlock;
 
        dreq->inode = inode;
-       dreq->bytes_left = count;
+       dreq->bytes_left = dreq->max_count = count;
        dreq->io_start = iocb->ki_pos;
        dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp));
        l_ctx = nfs_get_lock_context(dreq->ctx);
@@ -630,13 +637,13 @@ nfs_direct_write_scan_commit_list(struct inode *inode,
                                  struct list_head *list,
                                  struct nfs_commit_info *cinfo)
 {
-       spin_lock(cinfo->lock);
+       spin_lock(&cinfo->inode->i_lock);
 #ifdef CONFIG_NFS_V4_1
        if (cinfo->ds != NULL && cinfo->ds->nwritten != 0)
                NFS_SERVER(inode)->pnfs_curr_ld->recover_commit_reqs(list, cinfo);
 #endif
        nfs_scan_commit_list(&cinfo->mds->list, list, cinfo, 0);
-       spin_unlock(cinfo->lock);
+       spin_unlock(&cinfo->inode->i_lock);
 }
 
 static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
@@ -671,13 +678,13 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
                if (!nfs_pageio_add_request(&desc, req)) {
                        nfs_list_remove_request(req);
                        nfs_list_add_request(req, &failed);
-                       spin_lock(cinfo.lock);
+                       spin_lock(&cinfo.inode->i_lock);
                        dreq->flags = 0;
                        if (desc.pg_error < 0)
                                dreq->error = desc.pg_error;
                        else
                                dreq->error = -EIO;
-                       spin_unlock(cinfo.lock);
+                       spin_unlock(&cinfo.inode->i_lock);
                }
                nfs_release_request(req);
        }
@@ -1023,7 +1030,7 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter)
                goto out_unlock;
 
        dreq->inode = inode;
-       dreq->bytes_left = iov_iter_count(iter);
+       dreq->bytes_left = dreq->max_count = iov_iter_count(iter);
        dreq->io_start = pos;
        dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp));
        l_ctx = nfs_get_lock_context(dreq->ctx);