diff options
| author | Mark Brown <[email protected]> | 2015-10-12 18:09:27 +0100 | 
|---|---|---|
| committer | Mark Brown <[email protected]> | 2015-10-12 18:09:27 +0100 | 
| commit | 79828b4fa835f73cdaf4bffa48696abdcbea9d02 (patch) | |
| tree | 5e0fa7156acb75ba603022bc807df8f2fedb97a8 /fs/nfs/pnfs.c | |
| parent | 721b51fcf91898299d96f4b72cb9434cda29dce6 (diff) | |
| parent | 8c1a9d6323abf0fb1e5dad96cf3f1c783505ea5a (diff) | |
Merge remote-tracking branch 'asoc/fix/rt5645' into asoc-fix-rt5645
Diffstat (limited to 'fs/nfs/pnfs.c')
| -rw-r--r-- | fs/nfs/pnfs.c | 282 | 
1 files changed, 169 insertions, 113 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 0ba9a02c9566..ba1246433794 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c @@ -352,7 +352,7 @@ pnfs_layout_need_return(struct pnfs_layout_hdr *lo,  {  	struct pnfs_layout_segment *s; -	if (!test_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags)) +	if (!test_and_clear_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags))  		return false;  	list_for_each_entry(s, &lo->plh_segs, pls_list) @@ -362,6 +362,17 @@ pnfs_layout_need_return(struct pnfs_layout_hdr *lo,  	return true;  } +static bool +pnfs_prepare_layoutreturn(struct pnfs_layout_hdr *lo) +{ +	if (test_and_set_bit(NFS_LAYOUT_RETURN, &lo->plh_flags)) +		return false; +	lo->plh_return_iomode = 0; +	pnfs_get_layout_hdr(lo); +	clear_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE, &lo->plh_flags); +	return true; +} +  static void pnfs_layoutreturn_before_put_lseg(struct pnfs_layout_segment *lseg,  		struct pnfs_layout_hdr *lo, struct inode *inode)  { @@ -372,17 +383,16 @@ static void pnfs_layoutreturn_before_put_lseg(struct pnfs_layout_segment *lseg,  	if (pnfs_layout_need_return(lo, lseg)) {  		nfs4_stateid stateid;  		enum pnfs_iomode iomode; +		bool send;  		stateid = lo->plh_stateid;  		iomode = lo->plh_return_iomode; -		/* decreased in pnfs_send_layoutreturn() */ -		lo->plh_block_lgets++; -		lo->plh_return_iomode = 0; +		send = pnfs_prepare_layoutreturn(lo);  		spin_unlock(&inode->i_lock); -		pnfs_get_layout_hdr(lo); - -		/* Send an async layoutreturn so we dont deadlock */ -		pnfs_send_layoutreturn(lo, stateid, iomode, false); +		if (send) { +			/* Send an async layoutreturn so we dont deadlock */ +			pnfs_send_layoutreturn(lo, stateid, iomode, false); +		}  	} else  		spin_unlock(&inode->i_lock);  } @@ -411,6 +421,10 @@ pnfs_put_lseg(struct pnfs_layout_segment *lseg)  		pnfs_layoutreturn_before_put_lseg(lseg, lo, inode);  	if (atomic_dec_and_lock(&lseg->pls_refcount, &inode->i_lock)) { +		if (test_bit(NFS_LSEG_VALID, &lseg->pls_flags)) { +			spin_unlock(&inode->i_lock); +			return; +		}  		pnfs_get_layout_hdr(lo);  		pnfs_layout_remove_lseg(lo, lseg);  		spin_unlock(&inode->i_lock); @@ -451,6 +465,8 @@ pnfs_put_lseg_locked(struct pnfs_layout_segment *lseg)  		test_bit(NFS_LSEG_VALID, &lseg->pls_flags));  	if (atomic_dec_and_test(&lseg->pls_refcount)) {  		struct pnfs_layout_hdr *lo = lseg->pls_layout; +		if (test_bit(NFS_LSEG_VALID, &lseg->pls_flags)) +			return;  		pnfs_get_layout_hdr(lo);  		pnfs_layout_remove_lseg(lo, lseg);  		pnfs_free_lseg_async(lseg); @@ -800,25 +816,12 @@ pnfs_layout_stateid_blocked(const struct pnfs_layout_hdr *lo,  	return !pnfs_seqid_is_newer(seqid, lo->plh_barrier);  } -static bool -pnfs_layout_returning(const struct pnfs_layout_hdr *lo, -		      struct pnfs_layout_range *range) -{ -	return test_bit(NFS_LAYOUT_RETURN, &lo->plh_flags) && -		(lo->plh_return_iomode == IOMODE_ANY || -		 lo->plh_return_iomode == range->iomode); -} -  /* lget is set to 1 if called from inside send_layoutget call chain */  static bool -pnfs_layoutgets_blocked(const struct pnfs_layout_hdr *lo, -			struct pnfs_layout_range *range, int lget) +pnfs_layoutgets_blocked(const struct pnfs_layout_hdr *lo)  {  	return lo->plh_block_lgets || -		test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags) || -		(list_empty(&lo->plh_segs) && -		 (atomic_read(&lo->plh_outstanding) > lget)) || -		pnfs_layout_returning(lo, range); +		test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags);  }  int @@ -830,7 +833,7 @@ pnfs_choose_layoutget_stateid(nfs4_stateid *dst, struct pnfs_layout_hdr *lo,  	dprintk("--> %s\n", __func__);  	spin_lock(&lo->plh_inode->i_lock); -	if (pnfs_layoutgets_blocked(lo, range, 1)) { +	if (pnfs_layoutgets_blocked(lo)) {  		status = -EAGAIN;  	} else if (!nfs4_valid_open_stateid(open_state)) {  		status = -EBADF; @@ -865,6 +868,7 @@ send_layoutget(struct pnfs_layout_hdr *lo,  	struct nfs_server *server = NFS_SERVER(ino);  	struct nfs4_layoutget *lgp;  	struct pnfs_layout_segment *lseg; +	loff_t i_size;  	dprintk("--> %s\n", __func__); @@ -872,9 +876,17 @@ send_layoutget(struct pnfs_layout_hdr *lo,  	if (lgp == NULL)  		return NULL; +	i_size = i_size_read(ino); +  	lgp->args.minlength = PAGE_CACHE_SIZE;  	if (lgp->args.minlength > range->length)  		lgp->args.minlength = range->length; +	if (range->iomode == IOMODE_READ) { +		if (range->offset >= i_size) +			lgp->args.minlength = 0; +		else if (i_size - range->offset < lgp->args.minlength) +			lgp->args.minlength = i_size - range->offset; +	}  	lgp->args.maxcount = PNFS_LAYOUT_MAXSIZE;  	lgp->args.range = *range;  	lgp->args.type = server->pnfs_curr_ld->id; @@ -924,6 +936,7 @@ void pnfs_clear_layoutreturn_waitbit(struct pnfs_layout_hdr *lo)  	clear_bit_unlock(NFS_LAYOUT_RETURN, &lo->plh_flags);  	smp_mb__after_atomic();  	wake_up_bit(&lo->plh_flags, NFS_LAYOUT_RETURN); +	rpc_wake_up(&NFS_SERVER(lo->plh_inode)->roc_rpcwaitq);  }  static int @@ -938,9 +951,7 @@ pnfs_send_layoutreturn(struct pnfs_layout_hdr *lo, nfs4_stateid stateid,  	if (unlikely(lrp == NULL)) {  		status = -ENOMEM;  		spin_lock(&ino->i_lock); -		lo->plh_block_lgets--;  		pnfs_clear_layoutreturn_waitbit(lo); -		rpc_wake_up(&NFS_SERVER(ino)->roc_rpcwaitq);  		spin_unlock(&ino->i_lock);  		pnfs_put_layout_hdr(lo);  		goto out; @@ -978,6 +989,7 @@ _pnfs_return_layout(struct inode *ino)  	LIST_HEAD(tmp_list);  	nfs4_stateid stateid;  	int status = 0, empty; +	bool send;  	dprintk("NFS: %s for inode %lu\n", __func__, ino->i_ino); @@ -1007,17 +1019,18 @@ _pnfs_return_layout(struct inode *ino)  	/* Don't send a LAYOUTRETURN if list was initially empty */  	if (empty) {  		spin_unlock(&ino->i_lock); -		pnfs_put_layout_hdr(lo);  		dprintk("NFS: %s no layout segments to return\n", __func__); -		goto out; +		goto out_put_layout_hdr;  	}  	set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags); -	lo->plh_block_lgets++; +	send = pnfs_prepare_layoutreturn(lo);  	spin_unlock(&ino->i_lock);  	pnfs_free_lseg_list(&tmp_list); - -	status = pnfs_send_layoutreturn(lo, stateid, IOMODE_ANY, true); +	if (send) +		status = pnfs_send_layoutreturn(lo, stateid, IOMODE_ANY, true); +out_put_layout_hdr: +	pnfs_put_layout_hdr(lo);  out:  	dprintk("<-- %s status: %d\n", __func__, status);  	return status; @@ -1060,15 +1073,14 @@ bool pnfs_roc(struct inode *ino)  	struct pnfs_layout_segment *lseg, *tmp;  	nfs4_stateid stateid;  	LIST_HEAD(tmp_list); -	bool found = false, layoutreturn = false; +	bool found = false, layoutreturn = false, roc = false;  	spin_lock(&ino->i_lock);  	lo = nfsi->layout; -	if (!lo || !test_and_clear_bit(NFS_LAYOUT_ROC, &lo->plh_flags) || -	    test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags)) +	if (!lo || test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags))  		goto out_noroc; -	/* Don't return layout if we hold a delegation */ +	/* no roc if we hold a delegation */  	if (nfs4_check_delegation(ino, FMODE_READ))  		goto out_noroc; @@ -1079,38 +1091,41 @@ bool pnfs_roc(struct inode *ino)  			goto out_noroc;  	} +	stateid = lo->plh_stateid; +	/* always send layoutreturn if being marked so */ +	if (test_and_clear_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE, +				   &lo->plh_flags)) +		layoutreturn = pnfs_prepare_layoutreturn(lo); +  	pnfs_clear_retry_layoutget(lo);  	list_for_each_entry_safe(lseg, tmp, &lo->plh_segs, pls_list) -		if (test_bit(NFS_LSEG_ROC, &lseg->pls_flags)) { +		/* If we are sending layoutreturn, invalidate all valid lsegs */ +		if (layoutreturn || test_bit(NFS_LSEG_ROC, &lseg->pls_flags)) {  			mark_lseg_invalid(lseg, &tmp_list);  			found = true;  		} -	if (!found) -		goto out_noroc; -	lo->plh_block_lgets++; -	pnfs_get_layout_hdr(lo); /* matched in pnfs_roc_release */ -	spin_unlock(&ino->i_lock); -	pnfs_free_lseg_list(&tmp_list); -	pnfs_layoutcommit_inode(ino, true); -	return true; +	/* pnfs_prepare_layoutreturn() grabs lo ref and it will be put +	 * in pnfs_roc_release(). We don't really send a layoutreturn but +	 * still want others to view us like we are sending one! +	 * +	 * If pnfs_prepare_layoutreturn() fails, it means someone else is doing +	 * LAYOUTRETURN, so we proceed like there are no layouts to return. +	 * +	 * ROC in three conditions: +	 * 1. there are ROC lsegs +	 * 2. we don't send layoutreturn +	 * 3. no others are sending layoutreturn +	 */ +	if (found && !layoutreturn && pnfs_prepare_layoutreturn(lo)) +		roc = true;  out_noroc: -	if (lo) { -		stateid = lo->plh_stateid; -		layoutreturn = -			test_and_clear_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE, -					   &lo->plh_flags); -		if (layoutreturn) { -			lo->plh_block_lgets++; -			pnfs_get_layout_hdr(lo); -		} -	}  	spin_unlock(&ino->i_lock); -	if (layoutreturn) { -		pnfs_layoutcommit_inode(ino, true); +	pnfs_free_lseg_list(&tmp_list); +	pnfs_layoutcommit_inode(ino, true); +	if (layoutreturn)  		pnfs_send_layoutreturn(lo, stateid, IOMODE_ANY, true); -	} -	return false; +	return roc;  }  void pnfs_roc_release(struct inode *ino) @@ -1119,7 +1134,7 @@ void pnfs_roc_release(struct inode *ino)  	spin_lock(&ino->i_lock);  	lo = NFS_I(ino)->layout; -	lo->plh_block_lgets--; +	pnfs_clear_layoutreturn_waitbit(lo);  	if (atomic_dec_and_test(&lo->plh_refcount)) {  		pnfs_detach_layout_hdr(lo);  		spin_unlock(&ino->i_lock); @@ -1137,24 +1152,16 @@ void pnfs_roc_set_barrier(struct inode *ino, u32 barrier)  	if (pnfs_seqid_is_newer(barrier, lo->plh_barrier))  		lo->plh_barrier = barrier;  	spin_unlock(&ino->i_lock); +	trace_nfs4_layoutreturn_on_close(ino, 0);  } -bool pnfs_roc_drain(struct inode *ino, u32 *barrier, struct rpc_task *task) +void pnfs_roc_get_barrier(struct inode *ino, u32 *barrier)  {  	struct nfs_inode *nfsi = NFS_I(ino);  	struct pnfs_layout_hdr *lo; -	struct pnfs_layout_segment *lseg; -	nfs4_stateid stateid;  	u32 current_seqid; -	bool found = false, layoutreturn = false;  	spin_lock(&ino->i_lock); -	list_for_each_entry(lseg, &nfsi->layout->plh_segs, pls_list) -		if (test_bit(NFS_LSEG_ROC, &lseg->pls_flags)) { -			rpc_sleep_on(&NFS_SERVER(ino)->roc_rpcwaitq, task, NULL); -			found = true; -			goto out; -		}  	lo = nfsi->layout;  	current_seqid = be32_to_cpu(lo->plh_stateid.seqid); @@ -1162,23 +1169,7 @@ bool pnfs_roc_drain(struct inode *ino, u32 *barrier, struct rpc_task *task)  	 * a barrier, we choose the worst-case barrier.  	 */  	*barrier = current_seqid + atomic_read(&lo->plh_outstanding); -out: -	if (!found) { -		stateid = lo->plh_stateid; -		layoutreturn = -			test_and_clear_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE, -					   &lo->plh_flags); -		if (layoutreturn) { -			lo->plh_block_lgets++; -			pnfs_get_layout_hdr(lo); -		} -	}  	spin_unlock(&ino->i_lock); -	if (layoutreturn) { -		rpc_sleep_on(&NFS_SERVER(ino)->roc_rpcwaitq, task, NULL); -		pnfs_send_layoutreturn(lo, stateid, IOMODE_ANY, false); -	} -	return found;  }  /* @@ -1206,16 +1197,41 @@ pnfs_lseg_range_cmp(const struct pnfs_layout_range *l1,  	return (int)(l1->iomode == IOMODE_READ) - (int)(l2->iomode == IOMODE_READ);  } -static void -pnfs_layout_insert_lseg(struct pnfs_layout_hdr *lo, -		   struct pnfs_layout_segment *lseg) +static bool +pnfs_lseg_range_is_after(const struct pnfs_layout_range *l1, +		const struct pnfs_layout_range *l2) +{ +	return pnfs_lseg_range_cmp(l1, l2) > 0; +} + +static bool +pnfs_lseg_no_merge(struct pnfs_layout_segment *lseg, +		struct pnfs_layout_segment *old)  { -	struct pnfs_layout_segment *lp; +	return false; +} + +void +pnfs_generic_layout_insert_lseg(struct pnfs_layout_hdr *lo, +		   struct pnfs_layout_segment *lseg, +		   bool (*is_after)(const struct pnfs_layout_range *, +			   const struct pnfs_layout_range *), +		   bool (*do_merge)(struct pnfs_layout_segment *, +			   struct pnfs_layout_segment *), +		   struct list_head *free_me) +{ +	struct pnfs_layout_segment *lp, *tmp;  	dprintk("%s:Begin\n", __func__); -	list_for_each_entry(lp, &lo->plh_segs, pls_list) { -		if (pnfs_lseg_range_cmp(&lseg->pls_range, &lp->pls_range) > 0) +	list_for_each_entry_safe(lp, tmp, &lo->plh_segs, pls_list) { +		if (test_bit(NFS_LSEG_VALID, &lp->pls_flags) == 0) +			continue; +		if (do_merge(lseg, lp)) { +			mark_lseg_invalid(lp, free_me); +			continue; +		} +		if (is_after(&lseg->pls_range, &lp->pls_range))  			continue;  		list_add_tail(&lseg->pls_list, &lp->pls_list);  		dprintk("%s: inserted lseg %p " @@ -1237,6 +1253,24 @@ out:  	dprintk("%s:Return\n", __func__);  } +EXPORT_SYMBOL_GPL(pnfs_generic_layout_insert_lseg); + +static void +pnfs_layout_insert_lseg(struct pnfs_layout_hdr *lo, +		   struct pnfs_layout_segment *lseg, +		   struct list_head *free_me) +{ +	struct inode *inode = lo->plh_inode; +	struct pnfs_layoutdriver_type *ld = NFS_SERVER(inode)->pnfs_curr_ld; + +	if (ld->add_lseg != NULL) +		ld->add_lseg(lo, lseg, free_me); +	else +		pnfs_generic_layout_insert_lseg(lo, lseg, +				pnfs_lseg_range_is_after, +				pnfs_lseg_no_merge, +				free_me); +}  static struct pnfs_layout_hdr *  alloc_init_layout_hdr(struct inode *ino, @@ -1329,8 +1363,6 @@ pnfs_find_lseg(struct pnfs_layout_hdr *lo,  			ret = pnfs_get_lseg(lseg);  			break;  		} -		if (lseg->pls_range.offset > range->offset) -			break;  	}  	dprintk("%s:Return lseg %p ref %d\n", @@ -1423,6 +1455,8 @@ static int pnfs_layoutget_retry_bit_wait(struct wait_bit_key *key)  static bool pnfs_prepare_to_retry_layoutget(struct pnfs_layout_hdr *lo)  { +	if (!pnfs_should_retry_layoutget(lo)) +		return false;  	/*  	 * send layoutcommit as it can hold up layoutreturn due to lseg  	 * reference @@ -1469,6 +1503,9 @@ pnfs_update_layout(struct inode *ino,  	if (!pnfs_enabled_sb(NFS_SERVER(ino)))  		goto out; +	if (iomode == IOMODE_READ && i_size_read(ino) == 0) +		goto out; +  	if (pnfs_within_mdsthreshold(ctx, ino, iomode))  		goto out; @@ -1518,8 +1555,7 @@ lookup_again:  	 * Because we free lsegs before sending LAYOUTRETURN, we need to wait  	 * for LAYOUTRETURN even if first is true.  	 */ -	if (!lseg && pnfs_should_retry_layoutget(lo) && -	    test_bit(NFS_LAYOUT_RETURN, &lo->plh_flags)) { +	if (test_bit(NFS_LAYOUT_RETURN, &lo->plh_flags)) {  		spin_unlock(&ino->i_lock);  		dprintk("%s wait for layoutreturn\n", __func__);  		if (pnfs_prepare_to_retry_layoutget(lo)) { @@ -1532,7 +1568,7 @@ lookup_again:  		goto out_put_layout_hdr;  	} -	if (pnfs_layoutgets_blocked(lo, &arg, 0)) +	if (pnfs_layoutgets_blocked(lo))  		goto out_unlock;  	atomic_inc(&lo->plh_outstanding);  	spin_unlock(&ino->i_lock); @@ -1578,6 +1614,26 @@ out_unlock:  }  EXPORT_SYMBOL_GPL(pnfs_update_layout); +static bool +pnfs_sanity_check_layout_range(struct pnfs_layout_range *range) +{ +	switch (range->iomode) { +	case IOMODE_READ: +	case IOMODE_RW: +		break; +	default: +		return false; +	} +	if (range->offset == NFS4_MAX_UINT64) +		return false; +	if (range->length == 0) +		return false; +	if (range->length != NFS4_MAX_UINT64 && +	    range->length > NFS4_MAX_UINT64 - range->offset) +		return false; +	return true; +} +  struct pnfs_layout_segment *  pnfs_layout_process(struct nfs4_layoutget *lgp)  { @@ -1586,7 +1642,10 @@ pnfs_layout_process(struct nfs4_layoutget *lgp)  	struct pnfs_layout_segment *lseg;  	struct inode *ino = lo->plh_inode;  	LIST_HEAD(free_me); -	int status = 0; +	int status = -EINVAL; + +	if (!pnfs_sanity_check_layout_range(&res->range)) +		goto out;  	/* Inject layout blob into I/O device driver */  	lseg = NFS_SERVER(ino)->pnfs_curr_ld->alloc_lseg(lo, res, lgp->gfp_flags); @@ -1604,12 +1663,7 @@ pnfs_layout_process(struct nfs4_layoutget *lgp)  	lseg->pls_range = res->range;  	spin_lock(&ino->i_lock); -	if (test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags)) { -		dprintk("%s forget reply due to recall\n", __func__); -		goto out_forget_reply; -	} - -	if (pnfs_layoutgets_blocked(lo, &lgp->args.range, 1)) { +	if (pnfs_layoutgets_blocked(lo)) {  		dprintk("%s forget reply due to state\n", __func__);  		goto out_forget_reply;  	} @@ -1636,12 +1690,10 @@ pnfs_layout_process(struct nfs4_layoutget *lgp)  	clear_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags);  	pnfs_get_lseg(lseg); -	pnfs_layout_insert_lseg(lo, lseg); +	pnfs_layout_insert_lseg(lo, lseg, &free_me); -	if (res->return_on_close) { +	if (res->return_on_close)  		set_bit(NFS_LSEG_ROC, &lseg->pls_flags); -		set_bit(NFS_LAYOUT_ROC, &lo->plh_flags); -	}  	spin_unlock(&ino->i_lock);  	pnfs_free_lseg_list(&free_me); @@ -1677,6 +1729,8 @@ pnfs_mark_matching_lsegs_return(struct pnfs_layout_hdr *lo,  				lseg->pls_range.length);  			set_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags);  			mark_lseg_invalid(lseg, tmp_list); +			set_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE, +					&lo->plh_flags);  		}  } @@ -1695,7 +1749,6 @@ void pnfs_error_mark_layout_for_return(struct inode *inode,  	spin_lock(&inode->i_lock);  	/* set failure bit so that pnfs path will be retried later */  	pnfs_layout_set_fail_bit(lo, iomode); -	set_bit(NFS_LAYOUT_RETURN, &lo->plh_flags);  	if (lo->plh_return_iomode == 0)  		lo->plh_return_iomode = range.iomode;  	else if (lo->plh_return_iomode != range.iomode) @@ -2207,13 +2260,12 @@ pnfs_layoutcommit_inode(struct inode *inode, bool sync)  	if (ld->prepare_layoutcommit) {  		status = ld->prepare_layoutcommit(&data->args);  		if (status) { +			put_rpccred(data->cred);  			spin_lock(&inode->i_lock);  			set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags);  			if (end_pos > nfsi->layout->plh_lwb)  				nfsi->layout->plh_lwb = end_pos; -			spin_unlock(&inode->i_lock); -			put_rpccred(data->cred); -			goto clear_layoutcommitting; +			goto out_unlock;  		}  	} @@ -2254,7 +2306,7 @@ struct nfs4_threshold *pnfs_mdsthreshold_alloc(void)  #if IS_ENABLED(CONFIG_NFS_V4_2)  int -pnfs_report_layoutstat(struct inode *inode) +pnfs_report_layoutstat(struct inode *inode, gfp_t gfp_flags)  {  	struct pnfs_layoutdriver_type *ld = NFS_SERVER(inode)->pnfs_curr_ld;  	struct nfs_server *server = NFS_SERVER(inode); @@ -2281,7 +2333,7 @@ pnfs_report_layoutstat(struct inode *inode)  	pnfs_get_layout_hdr(hdr);  	spin_unlock(&inode->i_lock); -	data = kzalloc(sizeof(*data), GFP_KERNEL); +	data = kzalloc(sizeof(*data), gfp_flags);  	if (!data) {  		status = -ENOMEM;  		goto out_put; @@ -2311,3 +2363,7 @@ out_put:  }  EXPORT_SYMBOL_GPL(pnfs_report_layoutstat);  #endif + +unsigned int layoutstats_timer; +module_param(layoutstats_timer, uint, 0644); +EXPORT_SYMBOL_GPL(layoutstats_timer);  |