Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cf70cc5b authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* '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
Loading
Loading
Loading
Loading
+16 −11
Original line number Diff line number Diff line
@@ -117,6 +117,8 @@ static int filelayout_async_handle_error(struct rpc_task *task,
	case -EKEYEXPIRED:
		rpc_delay(task, FILELAYOUT_POLL_RETRY_MAX);
		break;
	case -NFS4ERR_RETRY_UNCACHED_REP:
		break;
	default:
		dprintk("%s DS error. Retry through MDS %d\n", __func__,
			task->tk_status);
@@ -416,7 +418,8 @@ static int
filelayout_check_layout(struct pnfs_layout_hdr *lo,
			struct nfs4_filelayout_segment *fl,
			struct nfs4_layoutget_res *lgr,
			struct nfs4_deviceid *id)
			struct nfs4_deviceid *id,
			gfp_t gfp_flags)
{
	struct nfs4_file_layout_dsaddr *dsaddr;
	int status = -EINVAL;
@@ -439,7 +442,7 @@ filelayout_check_layout(struct pnfs_layout_hdr *lo,
	/* find and reference the deviceid */
	dsaddr = nfs4_fl_find_get_deviceid(id);
	if (dsaddr == NULL) {
		dsaddr = get_device_info(lo->plh_inode, id);
		dsaddr = get_device_info(lo->plh_inode, id, gfp_flags);
		if (dsaddr == NULL)
			goto out;
	}
@@ -500,7 +503,8 @@ static int
filelayout_decode_layout(struct pnfs_layout_hdr *flo,
			 struct nfs4_filelayout_segment *fl,
			 struct nfs4_layoutget_res *lgr,
			 struct nfs4_deviceid *id)
			 struct nfs4_deviceid *id,
			 gfp_t gfp_flags)
{
	struct xdr_stream stream;
	struct xdr_buf buf = {
@@ -516,7 +520,7 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo,

	dprintk("%s: set_layout_map Begin\n", __func__);

	scratch = alloc_page(GFP_KERNEL);
	scratch = alloc_page(gfp_flags);
	if (!scratch)
		return -ENOMEM;

@@ -554,13 +558,13 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo,
		goto out_err;

	fl->fh_array = kzalloc(fl->num_fh * sizeof(struct nfs_fh *),
			       GFP_KERNEL);
			       gfp_flags);
	if (!fl->fh_array)
		goto out_err;

	for (i = 0; i < fl->num_fh; i++) {
		/* 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])
			goto out_err_free;

@@ -605,19 +609,20 @@ filelayout_free_lseg(struct pnfs_layout_segment *lseg)

static struct pnfs_layout_segment *
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;
	int rc;
	struct nfs4_deviceid id;

	dprintk("--> %s\n", __func__);
	fl = kzalloc(sizeof(*fl), GFP_KERNEL);
	fl = kzalloc(sizeof(*fl), gfp_flags);
	if (!fl)
		return NULL;

	rc = filelayout_decode_layout(layoutid, fl, lgr, &id);
	if (rc != 0 || filelayout_check_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, gfp_flags)) {
		_filelayout_free_lseg(fl);
		return NULL;
	}
@@ -633,7 +638,7 @@ filelayout_alloc_lseg(struct pnfs_layout_hdr *layoutid,
		int size = (fl->stripe_type == STRIPE_SPARSE) ?
			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) {
			filelayout_free_lseg(&fl->generic_hdr);
			return NULL;
+1 −1
Original line number Diff line number Diff line
@@ -104,6 +104,6 @@ extern struct nfs4_file_layout_dsaddr *
nfs4_fl_find_get_deviceid(struct nfs4_deviceid *dev_id);
extern void nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *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 */
+17 −17
Original line number Diff line number Diff line
@@ -225,11 +225,11 @@ nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr)
}

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;

	ds = kzalloc(sizeof(*tmp_ds), GFP_KERNEL);
	ds = kzalloc(sizeof(*tmp_ds), gfp_flags);
	if (!ds)
		goto out;

@@ -261,7 +261,7 @@ out:
 * Currently only support ipv4, and one multi-path address.
 */
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;
	char *buf;
@@ -303,7 +303,7 @@ decode_and_add_ds(struct xdr_stream *streamp, struct inode *inode)
			rlen);
		goto out_err;
	}
	buf = kmalloc(rlen + 1, GFP_KERNEL);
	buf = kmalloc(rlen + 1, gfp_flags);
	if (!buf) {
		dprintk("%s: Not enough memory\n", __func__);
		goto out_err;
@@ -333,7 +333,7 @@ decode_and_add_ds(struct xdr_stream *streamp, struct inode *inode)
	sscanf(pstr, "-%d-%d", &tmp[0], &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);
out_free:
	kfree(buf);
@@ -343,7 +343,7 @@ out_err:

/* Decode opaque device data and return the result */
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;
	u32 cnt, num;
@@ -362,7 +362,7 @@ decode_device(struct inode *ino, struct pnfs_device *pdev)
	struct page *scratch;

	/* set up xdr stream */
	scratch = alloc_page(GFP_KERNEL);
	scratch = alloc_page(gfp_flags);
	if (!scratch)
		goto out_err;

@@ -384,7 +384,7 @@ decode_device(struct inode *ino, struct pnfs_device *pdev)
	}

	/* read stripe indices */
	stripe_indices = kcalloc(cnt, sizeof(u8), GFP_KERNEL);
	stripe_indices = kcalloc(cnt, sizeof(u8), gfp_flags);
	if (!stripe_indices)
		goto out_err_free_scratch;

@@ -423,7 +423,7 @@ decode_device(struct inode *ino, struct pnfs_device *pdev)

	dsaddr = kzalloc(sizeof(*dsaddr) +
			(sizeof(struct nfs4_pnfs_ds *) * (num - 1)),
			GFP_KERNEL);
			gfp_flags);
	if (!dsaddr)
		goto out_err_free_stripe_indices;

@@ -452,7 +452,7 @@ decode_device(struct inode *ino, struct pnfs_device *pdev)
		for (j = 0; j < mp_count; j++) {
			if (j == 0) {
				dsaddr->ds_list[i] = decode_and_add_ds(&stream,
					ino);
					ino, gfp_flags);
				if (dsaddr->ds_list[i] == NULL)
					goto out_err_free_deviceid;
			} else {
@@ -503,12 +503,12 @@ out_err:
 * available devices.
 */
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;
	long hash;

	new = decode_device(inode, dev);
	new = decode_device(inode, dev, gfp_flags);
	if (!new) {
		printk(KERN_WARNING "%s: Could not decode or add device\n",
			__func__);
@@ -537,7 +537,7 @@ decode_and_add_device(struct inode *inode, struct pnfs_device *dev)
 * of available devices, and return it.
 */
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;
	u32 max_resp_sz;
@@ -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",
		__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)
		return NULL;

	pages = kzalloc(max_pages * sizeof(struct page *), GFP_KERNEL);
	pages = kzalloc(max_pages * sizeof(struct page *), gfp_flags);
	if (pages == NULL) {
		kfree(pdev);
		return NULL;
	}
	for (i = 0; i < max_pages; i++) {
		pages[i] = alloc_page(GFP_KERNEL);
		pages[i] = alloc_page(gfp_flags);
		if (!pages[i])
			goto out_free;
	}
@@ -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
	 * 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:
	for (i = 0; i < max_pages; i++)
		__free_page(pages[i]);
+6 −0
Original line number Diff line number Diff line
@@ -300,6 +300,7 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc
			ret = nfs4_delay(server->client, &exception->timeout);
			if (ret != 0)
				break;
		case -NFS4ERR_RETRY_UNCACHED_REP:
		case -NFS4ERR_OLD_STATEID:
			exception->retry = 1;
			break;
@@ -3695,6 +3696,7 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
			rpc_delay(task, NFS4_POLL_RETRY_MAX);
			task->tk_status = 0;
			return -EAGAIN;
		case -NFS4ERR_RETRY_UNCACHED_REP:
		case -NFS4ERR_OLD_STATEID:
			task->tk_status = 0;
			return -EAGAIN;
@@ -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);
		rpc_delay(task, NFS4_POLL_RETRY_MIN);
		task->tk_status = 0;
		/* fall through */
	case -NFS4ERR_RETRY_UNCACHED_REP:
		nfs_restart_rpc(task, data->clp);
		return;
	}
@@ -5479,6 +5483,8 @@ static int nfs41_reclaim_complete_handle_errors(struct rpc_task *task, struct nf
		break;
	case -NFS4ERR_DELAY:
		rpc_delay(task, NFS4_POLL_RETRY_MAX);
		/* fall through */
	case -NFS4ERR_RETRY_UNCACHED_REP:
		return -EAGAIN;
	default:
		nfs4_schedule_lease_recovery(clp);
+20 −14
Original line number Diff line number Diff line
@@ -383,6 +383,7 @@ pnfs_destroy_all_layouts(struct nfs_client *clp)
				plh_layouts);
		dprintk("%s freeing layout for inode %lu\n", __func__,
			lo->plh_inode->i_ino);
		list_del_init(&lo->plh_layouts);
		pnfs_destroy_layout(NFS_I(lo->plh_inode));
	}
}
@@ -466,7 +467,8 @@ pnfs_choose_layoutget_stateid(nfs4_stateid *dst, struct pnfs_layout_hdr *lo,
static struct pnfs_layout_segment *
send_layoutget(struct pnfs_layout_hdr *lo,
	   struct nfs_open_context *ctx,
	   u32 iomode)
	   u32 iomode,
	   gfp_t gfp_flags)
{
	struct inode *ino = lo->plh_inode;
	struct nfs_server *server = NFS_SERVER(ino);
@@ -479,7 +481,7 @@ send_layoutget(struct pnfs_layout_hdr *lo,
	dprintk("--> %s\n", __func__);

	BUG_ON(ctx == NULL);
	lgp = kzalloc(sizeof(*lgp), GFP_KERNEL);
	lgp = kzalloc(sizeof(*lgp), gfp_flags);
	if (lgp == NULL)
		return NULL;

@@ -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_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)
		goto out_err_free;

	for (i = 0; i < max_pages; i++) {
		pages[i] = alloc_page(GFP_KERNEL);
		pages[i] = alloc_page(gfp_flags);
		if (!pages[i])
			goto out_err_free;
	}
@@ -508,6 +510,7 @@ send_layoutget(struct pnfs_layout_hdr *lo,
	lgp->args.layout.pages = pages;
	lgp->args.layout.pglen = max_pages * PAGE_SIZE;
	lgp->lsegpp = &lseg;
	lgp->gfp_flags = gfp_flags;

	/* Synchronously retrieve layout information from server and
	 * store in lseg.
@@ -665,11 +668,11 @@ pnfs_insert_layout(struct pnfs_layout_hdr *lo,
}

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;

	lo = kzalloc(sizeof(struct pnfs_layout_hdr), GFP_KERNEL);
	lo = kzalloc(sizeof(struct pnfs_layout_hdr), gfp_flags);
	if (!lo)
		return NULL;
	atomic_set(&lo->plh_refcount, 1);
@@ -681,7 +684,7 @@ alloc_init_layout_hdr(struct inode *ino)
}

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 pnfs_layout_hdr *new = NULL;
@@ -696,7 +699,7 @@ pnfs_find_alloc_layout(struct inode *ino)
			return nfsi->layout;
	}
	spin_unlock(&ino->i_lock);
	new = alloc_init_layout_hdr(ino);
	new = alloc_init_layout_hdr(ino, gfp_flags);
	spin_lock(&ino->i_lock);

	if (likely(nfsi->layout == NULL))	/* Won the race? */
@@ -756,7 +759,8 @@ pnfs_find_lseg(struct pnfs_layout_hdr *lo, u32 iomode)
struct pnfs_layout_segment *
pnfs_update_layout(struct inode *ino,
		   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_client *clp = NFS_SERVER(ino)->nfs_client;
@@ -767,7 +771,7 @@ pnfs_update_layout(struct inode *ino,
	if (!pnfs_enabled_sb(NFS_SERVER(ino)))
		return NULL;
	spin_lock(&ino->i_lock);
	lo = pnfs_find_alloc_layout(ino);
	lo = pnfs_find_alloc_layout(ino, gfp_flags);
	if (lo == NULL) {
		dprintk("%s ERROR: can't get pnfs_layout_hdr\n", __func__);
		goto out_unlock;
@@ -807,7 +811,7 @@ pnfs_update_layout(struct inode *ino,
		spin_unlock(&clp->cl_lock);
	}

	lseg = send_layoutget(lo, ctx, iomode);
	lseg = send_layoutget(lo, ctx, iomode, gfp_flags);
	if (!lseg && first) {
		spin_lock(&clp->cl_lock);
		list_del_init(&lo->plh_layouts);
@@ -846,7 +850,7 @@ pnfs_layout_process(struct nfs4_layoutget *lgp)
		goto out;
	}
	/* 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)
			status = -ENOMEM;
@@ -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 */
		pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
						   prev->wb_context,
						   IOMODE_READ);
						   IOMODE_READ,
						   GFP_KERNEL);
	}
	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,
		/* This is first coelesce call for a series of nfs_pages */
		pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
						   prev->wb_context,
						   IOMODE_RW);
						   IOMODE_RW,
						   GFP_NOFS);
	}
	return NFS_SERVER(pgio->pg_inode)->pnfs_curr_ld->pg_test(pgio, prev, req);
}
Loading