]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - fs/nfs/pnfs.c
Merge tag 'clk-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux.git] / fs / nfs / pnfs.c
index 7d9a51e6b847c65df159d6632a98ac891370f80f..06cb90e9bc6eccf2ef6628b2cff6cb4f51792900 100644 (file)
@@ -965,7 +965,7 @@ static struct page **nfs4_alloc_pages(size_t size, gfp_t gfp_flags)
        struct page **pages;
        int i;
 
-       pages = kcalloc(size, sizeof(struct page *), gfp_flags);
+       pages = kmalloc_array(size, sizeof(struct page *), gfp_flags);
        if (!pages) {
                dprintk("%s: can't alloc array of %zu pages\n", __func__, size);
                return NULL;
@@ -975,7 +975,7 @@ static struct page **nfs4_alloc_pages(size_t size, gfp_t gfp_flags)
                pages[i] = alloc_page(gfp_flags);
                if (!pages[i]) {
                        dprintk("%s: failed to allocate page\n", __func__);
-                       nfs4_free_pages(pages, size);
+                       nfs4_free_pages(pages, i);
                        return NULL;
                }
        }
@@ -991,6 +991,7 @@ pnfs_alloc_init_layoutget_args(struct inode *ino,
           gfp_t gfp_flags)
 {
        struct nfs_server *server = pnfs_find_server(ino, ctx);
+       size_t max_reply_sz = server->pnfs_curr_ld->max_layoutget_response;
        size_t max_pages = max_response_pages(server);
        struct nfs4_layoutget *lgp;
 
@@ -1000,6 +1001,12 @@ pnfs_alloc_init_layoutget_args(struct inode *ino,
        if (lgp == NULL)
                return NULL;
 
+       if (max_reply_sz) {
+               size_t npages = (max_reply_sz + PAGE_SIZE - 1) >> PAGE_SHIFT;
+               if (npages < max_pages)
+                       max_pages = npages;
+       }
+
        lgp->args.layout.pages = nfs4_alloc_pages(max_pages, gfp_flags);
        if (!lgp->args.layout.pages) {
                kfree(lgp);
@@ -1332,6 +1339,7 @@ bool pnfs_roc(struct inode *ino,
        if (!nfs_have_layout(ino))
                return false;
 retry:
+       rcu_read_lock();
        spin_lock(&ino->i_lock);
        lo = nfsi->layout;
        if (!lo || !pnfs_layout_is_valid(lo) ||
@@ -1342,6 +1350,7 @@ bool pnfs_roc(struct inode *ino,
        pnfs_get_layout_hdr(lo);
        if (test_bit(NFS_LAYOUT_RETURN_LOCK, &lo->plh_flags)) {
                spin_unlock(&ino->i_lock);
+               rcu_read_unlock();
                wait_on_bit(&lo->plh_flags, NFS_LAYOUT_RETURN,
                                TASK_UNINTERRUPTIBLE);
                pnfs_put_layout_hdr(lo);
@@ -1355,7 +1364,7 @@ bool pnfs_roc(struct inode *ino,
                skip_read = true;
        }
 
-       list_for_each_entry(ctx, &nfsi->open_files, list) {
+       list_for_each_entry_rcu(ctx, &nfsi->open_files, list) {
                state = ctx->state;
                if (state == NULL)
                        continue;
@@ -1403,6 +1412,7 @@ bool pnfs_roc(struct inode *ino,
 
 out_noroc:
        spin_unlock(&ino->i_lock);
+       rcu_read_unlock();
        pnfs_layoutcommit_inode(ino, true);
        if (roc) {
                struct pnfs_layoutdriver_type *ld = NFS_SERVER(ino)->pnfs_curr_ld;