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

Commit 449bf8d0 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'nfsd-next' of git://linux-nfs.org/~bfields/linux

Pull nfsd changes from Bruce Fields:
 "This includes miscellaneous bugfixes and cleanup and a performance fix
  for write-heavy NFSv4 workloads.

  (The most significant nfsd-relevant change this time is actually in
  the delegation patches that went through Viro, fixing a long-standing
  bug that can cause NFSv4 clients to miss updates made by non-nfs users
  of the filesystem.  Those enable some followup nfsd patches which I
  have queued locally, but those can wait till 3.14)"

* 'nfsd-next' of git://linux-nfs.org/~bfields/linux: (24 commits)
  nfsd: export proper maximum file size to the client
  nfsd4: improve write performance with better sendspace reservations
  svcrpc: remove an unnecessary assignment
  sunrpc: comment typo fix
  Revert "nfsd: remove_stid can be incorporated into nfs4_put_delegation"
  nfsd4: fix discarded security labels on setattr
  NFSD: Add support for NFS v4.2 operation checking
  nfsd4: nfsd_shutdown_net needs state lock
  NFSD: Combine decode operations for v4 and v4.1
  nfsd: -EINVAL on invalid anonuid/gid instead of silent failure
  nfsd: return better errors to exportfs
  nfsd: fh_update should error out in unexpected cases
  nfsd4: need to destroy revoked delegations in destroy_client
  nfsd: no need to unhash_stid before free
  nfsd: remove_stid can be incorporated into nfs4_put_delegation
  nfsd: nfs4_open_delegation needs to remove_stid rather than unhash_stid
  nfsd: nfs4_free_stid
  nfsd: fix Kconfig syntax
  sunrpc: trim off EC bytes in GSSAPI v2 unwrap
  gss_krb5: document that we ignore sequence number
  ...
parents ffd3c026 aea240f4
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -95,7 +95,7 @@ config NFSD_V4_SECURITY_LABEL
	Smack policies on NFSv4 files, say N.
	Smack policies on NFSv4 files, say N.


	WARNING: there is still a chance of backwards-incompatible protocol changes.
	WARNING: there is still a chance of backwards-incompatible protocol changes.
	For now we recommend "Y" only for developers and testers."
	For now we recommend "Y" only for developers and testers.


config NFSD_FAULT_INJECTION
config NFSD_FAULT_INJECTION
	bool "NFS server manual fault injection"
	bool "NFS server manual fault injection"
+20 −4
Original line number Original line Diff line number Diff line
@@ -536,16 +536,12 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
		if (err)
		if (err)
			goto out3;
			goto out3;
		exp.ex_anon_uid= make_kuid(&init_user_ns, an_int);
		exp.ex_anon_uid= make_kuid(&init_user_ns, an_int);
		if (!uid_valid(exp.ex_anon_uid))
			goto out3;


		/* anon gid */
		/* anon gid */
		err = get_int(&mesg, &an_int);
		err = get_int(&mesg, &an_int);
		if (err)
		if (err)
			goto out3;
			goto out3;
		exp.ex_anon_gid= make_kgid(&init_user_ns, an_int);
		exp.ex_anon_gid= make_kgid(&init_user_ns, an_int);
		if (!gid_valid(exp.ex_anon_gid))
			goto out3;


		/* fsid */
		/* fsid */
		err = get_int(&mesg, &an_int);
		err = get_int(&mesg, &an_int);
@@ -583,6 +579,26 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
				   exp.ex_uuid);
				   exp.ex_uuid);
		if (err)
		if (err)
			goto out4;
			goto out4;
		/*
		 * No point caching this if it would immediately expire.
		 * Also, this protects exportfs's dummy export from the
		 * anon_uid/anon_gid checks:
		 */
		if (exp.h.expiry_time < seconds_since_boot())
			goto out4;
		/*
		 * For some reason exportfs has been passing down an
		 * invalid (-1) uid & gid on the "dummy" export which it
		 * uses to test export support.  To make sure exportfs
		 * sees errors from check_export we therefore need to
		 * delay these checks till after check_export:
		 */
		err = -EINVAL;
		if (!uid_valid(exp.ex_anon_uid))
			goto out4;
		if (!gid_valid(exp.ex_anon_gid))
			goto out4;
		err = 0;
	}
	}


	expp = svc_export_lookup(&exp);
	expp = svc_export_lookup(&exp);
+17 −9
Original line number Original line Diff line number Diff line
@@ -402,11 +402,16 @@ static void remove_stid(struct nfs4_stid *s)
	idr_remove(stateids, s->sc_stateid.si_opaque.so_id);
	idr_remove(stateids, s->sc_stateid.si_opaque.so_id);
}
}


static void nfs4_free_stid(struct kmem_cache *slab, struct nfs4_stid *s)
{
	kmem_cache_free(slab, s);
}

void
void
nfs4_put_delegation(struct nfs4_delegation *dp)
nfs4_put_delegation(struct nfs4_delegation *dp)
{
{
	if (atomic_dec_and_test(&dp->dl_count)) {
	if (atomic_dec_and_test(&dp->dl_count)) {
		kmem_cache_free(deleg_slab, dp);
		nfs4_free_stid(deleg_slab, &dp->dl_stid);
		num_delegations--;
		num_delegations--;
	}
	}
}
}
@@ -610,7 +615,7 @@ static void close_generic_stateid(struct nfs4_ol_stateid *stp)
static void free_generic_stateid(struct nfs4_ol_stateid *stp)
static void free_generic_stateid(struct nfs4_ol_stateid *stp)
{
{
	remove_stid(&stp->st_stid);
	remove_stid(&stp->st_stid);
	kmem_cache_free(stateid_slab, stp);
	nfs4_free_stid(stateid_slab, &stp->st_stid);
}
}


static void release_lock_stateid(struct nfs4_ol_stateid *stp)
static void release_lock_stateid(struct nfs4_ol_stateid *stp)
@@ -668,7 +673,6 @@ static void unhash_open_stateid(struct nfs4_ol_stateid *stp)
static void release_open_stateid(struct nfs4_ol_stateid *stp)
static void release_open_stateid(struct nfs4_ol_stateid *stp)
{
{
	unhash_open_stateid(stp);
	unhash_open_stateid(stp);
	unhash_stid(&stp->st_stid);
	free_generic_stateid(stp);
	free_generic_stateid(stp);
}
}


@@ -690,7 +694,6 @@ static void release_last_closed_stateid(struct nfs4_openowner *oo)
	struct nfs4_ol_stateid *s = oo->oo_last_closed_stid;
	struct nfs4_ol_stateid *s = oo->oo_last_closed_stid;


	if (s) {
	if (s) {
		unhash_stid(&s->st_stid);
		free_generic_stateid(s);
		free_generic_stateid(s);
		oo->oo_last_closed_stid = NULL;
		oo->oo_last_closed_stid = NULL;
	}
	}
@@ -1127,6 +1130,11 @@ destroy_client(struct nfs4_client *clp)
		dp = list_entry(reaplist.next, struct nfs4_delegation, dl_recall_lru);
		dp = list_entry(reaplist.next, struct nfs4_delegation, dl_recall_lru);
		destroy_delegation(dp);
		destroy_delegation(dp);
	}
	}
	list_splice_init(&clp->cl_revoked, &reaplist);
	while (!list_empty(&reaplist)) {
		dp = list_entry(reaplist.next, struct nfs4_delegation, dl_recall_lru);
		destroy_revoked_delegation(dp);
	}
	while (!list_empty(&clp->cl_openowners)) {
	while (!list_empty(&clp->cl_openowners)) {
		oo = list_entry(clp->cl_openowners.next, struct nfs4_openowner, oo_perclient);
		oo = list_entry(clp->cl_openowners.next, struct nfs4_openowner, oo_perclient);
		release_openowner(oo);
		release_openowner(oo);
@@ -3154,7 +3162,7 @@ nfs4_open_delegation(struct net *net, struct svc_fh *fh,
	open->op_delegate_type = NFS4_OPEN_DELEGATE_READ;
	open->op_delegate_type = NFS4_OPEN_DELEGATE_READ;
	return;
	return;
out_free:
out_free:
	unhash_stid(&dp->dl_stid);
	remove_stid(&dp->dl_stid);
	nfs4_put_delegation(dp);
	nfs4_put_delegation(dp);
out_no_deleg:
out_no_deleg:
	open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE;
	open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE;
@@ -3995,10 +4003,9 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,


	nfsd4_close_open_stateid(stp);
	nfsd4_close_open_stateid(stp);


	if (cstate->minorversion) {
	if (cstate->minorversion)
		unhash_stid(&stp->st_stid);
		free_generic_stateid(stp);
		free_generic_stateid(stp);
	} else
	else
		oo->oo_last_closed_stid = stp;
		oo->oo_last_closed_stid = stp;


	if (list_empty(&oo->oo_owner.so_stateids)) {
	if (list_empty(&oo->oo_owner.so_stateids)) {
@@ -5119,7 +5126,6 @@ nfs4_state_start(void)
	return ret;
	return ret;
}
}


/* should be called with the state lock held */
void
void
nfs4_state_shutdown_net(struct net *net)
nfs4_state_shutdown_net(struct net *net)
{
{
@@ -5130,6 +5136,7 @@ nfs4_state_shutdown_net(struct net *net)
	cancel_delayed_work_sync(&nn->laundromat_work);
	cancel_delayed_work_sync(&nn->laundromat_work);
	locks_end_grace(&nn->nfsd4_manager);
	locks_end_grace(&nn->nfsd4_manager);


	nfs4_lock_state();
	INIT_LIST_HEAD(&reaplist);
	INIT_LIST_HEAD(&reaplist);
	spin_lock(&recall_lock);
	spin_lock(&recall_lock);
	list_for_each_safe(pos, next, &nn->del_recall_lru) {
	list_for_each_safe(pos, next, &nn->del_recall_lru) {
@@ -5144,6 +5151,7 @@ nfs4_state_shutdown_net(struct net *net)


	nfsd4_client_tracking_exit(net);
	nfsd4_client_tracking_exit(net);
	nfs4_state_destroy_net(net);
	nfs4_state_destroy_net(net);
	nfs4_unlock_state();
}
}


void
void
+74 −58
Original line number Original line Diff line number Diff line
@@ -411,6 +411,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
		label->data = kzalloc(dummy32 + 1, GFP_KERNEL);
		label->data = kzalloc(dummy32 + 1, GFP_KERNEL);
		if (!label->data)
		if (!label->data)
			return nfserr_jukebox;
			return nfserr_jukebox;
		label->len = dummy32;
		defer_free(argp, kfree, label->data);
		defer_free(argp, kfree, label->data);
		memcpy(label->data, buf, dummy32);
		memcpy(label->data, buf, dummy32);
	}
	}
@@ -946,6 +947,9 @@ nfsd4_decode_open_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_open_con
{
{
	DECODE_HEAD;
	DECODE_HEAD;


	if (argp->minorversion >= 1)
		return nfserr_notsupp;

	status = nfsd4_decode_stateid(argp, &open_conf->oc_req_stateid);
	status = nfsd4_decode_stateid(argp, &open_conf->oc_req_stateid);
	if (status)
	if (status)
		return status;
		return status;
@@ -990,6 +994,14 @@ nfsd4_decode_putfh(struct nfsd4_compoundargs *argp, struct nfsd4_putfh *putfh)
	DECODE_TAIL;
	DECODE_TAIL;
}
}


static __be32
nfsd4_decode_putpubfh(struct nfsd4_compoundargs *argp, void *p)
{
	if (argp->minorversion == 0)
		return nfs_ok;
	return nfserr_notsupp;
}

static __be32
static __be32
nfsd4_decode_read(struct nfsd4_compoundargs *argp, struct nfsd4_read *read)
nfsd4_decode_read(struct nfsd4_compoundargs *argp, struct nfsd4_read *read)
{
{
@@ -1061,6 +1073,9 @@ nfsd4_decode_renew(struct nfsd4_compoundargs *argp, clientid_t *clientid)
{
{
	DECODE_HEAD;
	DECODE_HEAD;


	if (argp->minorversion >= 1)
		return nfserr_notsupp;

	READ_BUF(sizeof(clientid_t));
	READ_BUF(sizeof(clientid_t));
	COPYMEM(clientid, sizeof(clientid_t));
	COPYMEM(clientid, sizeof(clientid_t));


@@ -1111,6 +1126,9 @@ nfsd4_decode_setclientid(struct nfsd4_compoundargs *argp, struct nfsd4_setclient
{
{
	DECODE_HEAD;
	DECODE_HEAD;


	if (argp->minorversion >= 1)
		return nfserr_notsupp;

	READ_BUF(NFS4_VERIFIER_SIZE);
	READ_BUF(NFS4_VERIFIER_SIZE);
	COPYMEM(setclientid->se_verf.data, NFS4_VERIFIER_SIZE);
	COPYMEM(setclientid->se_verf.data, NFS4_VERIFIER_SIZE);


@@ -1137,6 +1155,9 @@ nfsd4_decode_setclientid_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_s
{
{
	DECODE_HEAD;
	DECODE_HEAD;


	if (argp->minorversion >= 1)
		return nfserr_notsupp;

	READ_BUF(8 + NFS4_VERIFIER_SIZE);
	READ_BUF(8 + NFS4_VERIFIER_SIZE);
	COPYMEM(&scd_c->sc_clientid, 8);
	COPYMEM(&scd_c->sc_clientid, 8);
	COPYMEM(&scd_c->sc_confirm, NFS4_VERIFIER_SIZE);
	COPYMEM(&scd_c->sc_confirm, NFS4_VERIFIER_SIZE);
@@ -1220,6 +1241,9 @@ nfsd4_decode_release_lockowner(struct nfsd4_compoundargs *argp, struct nfsd4_rel
{
{
	DECODE_HEAD;
	DECODE_HEAD;


	if (argp->minorversion >= 1)
		return nfserr_notsupp;

	READ_BUF(12);
	READ_BUF(12);
	COPYMEM(&rlockowner->rl_clientid, sizeof(clientid_t));
	COPYMEM(&rlockowner->rl_clientid, sizeof(clientid_t));
	READ32(rlockowner->rl_owner.len);
	READ32(rlockowner->rl_owner.len);
@@ -1519,7 +1543,7 @@ static nfsd4_dec nfsd4_dec_ops[] = {
	[OP_OPEN_CONFIRM]	= (nfsd4_dec)nfsd4_decode_open_confirm,
	[OP_OPEN_CONFIRM]	= (nfsd4_dec)nfsd4_decode_open_confirm,
	[OP_OPEN_DOWNGRADE]	= (nfsd4_dec)nfsd4_decode_open_downgrade,
	[OP_OPEN_DOWNGRADE]	= (nfsd4_dec)nfsd4_decode_open_downgrade,
	[OP_PUTFH]		= (nfsd4_dec)nfsd4_decode_putfh,
	[OP_PUTFH]		= (nfsd4_dec)nfsd4_decode_putfh,
	[OP_PUTPUBFH]		= (nfsd4_dec)nfsd4_decode_noop,
	[OP_PUTPUBFH]		= (nfsd4_dec)nfsd4_decode_putpubfh,
	[OP_PUTROOTFH]		= (nfsd4_dec)nfsd4_decode_noop,
	[OP_PUTROOTFH]		= (nfsd4_dec)nfsd4_decode_noop,
	[OP_READ]		= (nfsd4_dec)nfsd4_decode_read,
	[OP_READ]		= (nfsd4_dec)nfsd4_decode_read,
	[OP_READDIR]		= (nfsd4_dec)nfsd4_decode_readdir,
	[OP_READDIR]		= (nfsd4_dec)nfsd4_decode_readdir,
@@ -1536,46 +1560,6 @@ static nfsd4_dec nfsd4_dec_ops[] = {
	[OP_VERIFY]		= (nfsd4_dec)nfsd4_decode_verify,
	[OP_VERIFY]		= (nfsd4_dec)nfsd4_decode_verify,
	[OP_WRITE]		= (nfsd4_dec)nfsd4_decode_write,
	[OP_WRITE]		= (nfsd4_dec)nfsd4_decode_write,
	[OP_RELEASE_LOCKOWNER]	= (nfsd4_dec)nfsd4_decode_release_lockowner,
	[OP_RELEASE_LOCKOWNER]	= (nfsd4_dec)nfsd4_decode_release_lockowner,
};

static nfsd4_dec nfsd41_dec_ops[] = {
	[OP_ACCESS]		= (nfsd4_dec)nfsd4_decode_access,
	[OP_CLOSE]		= (nfsd4_dec)nfsd4_decode_close,
	[OP_COMMIT]		= (nfsd4_dec)nfsd4_decode_commit,
	[OP_CREATE]		= (nfsd4_dec)nfsd4_decode_create,
	[OP_DELEGPURGE]		= (nfsd4_dec)nfsd4_decode_notsupp,
	[OP_DELEGRETURN]	= (nfsd4_dec)nfsd4_decode_delegreturn,
	[OP_GETATTR]		= (nfsd4_dec)nfsd4_decode_getattr,
	[OP_GETFH]		= (nfsd4_dec)nfsd4_decode_noop,
	[OP_LINK]		= (nfsd4_dec)nfsd4_decode_link,
	[OP_LOCK]		= (nfsd4_dec)nfsd4_decode_lock,
	[OP_LOCKT]		= (nfsd4_dec)nfsd4_decode_lockt,
	[OP_LOCKU]		= (nfsd4_dec)nfsd4_decode_locku,
	[OP_LOOKUP]		= (nfsd4_dec)nfsd4_decode_lookup,
	[OP_LOOKUPP]		= (nfsd4_dec)nfsd4_decode_noop,
	[OP_NVERIFY]		= (nfsd4_dec)nfsd4_decode_verify,
	[OP_OPEN]		= (nfsd4_dec)nfsd4_decode_open,
	[OP_OPENATTR]		= (nfsd4_dec)nfsd4_decode_notsupp,
	[OP_OPEN_CONFIRM]	= (nfsd4_dec)nfsd4_decode_notsupp,
	[OP_OPEN_DOWNGRADE]	= (nfsd4_dec)nfsd4_decode_open_downgrade,
	[OP_PUTFH]		= (nfsd4_dec)nfsd4_decode_putfh,
	[OP_PUTPUBFH]		= (nfsd4_dec)nfsd4_decode_notsupp,
	[OP_PUTROOTFH]		= (nfsd4_dec)nfsd4_decode_noop,
	[OP_READ]		= (nfsd4_dec)nfsd4_decode_read,
	[OP_READDIR]		= (nfsd4_dec)nfsd4_decode_readdir,
	[OP_READLINK]		= (nfsd4_dec)nfsd4_decode_noop,
	[OP_REMOVE]		= (nfsd4_dec)nfsd4_decode_remove,
	[OP_RENAME]		= (nfsd4_dec)nfsd4_decode_rename,
	[OP_RENEW]		= (nfsd4_dec)nfsd4_decode_notsupp,
	[OP_RESTOREFH]		= (nfsd4_dec)nfsd4_decode_noop,
	[OP_SAVEFH]		= (nfsd4_dec)nfsd4_decode_noop,
	[OP_SECINFO]		= (nfsd4_dec)nfsd4_decode_secinfo,
	[OP_SETATTR]		= (nfsd4_dec)nfsd4_decode_setattr,
	[OP_SETCLIENTID]	= (nfsd4_dec)nfsd4_decode_notsupp,
	[OP_SETCLIENTID_CONFIRM]= (nfsd4_dec)nfsd4_decode_notsupp,
	[OP_VERIFY]		= (nfsd4_dec)nfsd4_decode_verify,
	[OP_WRITE]		= (nfsd4_dec)nfsd4_decode_write,
	[OP_RELEASE_LOCKOWNER]	= (nfsd4_dec)nfsd4_decode_notsupp,


	/* new operations for NFSv4.1 */
	/* new operations for NFSv4.1 */
	[OP_BACKCHANNEL_CTL]	= (nfsd4_dec)nfsd4_decode_backchannel_ctl,
	[OP_BACKCHANNEL_CTL]	= (nfsd4_dec)nfsd4_decode_backchannel_ctl,
@@ -1599,24 +1583,53 @@ static nfsd4_dec nfsd41_dec_ops[] = {
	[OP_RECLAIM_COMPLETE]	= (nfsd4_dec)nfsd4_decode_reclaim_complete,
	[OP_RECLAIM_COMPLETE]	= (nfsd4_dec)nfsd4_decode_reclaim_complete,
};
};


struct nfsd4_minorversion_ops {
static inline bool
	nfsd4_dec *decoders;
nfsd4_opnum_in_range(struct nfsd4_compoundargs *argp, struct nfsd4_op *op)
	int nops;
{
};
	if (op->opnum < FIRST_NFS4_OP)
		return false;
	else if (argp->minorversion == 0 && op->opnum > LAST_NFS40_OP)
		return false;
	else if (argp->minorversion == 1 && op->opnum > LAST_NFS41_OP)
		return false;
	else if (argp->minorversion == 2 && op->opnum > LAST_NFS42_OP)
		return false;
	return true;
}


static struct nfsd4_minorversion_ops nfsd4_minorversion[] = {
/*
	[0] = { nfsd4_dec_ops, ARRAY_SIZE(nfsd4_dec_ops) },
 * Return a rough estimate of the maximum possible reply size.  Note the
	[1] = { nfsd41_dec_ops, ARRAY_SIZE(nfsd41_dec_ops) },
 * estimate includes rpc headers so is meant to be passed to
	[2] = { nfsd41_dec_ops, ARRAY_SIZE(nfsd41_dec_ops) },
 * svc_reserve, not svc_reserve_auth.
};
 *
 * Also note the current compound encoding permits only one operation to
 * use pages beyond the first one, so the maximum possible length is the
 * maximum over these values, not the sum.
 */
static int nfsd4_max_reply(u32 opnum)
{
	switch (opnum) {
	case OP_READLINK:
	case OP_READDIR:
		/*
		 * Both of these ops take a single page for data and put
		 * the head and tail in another page:
		 */
		return 2 * PAGE_SIZE;
	case OP_READ:
		return INT_MAX;
	default:
		return PAGE_SIZE;
	}
}


static __be32
static __be32
nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
{
{
	DECODE_HEAD;
	DECODE_HEAD;
	struct nfsd4_op *op;
	struct nfsd4_op *op;
	struct nfsd4_minorversion_ops *ops;
	bool cachethis = false;
	bool cachethis = false;
	int max_reply = PAGE_SIZE;
	int i;
	int i;


	READ_BUF(4);
	READ_BUF(4);
@@ -1640,10 +1653,9 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
		}
		}
	}
	}


	if (argp->minorversion >= ARRAY_SIZE(nfsd4_minorversion))
	if (argp->minorversion > NFSD_SUPPORTED_MINOR_VERSION)
		argp->opcnt = 0;
		argp->opcnt = 0;


	ops = &nfsd4_minorversion[argp->minorversion];
	for (i = 0; i < argp->opcnt; i++) {
	for (i = 0; i < argp->opcnt; i++) {
		op = &argp->ops[i];
		op = &argp->ops[i];
		op->replay = NULL;
		op->replay = NULL;
@@ -1651,8 +1663,8 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
		READ_BUF(4);
		READ_BUF(4);
		READ32(op->opnum);
		READ32(op->opnum);


		if (op->opnum >= FIRST_NFS4_OP && op->opnum <= LAST_NFS4_OP)
		if (nfsd4_opnum_in_range(argp, op))
			op->status = ops->decoders[op->opnum](argp, &op->u);
			op->status = nfsd4_dec_ops[op->opnum](argp, &op->u);
		else {
		else {
			op->opnum = OP_ILLEGAL;
			op->opnum = OP_ILLEGAL;
			op->status = nfserr_op_illegal;
			op->status = nfserr_op_illegal;
@@ -1667,10 +1679,14 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
		 * op in the compound wants to be cached:
		 * op in the compound wants to be cached:
		 */
		 */
		cachethis |= nfsd4_cache_this_op(op);
		cachethis |= nfsd4_cache_this_op(op);

		max_reply = max(max_reply, nfsd4_max_reply(op->opnum));
	}
	}
	/* Sessions make the DRC unnecessary: */
	/* Sessions make the DRC unnecessary: */
	if (argp->minorversion)
	if (argp->minorversion)
		cachethis = false;
		cachethis = false;
	if (max_reply != INT_MAX)
		svc_reserve(argp->rqstp, max_reply);
	argp->rqstp->rq_cachetype = cachethis ? RC_REPLBUFF : RC_NOCACHE;
	argp->rqstp->rq_cachetype = cachethis ? RC_REPLBUFF : RC_NOCACHE;


	DECODE_TAIL;
	DECODE_TAIL;
@@ -2375,7 +2391,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
	if (bmval0 & FATTR4_WORD0_MAXFILESIZE) {
	if (bmval0 & FATTR4_WORD0_MAXFILESIZE) {
		if ((buflen -= 8) < 0)
		if ((buflen -= 8) < 0)
			goto out_resource;
			goto out_resource;
		WRITE64(~(u64)0);
		WRITE64(exp->ex_path.mnt->mnt_sb->s_maxbytes);
	}
	}
	if (bmval0 & FATTR4_WORD0_MAXLINK) {
	if (bmval0 & FATTR4_WORD0_MAXLINK) {
		if ((buflen -= 4) < 0)
		if ((buflen -= 4) < 0)
+3 −5
Original line number Original line Diff line number Diff line
@@ -598,22 +598,20 @@ fh_update(struct svc_fh *fhp)
		_fh_update_old(dentry, fhp->fh_export, &fhp->fh_handle);
		_fh_update_old(dentry, fhp->fh_export, &fhp->fh_handle);
	} else {
	} else {
		if (fhp->fh_handle.fh_fileid_type != FILEID_ROOT)
		if (fhp->fh_handle.fh_fileid_type != FILEID_ROOT)
			goto out;
			return 0;


		_fh_update(fhp, fhp->fh_export, dentry);
		_fh_update(fhp, fhp->fh_export, dentry);
		if (fhp->fh_handle.fh_fileid_type == FILEID_INVALID)
		if (fhp->fh_handle.fh_fileid_type == FILEID_INVALID)
			return nfserr_opnotsupp;
			return nfserr_opnotsupp;
	}
	}
out:
	return 0;
	return 0;

out_bad:
out_bad:
	printk(KERN_ERR "fh_update: fh not verified!\n");
	printk(KERN_ERR "fh_update: fh not verified!\n");
	goto out;
	return nfserr_serverfault;
out_negative:
out_negative:
	printk(KERN_ERR "fh_update: %pd2 still negative!\n",
	printk(KERN_ERR "fh_update: %pd2 still negative!\n",
		dentry);
		dentry);
	goto out;
	return nfserr_serverfault;
}
}


/*
/*
Loading