nfsd4: don't try to encode conflicting owner if low on space
I ran into this corner case in testing: in theory clients can provide state owners up to 1024 bytes long. In the sessions case there might be a risk of this pushing us over the DRC slot size. The conflicting owner isn't really that important, so let's humor a client that provides a small maxresponsize_cached by allowing ourselves to return without the conflicting owner instead of outright failing the operation. Signed-off-by: J. Bruce Fields <bfields@redhat.com>
This commit is contained in:
		
					parent
					
						
							
								f5236013a2
							
						
					
				
			
			
				commit
				
					
						8c7424cff6
					
				
			
		
					 2 changed files with 15 additions and 4 deletions
				
			
		|  | @ -1432,7 +1432,8 @@ out: | |||
| #define op_encode_change_info_maxsz	(5) | ||||
| #define nfs4_fattr_bitmap_maxsz		(4) | ||||
| 
 | ||||
| #define op_encode_lockowner_maxsz	(1 + XDR_QUADLEN(IDMAP_NAMESZ)) | ||||
| /* We'll fall back on returning no lockowner if run out of space: */ | ||||
| #define op_encode_lockowner_maxsz	(0) | ||||
| #define op_encode_lock_denied_maxsz	(8 + op_encode_lockowner_maxsz) | ||||
| 
 | ||||
| #define nfs4_owner_maxsz		(1 + XDR_QUADLEN(IDMAP_NAMESZ)) | ||||
|  |  | |||
|  | @ -2878,9 +2878,20 @@ nfsd4_encode_lock_denied(struct xdr_stream *xdr, struct nfsd4_lock_denied *ld) | |||
| 	struct xdr_netobj *conf = &ld->ld_owner; | ||||
| 	__be32 *p; | ||||
| 
 | ||||
| again: | ||||
| 	p = xdr_reserve_space(xdr, 32 + XDR_LEN(conf->len)); | ||||
| 	if (!p) | ||||
| 	if (!p) { | ||||
| 		/*
 | ||||
| 		 * Don't fail to return the result just because we can't | ||||
| 		 * return the conflicting open: | ||||
| 		 */ | ||||
| 		if (conf->len) { | ||||
| 			conf->len = 0; | ||||
| 			conf->data = NULL; | ||||
| 			goto again; | ||||
| 		} | ||||
| 		return nfserr_resource; | ||||
| 	} | ||||
| 	WRITE64(ld->ld_start); | ||||
| 	WRITE64(ld->ld_length); | ||||
| 	WRITE32(ld->ld_type); | ||||
|  | @ -2888,7 +2899,6 @@ nfsd4_encode_lock_denied(struct xdr_stream *xdr, struct nfsd4_lock_denied *ld) | |||
| 		WRITEMEM(&ld->ld_clientid, 8); | ||||
| 		WRITE32(conf->len); | ||||
| 		WRITEMEM(conf->data, conf->len); | ||||
| 		kfree(conf->data); | ||||
| 	}  else {  /* non - nfsv4 lock in conflict, no clientid nor owner */ | ||||
| 		WRITE64((u64)0); /* clientid */ | ||||
| 		WRITE32(0); /* length of owner name */ | ||||
|  | @ -2905,7 +2915,7 @@ nfsd4_encode_lock(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lo | |||
| 		nfserr = nfsd4_encode_stateid(xdr, &lock->lk_resp_stateid); | ||||
| 	else if (nfserr == nfserr_denied) | ||||
| 		nfserr = nfsd4_encode_lock_denied(xdr, &lock->lk_denied); | ||||
| 
 | ||||
| 	kfree(lock->lk_denied.ld_owner.data); | ||||
| 	return nfserr; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 J. Bruce Fields
				J. Bruce Fields