|
@@ -3737,9 +3737,10 @@ out:
|
|
|
static void nfs4_write_cached_acl(struct inode *inode, struct page **pages, size_t pgbase, size_t acl_len)
|
|
|
{
|
|
|
struct nfs4_cached_acl *acl;
|
|
|
+ size_t buflen = sizeof(*acl) + acl_len;
|
|
|
|
|
|
- if (pages && acl_len <= PAGE_SIZE) {
|
|
|
- acl = kmalloc(sizeof(*acl) + acl_len, GFP_KERNEL);
|
|
|
+ if (pages && buflen <= PAGE_SIZE) {
|
|
|
+ acl = kmalloc(buflen, GFP_KERNEL);
|
|
|
if (acl == NULL)
|
|
|
goto out;
|
|
|
acl->cached = 1;
|
|
@@ -3819,7 +3820,7 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu
|
|
|
if (ret)
|
|
|
goto out_free;
|
|
|
|
|
|
- acl_len = res.acl_len - res.acl_data_offset;
|
|
|
+ acl_len = res.acl_len;
|
|
|
if (acl_len > args.acl_len)
|
|
|
nfs4_write_cached_acl(inode, NULL, 0, acl_len);
|
|
|
else
|
|
@@ -6223,11 +6224,58 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata)
|
|
|
dprintk("<-- %s\n", __func__);
|
|
|
}
|
|
|
|
|
|
+static size_t max_response_pages(struct nfs_server *server)
|
|
|
+{
|
|
|
+ u32 max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz;
|
|
|
+ return nfs_page_array_len(0, max_resp_sz);
|
|
|
+}
|
|
|
+
|
|
|
+static void nfs4_free_pages(struct page **pages, size_t size)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+
|
|
|
+ if (!pages)
|
|
|
+ return;
|
|
|
+
|
|
|
+ for (i = 0; i < size; i++) {
|
|
|
+ if (!pages[i])
|
|
|
+ break;
|
|
|
+ __free_page(pages[i]);
|
|
|
+ }
|
|
|
+ kfree(pages);
|
|
|
+}
|
|
|
+
|
|
|
+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);
|
|
|
+ if (!pages) {
|
|
|
+ dprintk("%s: can't alloc array of %zu pages\n", __func__, size);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (i = 0; i < size; i++) {
|
|
|
+ pages[i] = alloc_page(gfp_flags);
|
|
|
+ if (!pages[i]) {
|
|
|
+ dprintk("%s: failed to allocate page\n", __func__);
|
|
|
+ nfs4_free_pages(pages, size);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return pages;
|
|
|
+}
|
|
|
+
|
|
|
static void nfs4_layoutget_release(void *calldata)
|
|
|
{
|
|
|
struct nfs4_layoutget *lgp = calldata;
|
|
|
+ struct nfs_server *server = NFS_SERVER(lgp->args.inode);
|
|
|
+ size_t max_pages = max_response_pages(server);
|
|
|
|
|
|
dprintk("--> %s\n", __func__);
|
|
|
+ nfs4_free_pages(lgp->args.layout.pages, max_pages);
|
|
|
put_nfs_open_context(lgp->args.ctx);
|
|
|
kfree(calldata);
|
|
|
dprintk("<-- %s\n", __func__);
|
|
@@ -6239,9 +6287,10 @@ static const struct rpc_call_ops nfs4_layoutget_call_ops = {
|
|
|
.rpc_release = nfs4_layoutget_release,
|
|
|
};
|
|
|
|
|
|
-int nfs4_proc_layoutget(struct nfs4_layoutget *lgp)
|
|
|
+void nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags)
|
|
|
{
|
|
|
struct nfs_server *server = NFS_SERVER(lgp->args.inode);
|
|
|
+ size_t max_pages = max_response_pages(server);
|
|
|
struct rpc_task *task;
|
|
|
struct rpc_message msg = {
|
|
|
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTGET],
|
|
@@ -6259,12 +6308,19 @@ int nfs4_proc_layoutget(struct nfs4_layoutget *lgp)
|
|
|
|
|
|
dprintk("--> %s\n", __func__);
|
|
|
|
|
|
+ lgp->args.layout.pages = nfs4_alloc_pages(max_pages, gfp_flags);
|
|
|
+ if (!lgp->args.layout.pages) {
|
|
|
+ nfs4_layoutget_release(lgp);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ lgp->args.layout.pglen = max_pages * PAGE_SIZE;
|
|
|
+
|
|
|
lgp->res.layoutp = &lgp->args.layout;
|
|
|
lgp->res.seq_res.sr_slot = NULL;
|
|
|
nfs41_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0);
|
|
|
task = rpc_run_task(&task_setup_data);
|
|
|
if (IS_ERR(task))
|
|
|
- return PTR_ERR(task);
|
|
|
+ return;
|
|
|
status = nfs4_wait_for_completion_rpc_task(task);
|
|
|
if (status == 0)
|
|
|
status = task->tk_status;
|
|
@@ -6272,7 +6328,7 @@ int nfs4_proc_layoutget(struct nfs4_layoutget *lgp)
|
|
|
status = pnfs_layout_process(lgp);
|
|
|
rpc_put_task(task);
|
|
|
dprintk("<-- %s status=%d\n", __func__, status);
|
|
|
- return status;
|
|
|
+ return;
|
|
|
}
|
|
|
|
|
|
static void
|
|
@@ -6304,12 +6360,8 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata)
|
|
|
return;
|
|
|
}
|
|
|
spin_lock(&lo->plh_inode->i_lock);
|
|
|
- if (task->tk_status == 0) {
|
|
|
- if (lrp->res.lrs_present) {
|
|
|
- pnfs_set_layout_stateid(lo, &lrp->res.stateid, true);
|
|
|
- } else
|
|
|
- BUG_ON(!list_empty(&lo->plh_segs));
|
|
|
- }
|
|
|
+ if (task->tk_status == 0 && lrp->res.lrs_present)
|
|
|
+ pnfs_set_layout_stateid(lo, &lrp->res.stateid, true);
|
|
|
lo->plh_block_lgets--;
|
|
|
spin_unlock(&lo->plh_inode->i_lock);
|
|
|
dprintk("<-- %s\n", __func__);
|