Commit cf70cc5b authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'bugfixes' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6

* 'bugfixes' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6:
  NFSv4.1: Ensure that layoutget uses the correct gfp modes
  NFSv4.1: remove pnfs_layout_hdr from pnfs_destroy_all_layouts tmp_list
  NFSv41: Resend on NFS4ERR_RETRY_UNCACHED_REP
parents 087fbc99 a75b9df9
...@@ -117,6 +117,8 @@ static int filelayout_async_handle_error(struct rpc_task *task, ...@@ -117,6 +117,8 @@ static int filelayout_async_handle_error(struct rpc_task *task,
case -EKEYEXPIRED: case -EKEYEXPIRED:
rpc_delay(task, FILELAYOUT_POLL_RETRY_MAX); rpc_delay(task, FILELAYOUT_POLL_RETRY_MAX);
break; break;
case -NFS4ERR_RETRY_UNCACHED_REP:
break;
default: default:
dprintk("%s DS error. Retry through MDS %d\n", __func__, dprintk("%s DS error. Retry through MDS %d\n", __func__,
task->tk_status); task->tk_status);
...@@ -416,7 +418,8 @@ static int ...@@ -416,7 +418,8 @@ static int
filelayout_check_layout(struct pnfs_layout_hdr *lo, filelayout_check_layout(struct pnfs_layout_hdr *lo,
struct nfs4_filelayout_segment *fl, struct nfs4_filelayout_segment *fl,
struct nfs4_layoutget_res *lgr, struct nfs4_layoutget_res *lgr,
struct nfs4_deviceid *id) struct nfs4_deviceid *id,
gfp_t gfp_flags)
{ {
struct nfs4_file_layout_dsaddr *dsaddr; struct nfs4_file_layout_dsaddr *dsaddr;
int status = -EINVAL; int status = -EINVAL;
...@@ -439,7 +442,7 @@ filelayout_check_layout(struct pnfs_layout_hdr *lo, ...@@ -439,7 +442,7 @@ filelayout_check_layout(struct pnfs_layout_hdr *lo,
/* find and reference the deviceid */ /* find and reference the deviceid */
dsaddr = nfs4_fl_find_get_deviceid(id); dsaddr = nfs4_fl_find_get_deviceid(id);
if (dsaddr == NULL) { if (dsaddr == NULL) {
dsaddr = get_device_info(lo->plh_inode, id); dsaddr = get_device_info(lo->plh_inode, id, gfp_flags);
if (dsaddr == NULL) if (dsaddr == NULL)
goto out; goto out;
} }
...@@ -500,7 +503,8 @@ static int ...@@ -500,7 +503,8 @@ static int
filelayout_decode_layout(struct pnfs_layout_hdr *flo, filelayout_decode_layout(struct pnfs_layout_hdr *flo,
struct nfs4_filelayout_segment *fl, struct nfs4_filelayout_segment *fl,
struct nfs4_layoutget_res *lgr, struct nfs4_layoutget_res *lgr,
struct nfs4_deviceid *id) struct nfs4_deviceid *id,
gfp_t gfp_flags)
{ {
struct xdr_stream stream; struct xdr_stream stream;
struct xdr_buf buf = { struct xdr_buf buf = {
...@@ -516,7 +520,7 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo, ...@@ -516,7 +520,7 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo,
dprintk("%s: set_layout_map Begin\n", __func__); dprintk("%s: set_layout_map Begin\n", __func__);
scratch = alloc_page(GFP_KERNEL); scratch = alloc_page(gfp_flags);
if (!scratch) if (!scratch)
return -ENOMEM; return -ENOMEM;
...@@ -554,13 +558,13 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo, ...@@ -554,13 +558,13 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo,
goto out_err; goto out_err;
fl->fh_array = kzalloc(fl->num_fh * sizeof(struct nfs_fh *), fl->fh_array = kzalloc(fl->num_fh * sizeof(struct nfs_fh *),
GFP_KERNEL); gfp_flags);
if (!fl->fh_array) if (!fl->fh_array)
goto out_err; goto out_err;
for (i = 0; i < fl->num_fh; i++) { for (i = 0; i < fl->num_fh; i++) {
/* Do we want to use a mempool here? */ /* Do we want to use a mempool here? */
fl->fh_array[i] = kmalloc(sizeof(struct nfs_fh), GFP_KERNEL); fl->fh_array[i] = kmalloc(sizeof(struct nfs_fh), gfp_flags);
if (!fl->fh_array[i]) if (!fl->fh_array[i])
goto out_err_free; goto out_err_free;
...@@ -605,19 +609,20 @@ filelayout_free_lseg(struct pnfs_layout_segment *lseg) ...@@ -605,19 +609,20 @@ filelayout_free_lseg(struct pnfs_layout_segment *lseg)
static struct pnfs_layout_segment * static struct pnfs_layout_segment *
filelayout_alloc_lseg(struct pnfs_layout_hdr *layoutid, filelayout_alloc_lseg(struct pnfs_layout_hdr *layoutid,
struct nfs4_layoutget_res *lgr) struct nfs4_layoutget_res *lgr,
gfp_t gfp_flags)
{ {
struct nfs4_filelayout_segment *fl; struct nfs4_filelayout_segment *fl;
int rc; int rc;
struct nfs4_deviceid id; struct nfs4_deviceid id;
dprintk("--> %s\n", __func__); dprintk("--> %s\n", __func__);
fl = kzalloc(sizeof(*fl), GFP_KERNEL); fl = kzalloc(sizeof(*fl), gfp_flags);
if (!fl) if (!fl)
return NULL; return NULL;
rc = filelayout_decode_layout(layoutid, fl, lgr, &id); rc = filelayout_decode_layout(layoutid, fl, lgr, &id, gfp_flags);
if (rc != 0 || filelayout_check_layout(layoutid, fl, lgr, &id)) { if (rc != 0 || filelayout_check_layout(layoutid, fl, lgr, &id, gfp_flags)) {
_filelayout_free_lseg(fl); _filelayout_free_lseg(fl);
return NULL; return NULL;
} }
...@@ -633,7 +638,7 @@ filelayout_alloc_lseg(struct pnfs_layout_hdr *layoutid, ...@@ -633,7 +638,7 @@ filelayout_alloc_lseg(struct pnfs_layout_hdr *layoutid,
int size = (fl->stripe_type == STRIPE_SPARSE) ? int size = (fl->stripe_type == STRIPE_SPARSE) ?
fl->dsaddr->ds_num : fl->dsaddr->stripe_count; fl->dsaddr->ds_num : fl->dsaddr->stripe_count;
fl->commit_buckets = kcalloc(size, sizeof(struct list_head), GFP_KERNEL); fl->commit_buckets = kcalloc(size, sizeof(struct list_head), gfp_flags);
if (!fl->commit_buckets) { if (!fl->commit_buckets) {
filelayout_free_lseg(&fl->generic_hdr); filelayout_free_lseg(&fl->generic_hdr);
return NULL; return NULL;
......
...@@ -104,6 +104,6 @@ extern struct nfs4_file_layout_dsaddr * ...@@ -104,6 +104,6 @@ extern struct nfs4_file_layout_dsaddr *
nfs4_fl_find_get_deviceid(struct nfs4_deviceid *dev_id); nfs4_fl_find_get_deviceid(struct nfs4_deviceid *dev_id);
extern void nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr); extern void nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr);
struct nfs4_file_layout_dsaddr * struct nfs4_file_layout_dsaddr *
get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id); get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id, gfp_t gfp_flags);
#endif /* FS_NFS_NFS4FILELAYOUT_H */ #endif /* FS_NFS_NFS4FILELAYOUT_H */
...@@ -225,11 +225,11 @@ nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr) ...@@ -225,11 +225,11 @@ nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr)
} }
static struct nfs4_pnfs_ds * static struct nfs4_pnfs_ds *
nfs4_pnfs_ds_add(struct inode *inode, u32 ip_addr, u32 port) nfs4_pnfs_ds_add(struct inode *inode, u32 ip_addr, u32 port, gfp_t gfp_flags)
{ {
struct nfs4_pnfs_ds *tmp_ds, *ds; struct nfs4_pnfs_ds *tmp_ds, *ds;
ds = kzalloc(sizeof(*tmp_ds), GFP_KERNEL); ds = kzalloc(sizeof(*tmp_ds), gfp_flags);
if (!ds) if (!ds)
goto out; goto out;
...@@ -261,7 +261,7 @@ nfs4_pnfs_ds_add(struct inode *inode, u32 ip_addr, u32 port) ...@@ -261,7 +261,7 @@ nfs4_pnfs_ds_add(struct inode *inode, u32 ip_addr, u32 port)
* Currently only support ipv4, and one multi-path address. * Currently only support ipv4, and one multi-path address.
*/ */
static struct nfs4_pnfs_ds * static struct nfs4_pnfs_ds *
decode_and_add_ds(struct xdr_stream *streamp, struct inode *inode) decode_and_add_ds(struct xdr_stream *streamp, struct inode *inode, gfp_t gfp_flags)
{ {
struct nfs4_pnfs_ds *ds = NULL; struct nfs4_pnfs_ds *ds = NULL;
char *buf; char *buf;
...@@ -303,7 +303,7 @@ decode_and_add_ds(struct xdr_stream *streamp, struct inode *inode) ...@@ -303,7 +303,7 @@ decode_and_add_ds(struct xdr_stream *streamp, struct inode *inode)
rlen); rlen);
goto out_err; goto out_err;
} }
buf = kmalloc(rlen + 1, GFP_KERNEL); buf = kmalloc(rlen + 1, gfp_flags);
if (!buf) { if (!buf) {
dprintk("%s: Not enough memory\n", __func__); dprintk("%s: Not enough memory\n", __func__);
goto out_err; goto out_err;
...@@ -333,7 +333,7 @@ decode_and_add_ds(struct xdr_stream *streamp, struct inode *inode) ...@@ -333,7 +333,7 @@ decode_and_add_ds(struct xdr_stream *streamp, struct inode *inode)
sscanf(pstr, "-%d-%d", &tmp[0], &tmp[1]); sscanf(pstr, "-%d-%d", &tmp[0], &tmp[1]);
port = htons((tmp[0] << 8) | (tmp[1])); port = htons((tmp[0] << 8) | (tmp[1]));
ds = nfs4_pnfs_ds_add(inode, ip_addr, port); ds = nfs4_pnfs_ds_add(inode, ip_addr, port, gfp_flags);
dprintk("%s: Decoded address and port %s\n", __func__, buf); dprintk("%s: Decoded address and port %s\n", __func__, buf);
out_free: out_free:
kfree(buf); kfree(buf);
...@@ -343,7 +343,7 @@ decode_and_add_ds(struct xdr_stream *streamp, struct inode *inode) ...@@ -343,7 +343,7 @@ decode_and_add_ds(struct xdr_stream *streamp, struct inode *inode)
/* Decode opaque device data and return the result */ /* Decode opaque device data and return the result */
static struct nfs4_file_layout_dsaddr* static struct nfs4_file_layout_dsaddr*
decode_device(struct inode *ino, struct pnfs_device *pdev) decode_device(struct inode *ino, struct pnfs_device *pdev, gfp_t gfp_flags)
{ {
int i; int i;
u32 cnt, num; u32 cnt, num;
...@@ -362,7 +362,7 @@ decode_device(struct inode *ino, struct pnfs_device *pdev) ...@@ -362,7 +362,7 @@ decode_device(struct inode *ino, struct pnfs_device *pdev)
struct page *scratch; struct page *scratch;
/* set up xdr stream */ /* set up xdr stream */
scratch = alloc_page(GFP_KERNEL); scratch = alloc_page(gfp_flags);
if (!scratch) if (!scratch)
goto out_err; goto out_err;
...@@ -384,7 +384,7 @@ decode_device(struct inode *ino, struct pnfs_device *pdev) ...@@ -384,7 +384,7 @@ decode_device(struct inode *ino, struct pnfs_device *pdev)
} }
/* read stripe indices */ /* read stripe indices */
stripe_indices = kcalloc(cnt, sizeof(u8), GFP_KERNEL); stripe_indices = kcalloc(cnt, sizeof(u8), gfp_flags);
if (!stripe_indices) if (!stripe_indices)
goto out_err_free_scratch; goto out_err_free_scratch;
...@@ -423,7 +423,7 @@ decode_device(struct inode *ino, struct pnfs_device *pdev) ...@@ -423,7 +423,7 @@ decode_device(struct inode *ino, struct pnfs_device *pdev)
dsaddr = kzalloc(sizeof(*dsaddr) + dsaddr = kzalloc(sizeof(*dsaddr) +
(sizeof(struct nfs4_pnfs_ds *) * (num - 1)), (sizeof(struct nfs4_pnfs_ds *) * (num - 1)),
GFP_KERNEL); gfp_flags);
if (!dsaddr) if (!dsaddr)
goto out_err_free_stripe_indices; goto out_err_free_stripe_indices;
...@@ -452,7 +452,7 @@ decode_device(struct inode *ino, struct pnfs_device *pdev) ...@@ -452,7 +452,7 @@ decode_device(struct inode *ino, struct pnfs_device *pdev)
for (j = 0; j < mp_count; j++) { for (j = 0; j < mp_count; j++) {
if (j == 0) { if (j == 0) {
dsaddr->ds_list[i] = decode_and_add_ds(&stream, dsaddr->ds_list[i] = decode_and_add_ds(&stream,
ino); ino, gfp_flags);
if (dsaddr->ds_list[i] == NULL) if (dsaddr->ds_list[i] == NULL)
goto out_err_free_deviceid; goto out_err_free_deviceid;
} else { } else {
...@@ -503,12 +503,12 @@ decode_device(struct inode *ino, struct pnfs_device *pdev) ...@@ -503,12 +503,12 @@ decode_device(struct inode *ino, struct pnfs_device *pdev)
* available devices. * available devices.
*/ */
static struct nfs4_file_layout_dsaddr * static struct nfs4_file_layout_dsaddr *
decode_and_add_device(struct inode *inode, struct pnfs_device *dev) decode_and_add_device(struct inode *inode, struct pnfs_device *dev, gfp_t gfp_flags)
{ {
struct nfs4_file_layout_dsaddr *d, *new; struct nfs4_file_layout_dsaddr *d, *new;
long hash; long hash;
new = decode_device(inode, dev); new = decode_device(inode, dev, gfp_flags);
if (!new) { if (!new) {
printk(KERN_WARNING "%s: Could not decode or add device\n", printk(KERN_WARNING "%s: Could not decode or add device\n",
__func__); __func__);
...@@ -537,7 +537,7 @@ decode_and_add_device(struct inode *inode, struct pnfs_device *dev) ...@@ -537,7 +537,7 @@ decode_and_add_device(struct inode *inode, struct pnfs_device *dev)
* of available devices, and return it. * of available devices, and return it.
*/ */
struct nfs4_file_layout_dsaddr * struct nfs4_file_layout_dsaddr *
get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id) get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id, gfp_t gfp_flags)
{ {
struct pnfs_device *pdev = NULL; struct pnfs_device *pdev = NULL;
u32 max_resp_sz; u32 max_resp_sz;
...@@ -556,17 +556,17 @@ get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id) ...@@ -556,17 +556,17 @@ get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id)
dprintk("%s inode %p max_resp_sz %u max_pages %d\n", dprintk("%s inode %p max_resp_sz %u max_pages %d\n",
__func__, inode, max_resp_sz, max_pages); __func__, inode, max_resp_sz, max_pages);
pdev = kzalloc(sizeof(struct pnfs_device), GFP_KERNEL); pdev = kzalloc(sizeof(struct pnfs_device), gfp_flags);
if (pdev == NULL) if (pdev == NULL)
return NULL; return NULL;
pages = kzalloc(max_pages * sizeof(struct page *), GFP_KERNEL); pages = kzalloc(max_pages * sizeof(struct page *), gfp_flags);
if (pages == NULL) { if (pages == NULL) {
kfree(pdev); kfree(pdev);
return NULL; return NULL;
} }
for (i = 0; i < max_pages; i++) { for (i = 0; i < max_pages; i++) {
pages[i] = alloc_page(GFP_KERNEL); pages[i] = alloc_page(gfp_flags);
if (!pages[i]) if (!pages[i])
goto out_free; goto out_free;
} }
...@@ -587,7 +587,7 @@ get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id) ...@@ -587,7 +587,7 @@ get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id)
* Found new device, need to decode it and then add it to the * Found new device, need to decode it and then add it to the
* list of known devices for this mountpoint. * list of known devices for this mountpoint.
*/ */
dsaddr = decode_and_add_device(inode, pdev); dsaddr = decode_and_add_device(inode, pdev, gfp_flags);
out_free: out_free:
for (i = 0; i < max_pages; i++) for (i = 0; i < max_pages; i++)
__free_page(pages[i]); __free_page(pages[i]);
......
...@@ -300,6 +300,7 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc ...@@ -300,6 +300,7 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc
ret = nfs4_delay(server->client, &exception->timeout); ret = nfs4_delay(server->client, &exception->timeout);
if (ret != 0) if (ret != 0)
break; break;
case -NFS4ERR_RETRY_UNCACHED_REP:
case -NFS4ERR_OLD_STATEID: case -NFS4ERR_OLD_STATEID:
exception->retry = 1; exception->retry = 1;
break; break;
...@@ -3695,6 +3696,7 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, ...@@ -3695,6 +3696,7 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
rpc_delay(task, NFS4_POLL_RETRY_MAX); rpc_delay(task, NFS4_POLL_RETRY_MAX);
task->tk_status = 0; task->tk_status = 0;
return -EAGAIN; return -EAGAIN;
case -NFS4ERR_RETRY_UNCACHED_REP:
case -NFS4ERR_OLD_STATEID: case -NFS4ERR_OLD_STATEID:
task->tk_status = 0; task->tk_status = 0;
return -EAGAIN; return -EAGAIN;
...@@ -4844,6 +4846,8 @@ static void nfs4_get_lease_time_done(struct rpc_task *task, void *calldata) ...@@ -4844,6 +4846,8 @@ static void nfs4_get_lease_time_done(struct rpc_task *task, void *calldata)
dprintk("%s Retry: tk_status %d\n", __func__, task->tk_status); dprintk("%s Retry: tk_status %d\n", __func__, task->tk_status);
rpc_delay(task, NFS4_POLL_RETRY_MIN); rpc_delay(task, NFS4_POLL_RETRY_MIN);
task->tk_status = 0; task->tk_status = 0;
/* fall through */
case -NFS4ERR_RETRY_UNCACHED_REP:
nfs_restart_rpc(task, data->clp); nfs_restart_rpc(task, data->clp);
return; return;
} }
...@@ -5479,6 +5483,8 @@ static int nfs41_reclaim_complete_handle_errors(struct rpc_task *task, struct nf ...@@ -5479,6 +5483,8 @@ static int nfs41_reclaim_complete_handle_errors(struct rpc_task *task, struct nf
break; break;
case -NFS4ERR_DELAY: case -NFS4ERR_DELAY:
rpc_delay(task, NFS4_POLL_RETRY_MAX); rpc_delay(task, NFS4_POLL_RETRY_MAX);
/* fall through */
case -NFS4ERR_RETRY_UNCACHED_REP:
return -EAGAIN; return -EAGAIN;
default: default:
nfs4_schedule_lease_recovery(clp); nfs4_schedule_lease_recovery(clp);
......
...@@ -383,6 +383,7 @@ pnfs_destroy_all_layouts(struct nfs_client *clp) ...@@ -383,6 +383,7 @@ pnfs_destroy_all_layouts(struct nfs_client *clp)
plh_layouts); plh_layouts);
dprintk("%s freeing layout for inode %lu\n", __func__, dprintk("%s freeing layout for inode %lu\n", __func__,
lo->plh_inode->i_ino); lo->plh_inode->i_ino);
list_del_init(&lo->plh_layouts);
pnfs_destroy_layout(NFS_I(lo->plh_inode)); pnfs_destroy_layout(NFS_I(lo->plh_inode));
} }
} }
...@@ -466,7 +467,8 @@ pnfs_choose_layoutget_stateid(nfs4_stateid *dst, struct pnfs_layout_hdr *lo, ...@@ -466,7 +467,8 @@ pnfs_choose_layoutget_stateid(nfs4_stateid *dst, struct pnfs_layout_hdr *lo,
static struct pnfs_layout_segment * static struct pnfs_layout_segment *
send_layoutget(struct pnfs_layout_hdr *lo, send_layoutget(struct pnfs_layout_hdr *lo,
struct nfs_open_context *ctx, struct nfs_open_context *ctx,
u32 iomode) u32 iomode,
gfp_t gfp_flags)
{ {
struct inode *ino = lo->plh_inode; struct inode *ino = lo->plh_inode;
struct nfs_server *server = NFS_SERVER(ino); struct nfs_server *server = NFS_SERVER(ino);
...@@ -479,7 +481,7 @@ send_layoutget(struct pnfs_layout_hdr *lo, ...@@ -479,7 +481,7 @@ send_layoutget(struct pnfs_layout_hdr *lo,
dprintk("--> %s\n", __func__); dprintk("--> %s\n", __func__);
BUG_ON(ctx == NULL); BUG_ON(ctx == NULL);
lgp = kzalloc(sizeof(*lgp), GFP_KERNEL); lgp = kzalloc(sizeof(*lgp), gfp_flags);
if (lgp == NULL) if (lgp == NULL)
return NULL; return NULL;
...@@ -487,12 +489,12 @@ send_layoutget(struct pnfs_layout_hdr *lo, ...@@ -487,12 +489,12 @@ send_layoutget(struct pnfs_layout_hdr *lo,
max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz; max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz;
max_pages = max_resp_sz >> PAGE_SHIFT; max_pages = max_resp_sz >> PAGE_SHIFT;
pages = kzalloc(max_pages * sizeof(struct page *), GFP_KERNEL); pages = kzalloc(max_pages * sizeof(struct page *), gfp_flags);
if (!pages) if (!pages)
goto out_err_free; goto out_err_free;
for (i = 0; i < max_pages; i++) { for (i = 0; i < max_pages; i++) {
pages[i] = alloc_page(GFP_KERNEL); pages[i] = alloc_page(gfp_flags);
if (!pages[i]) if (!pages[i])
goto out_err_free; goto out_err_free;
} }
...@@ -508,6 +510,7 @@ send_layoutget(struct pnfs_layout_hdr *lo, ...@@ -508,6 +510,7 @@ send_layoutget(struct pnfs_layout_hdr *lo,
lgp->args.layout.pages = pages; lgp->args.layout.pages = pages;
lgp->args.layout.pglen = max_pages * PAGE_SIZE; lgp->args.layout.pglen = max_pages * PAGE_SIZE;
lgp->lsegpp = &lseg; lgp->lsegpp = &lseg;
lgp->gfp_flags = gfp_flags;
/* Synchronously retrieve layout information from server and /* Synchronously retrieve layout information from server and
* store in lseg. * store in lseg.
...@@ -665,11 +668,11 @@ pnfs_insert_layout(struct pnfs_layout_hdr *lo, ...@@ -665,11 +668,11 @@ pnfs_insert_layout(struct pnfs_layout_hdr *lo,
} }
static struct pnfs_layout_hdr * static struct pnfs_layout_hdr *
alloc_init_layout_hdr(struct inode *ino) alloc_init_layout_hdr(struct inode *ino, gfp_t gfp_flags)
{ {
struct pnfs_layout_hdr *lo; struct pnfs_layout_hdr *lo;
lo = kzalloc(sizeof(struct pnfs_layout_hdr), GFP_KERNEL); lo = kzalloc(sizeof(struct pnfs_layout_hdr), gfp_flags);
if (!lo) if (!lo)
return NULL; return NULL;
atomic_set(&lo->plh_refcount, 1); atomic_set(&lo->plh_refcount, 1);
...@@ -681,7 +684,7 @@ alloc_init_layout_hdr(struct inode *ino) ...@@ -681,7 +684,7 @@ alloc_init_layout_hdr(struct inode *ino)
} }
static struct pnfs_layout_hdr * static struct pnfs_layout_hdr *
pnfs_find_alloc_layout(struct inode *ino) pnfs_find_alloc_layout(struct inode *ino, gfp_t gfp_flags)
{ {
struct nfs_inode *nfsi = NFS_I(ino); struct nfs_inode *nfsi = NFS_I(ino);
struct pnfs_layout_hdr *new = NULL; struct pnfs_layout_hdr *new = NULL;
...@@ -696,7 +699,7 @@ pnfs_find_alloc_layout(struct inode *ino) ...@@ -696,7 +699,7 @@ pnfs_find_alloc_layout(struct inode *ino)
return nfsi->layout; return nfsi->layout;
} }
spin_unlock(&ino->i_lock); spin_unlock(&ino->i_lock);
new = alloc_init_layout_hdr(ino); new = alloc_init_layout_hdr(ino, gfp_flags);
spin_lock(&ino->i_lock); spin_lock(&ino->i_lock);
if (likely(nfsi->layout == NULL)) /* Won the race? */ if (likely(nfsi->layout == NULL)) /* Won the race? */
...@@ -756,7 +759,8 @@ pnfs_find_lseg(struct pnfs_layout_hdr *lo, u32 iomode) ...@@ -756,7 +759,8 @@ pnfs_find_lseg(struct pnfs_layout_hdr *lo, u32 iomode)
struct pnfs_layout_segment * struct pnfs_layout_segment *
pnfs_update_layout(struct inode *ino, pnfs_update_layout(struct inode *ino,
struct nfs_open_context *ctx, struct nfs_open_context *ctx,
enum pnfs_iomode iomode) enum pnfs_iomode iomode,
gfp_t gfp_flags)
{ {
struct nfs_inode *nfsi = NFS_I(ino); struct nfs_inode *nfsi = NFS_I(ino);
struct nfs_client *clp = NFS_SERVER(ino)->nfs_client; struct nfs_client *clp = NFS_SERVER(ino)->nfs_client;
...@@ -767,7 +771,7 @@ pnfs_update_layout(struct inode *ino, ...@@ -767,7 +771,7 @@ pnfs_update_layout(struct inode *ino,
if (!pnfs_enabled_sb(NFS_SERVER(ino))) if (!pnfs_enabled_sb(NFS_SERVER(ino)))
return NULL; return NULL;
spin_lock(&ino->i_lock); spin_lock(&ino->i_lock);
lo = pnfs_find_alloc_layout(ino); lo = pnfs_find_alloc_layout(ino, gfp_flags);
if (lo == NULL) { if (lo == NULL) {
dprintk("%s ERROR: can't get pnfs_layout_hdr\n", __func__); dprintk("%s ERROR: can't get pnfs_layout_hdr\n", __func__);
goto out_unlock; goto out_unlock;
...@@ -807,7 +811,7 @@ pnfs_update_layout(struct inode *ino, ...@@ -807,7 +811,7 @@ pnfs_update_layout(struct inode *ino,
spin_unlock(&clp->cl_lock); spin_unlock(&clp->cl_lock);
} }
lseg = send_layoutget(lo, ctx, iomode); lseg = send_layoutget(lo, ctx, iomode, gfp_flags);
if (!lseg && first) { if (!lseg && first) {
spin_lock(&clp->cl_lock); spin_lock(&clp->cl_lock);
list_del_init(&lo->plh_layouts); list_del_init(&lo->plh_layouts);
...@@ -846,7 +850,7 @@ pnfs_layout_process(struct nfs4_layoutget *lgp) ...@@ -846,7 +850,7 @@ pnfs_layout_process(struct nfs4_layoutget *lgp)
goto out; goto out;
} }
/* Inject layout blob into I/O device driver */ /* Inject layout blob into I/O device driver */
lseg = NFS_SERVER(ino)->pnfs_curr_ld->alloc_lseg(lo, res); lseg = NFS_SERVER(ino)->pnfs_curr_ld->alloc_lseg(lo, res, lgp->gfp_flags);
if (!lseg || IS_ERR(lseg)) { if (!lseg || IS_ERR(lseg)) {
if (!lseg) if (!lseg)
status = -ENOMEM; status = -ENOMEM;
...@@ -899,7 +903,8 @@ static int pnfs_read_pg_test(struct nfs_pageio_descriptor *pgio, ...@@ -899,7 +903,8 @@ static int pnfs_read_pg_test(struct nfs_pageio_descriptor *pgio,
/* This is first coelesce call for a series of nfs_pages */ /* This is first coelesce call for a series of nfs_pages */
pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
prev->wb_context, prev->wb_context,
IOMODE_READ); IOMODE_READ,
GFP_KERNEL);
} }
return NFS_SERVER(pgio->pg_inode)->pnfs_curr_ld->pg_test(pgio, prev, req); return NFS_SERVER(pgio->pg_inode)->pnfs_curr_ld->pg_test(pgio, prev, req);
} }
...@@ -921,7 +926,8 @@ static int pnfs_write_pg_test(struct nfs_pageio_descriptor *pgio, ...@@ -921,7 +926,8 @@ static int pnfs_write_pg_test(struct nfs_pageio_descriptor *pgio,
/* This is first coelesce call for a series of nfs_pages */ /* This is first coelesce call for a series of nfs_pages */
pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
prev->wb_context, prev->wb_context,
IOMODE_RW); IOMODE_RW,
GFP_NOFS);
} }
return NFS_SERVER(pgio->pg_inode)->pnfs_curr_ld->pg_test(pgio, prev, req); return NFS_SERVER(pgio->pg_inode)->pnfs_curr_ld->pg_test(pgio, prev, req);
} }
......
...@@ -70,7 +70,7 @@ struct pnfs_layoutdriver_type { ...@@ -70,7 +70,7 @@ struct pnfs_layoutdriver_type {
const u32 id; const u32 id;
const char *name; const char *name;
struct module *owner; struct module *owner;
struct pnfs_layout_segment * (*alloc_lseg) (struct pnfs_layout_hdr *layoutid, struct nfs4_layoutget_res *lgr); struct pnfs_layout_segment * (*alloc_lseg) (struct pnfs_layout_hdr *layoutid, struct nfs4_layoutget_res *lgr, gfp_t gfp_flags);
void (*free_lseg) (struct pnfs_layout_segment *lseg); void (*free_lseg) (struct pnfs_layout_segment *lseg);
/* test for nfs page cache coalescing */ /* test for nfs page cache coalescing */
...@@ -126,7 +126,7 @@ void get_layout_hdr(struct pnfs_layout_hdr *lo); ...@@ -126,7 +126,7 @@ void get_layout_hdr(struct pnfs_layout_hdr *lo);
void put_lseg(struct pnfs_layout_segment *lseg); void put_lseg(struct pnfs_layout_segment *lseg);
struct pnfs_layout_segment * struct pnfs_layout_segment *
pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx, pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx,
enum pnfs_iomode access_type); enum pnfs_iomode access_type, gfp_t gfp_flags);
void set_pnfs_layoutdriver(struct nfs_server *, u32 id); void set_pnfs_layoutdriver(struct nfs_server *, u32 id);
void unset_pnfs_layoutdriver(struct nfs_server *); void unset_pnfs_layoutdriver(struct nfs_server *);
enum pnfs_try_status pnfs_try_to_write_data(struct nfs_write_data *, enum pnfs_try_status pnfs_try_to_write_data(struct nfs_write_data *,
...@@ -245,7 +245,7 @@ static inline void put_lseg(struct pnfs_layout_segment *lseg) ...@@ -245,7 +245,7 @@ static inline void put_lseg(struct pnfs_layout_segment *lseg)
static inline struct pnfs_layout_segment * static inline struct pnfs_layout_segment *
pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx, pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx,
enum pnfs_iomode access_type) enum pnfs_iomode access_type, gfp_t gfp_flags)
{ {
return NULL; return NULL;
} }
......
...@@ -288,7 +288,7 @@ static int nfs_pagein_multi(struct nfs_pageio_descriptor *desc) ...@@ -288,7 +288,7 @@ static int nfs_pagein_multi(struct nfs_pageio_descriptor *desc)
atomic_set(&req->wb_complete, requests); atomic_set(&req->wb_complete, requests);
BUG_ON(desc->pg_lseg != NULL); BUG_ON(desc->pg_lseg != NULL);
lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, IOMODE_READ); lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, IOMODE_READ, GFP_KERNEL);
ClearPageError(page); ClearPageError(page);
offset = 0; offset = 0;
nbytes = desc->pg_count; nbytes = desc->pg_count;
...@@ -351,7 +351,7 @@ static int nfs_pagein_one(struct nfs_pageio_descriptor *desc) ...@@ -351,7 +351,7 @@ static int nfs_pagein_one(struct nfs_pageio_descriptor *desc)
} }
req = nfs_list_entry(data->pages.next); req = nfs_list_entry(data->pages.next);
if ((!lseg) && list_is_singular(&data->pages)) if ((!lseg) && list_is_singular(&data->pages))
lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, IOMODE_READ); lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, IOMODE_READ, GFP_KERNEL);
ret = nfs_read_rpcsetup(req, data, &nfs_read_full_ops, desc->pg_count, ret = nfs_read_rpcsetup(req, data, &nfs_read_full_ops, desc->pg_count,
0, lseg); 0, lseg);
......
...@@ -939,7 +939,7 @@ static int nfs_flush_multi(struct nfs_pageio_descriptor *desc) ...@@ -939,7 +939,7 @@ static int nfs_flush_multi(struct nfs_pageio_descriptor *desc)
atomic_set(&req->wb_complete, requests); atomic_set(&req->wb_complete, requests);
BUG_ON(desc->pg_lseg); BUG_ON(desc->pg_lseg);
lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, IOMODE_RW); lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, IOMODE_RW, GFP_NOFS);
ClearPageError(page); ClearPageError(page);
offset = 0; offset = 0;
nbytes = desc->pg_count; nbytes = desc->pg_count;
...@@ -1013,7 +1013,7 @@ static int nfs_flush_one(struct nfs_pageio_descriptor *desc) ...@@ -1013,7 +1013,7 @@ static int nfs_flush_one(struct nfs_pageio_descriptor *desc)
} }
req = nfs_list_entry(data->pages.next); req = nfs_list_entry(data->pages.next);
if ((!lseg) && list_is_singular(&data->pages)) if ((!lseg) && list_is_singular(&data->pages))
lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, IOMODE_RW); lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, IOMODE_RW, GFP_NOFS);
if ((desc->pg_ioflags & FLUSH_COND_STABLE) && if ((desc->pg_ioflags & FLUSH_COND_STABLE) &&
(desc->pg_moreio || NFS_I(desc->pg_inode)->ncommit)) (desc->pg_moreio || NFS_I(desc->pg_inode)->ncommit))
......
...@@ -233,6 +233,7 @@ struct nfs4_layoutget { ...@@ -233,6 +233,7 @@ struct nfs4_layoutget {
struct nfs4_layoutget_args args; struct nfs4_layoutget_args args;
struct nfs4_layoutget_res res; struct nfs4_layoutget_res res;
struct pnfs_layout_segment **lsegpp; struct pnfs_layout_segment **lsegpp;
gfp_t gfp_flags;
}; };
struct nfs4_getdeviceinfo_args { struct nfs4_getdeviceinfo_args {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment