From patchwork Tue Nov 19 00:41:28 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: NeilBrown X-Patchwork-Id: 13879327 Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.223.130]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2096F25634 for ; Tue, 19 Nov 2024 00:49:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.135.223.130 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731977394; cv=none; b=n67BjChOacbXyHJ73wbhrcURMBQok7tBfy8sYTLC3h2OS3zuxeJANKb5jcyCx0HmvS/seM0rdwNtTeVbofFQoP6h3DizCBOEi/X0EuJTZZzdj4R90kBB/56AGJWYrmHdL6m8ssLKrbXRMWurSwgoEkvyDOTctMuCHnrAUP9j2TM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731977394; c=relaxed/simple; bh=csJ5MBHtdtC5By9RenTjcjZequPDTG6EYXXM6xUrpCg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=mhBY+hFOO4omytde58UCNt30+W46cE2whn/je04KHaQJJHJrSF5wH/76Llu4e5u65Em452yTSjDfp4LdDYlWjA38SSNwYcKy3gpau/rcDEG7d+zOSE3UYZM8/AtSWp7/W/Gj4f57lBDkKV5oj2AWcA5qRdQzvFFmyG5UV0+bylk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de; spf=pass smtp.mailfrom=suse.de; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b=Oppi3qKD; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=H+qVWjdb; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b=Oppi3qKD; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=H+qVWjdb; arc=none smtp.client-ip=195.135.223.130 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="Oppi3qKD"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="H+qVWjdb"; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="Oppi3qKD"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="H+qVWjdb" Received: from imap1.dmz-prg2.suse.org (imap1.dmz-prg2.suse.org [IPv6:2a07:de40:b281:104:10:150:64:97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id 55EB121757; Tue, 19 Nov 2024 00:49:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1731977391; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=njM+Luaws02Ib6cYYLYPk7SjhHHsnOngonPOsYqXErc=; b=Oppi3qKD62M9jL0phLG4FHdMa/6GbuvKiONDTfk1g4jof3w1FeDlaiAeJge2mQFVrIu1ua bZWOAz/QCdVgP/bEoT32tADV1NeSt7Dnyl4R7oIaWcpecYjEc/4ydLmx2j4qX6JAMwlhu+ yd92g907fFgI1g2AF/yydn6nmFHw7mk= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1731977391; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=njM+Luaws02Ib6cYYLYPk7SjhHHsnOngonPOsYqXErc=; b=H+qVWjdbaMmPVe5oJPvEXPV9ysguF71oC/nOrxBQwHR3C4UBQVxtJZoXQEj/U2w0hVcSZG I7Kflx3jPJKb5cBA== Authentication-Results: smtp-out1.suse.de; dkim=pass header.d=suse.de header.s=susede2_rsa header.b=Oppi3qKD; dkim=pass header.d=suse.de header.s=susede2_ed25519 header.b=H+qVWjdb DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1731977391; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=njM+Luaws02Ib6cYYLYPk7SjhHHsnOngonPOsYqXErc=; b=Oppi3qKD62M9jL0phLG4FHdMa/6GbuvKiONDTfk1g4jof3w1FeDlaiAeJge2mQFVrIu1ua bZWOAz/QCdVgP/bEoT32tADV1NeSt7Dnyl4R7oIaWcpecYjEc/4ydLmx2j4qX6JAMwlhu+ yd92g907fFgI1g2AF/yydn6nmFHw7mk= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1731977391; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=njM+Luaws02Ib6cYYLYPk7SjhHHsnOngonPOsYqXErc=; b=H+qVWjdbaMmPVe5oJPvEXPV9ysguF71oC/nOrxBQwHR3C4UBQVxtJZoXQEj/U2w0hVcSZG I7Kflx3jPJKb5cBA== Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id 4A3BA1376E; Tue, 19 Nov 2024 00:49:49 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id AZbyAK3gO2eaJgAAD6G6ig (envelope-from ); Tue, 19 Nov 2024 00:49:49 +0000 From: NeilBrown To: Chuck Lever , Jeff Layton Cc: linux-nfs@vger.kernel.org, Olga Kornievskaia , Dai Ngo , Tom Talpey Subject: [PATCH 1/6] nfsd: use an xarray to store v4.1 session slots Date: Tue, 19 Nov 2024 11:41:28 +1100 Message-ID: <20241119004928.3245873-2-neilb@suse.de> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241119004928.3245873-1-neilb@suse.de> References: <20241119004928.3245873-1-neilb@suse.de> Precedence: bulk X-Mailing-List: linux-nfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Rspamd-Queue-Id: 55EB121757 X-Spam-Score: -3.01 X-Rspamd-Action: no action X-Spamd-Result: default: False [-3.01 / 50.00]; BAYES_HAM(-3.00)[100.00%]; MID_CONTAINS_FROM(1.00)[]; NEURAL_HAM_LONG(-1.00)[-1.000]; R_MISSING_CHARSET(0.50)[]; R_DKIM_ALLOW(-0.20)[suse.de:s=susede2_rsa,suse.de:s=susede2_ed25519]; NEURAL_HAM_SHORT(-0.20)[-1.000]; MIME_GOOD(-0.10)[text/plain]; MX_GOOD(-0.01)[]; DKIM_SIGNED(0.00)[suse.de:s=susede2_rsa,suse.de:s=susede2_ed25519]; FUZZY_BLOCKED(0.00)[rspamd.com]; MIME_TRACE(0.00)[0:+]; TO_DN_SOME(0.00)[]; ARC_NA(0.00)[]; RCVD_COUNT_TWO(0.00)[2]; TO_MATCH_ENVRCPT_ALL(0.00)[]; FROM_HAS_DN(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[]; FROM_EQ_ENVFROM(0.00)[]; DKIM_TRACE(0.00)[suse.de:+]; RCPT_COUNT_FIVE(0.00)[6]; RCVD_TLS_ALL(0.00)[]; DBL_BLOCKED_OPENRESOLVER(0.00)[suse.de:dkim,suse.de:mid,suse.de:email] X-Rspamd-Server: rspamd1.dmz-prg2.suse.org X-Spam-Flag: NO X-Spam-Level: Using an xarray to store session slots will make it easier to change the number of active slots based on demand, and removes an unnecessary limit. To achieve good throughput with a high-latency server it can be helpful to have hundreds of concurrent writes, which means hundreds of slots. So increase the limit to 2048 (twice what the Linux client will currently use). Signed-off-by: NeilBrown --- fs/nfsd/nfs4state.c | 28 ++++++++++++++++++---------- fs/nfsd/state.h | 8 +++++--- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index e0daf8b3982c..b48c1423d89b 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -1915,8 +1915,11 @@ free_session_slots(struct nfsd4_session *ses) int i; for (i = 0; i < ses->se_fchannel.maxreqs; i++) { - free_svc_cred(&ses->se_slots[i]->sl_cred); - kfree(ses->se_slots[i]); + struct nfsd4_slot *slot = xa_load(&ses->se_slots, i); + + xa_erase(&ses->se_slots, i); + free_svc_cred(&slot->sl_cred); + kfree(slot); } } @@ -1996,17 +1999,20 @@ static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fattrs, struct nfsd4_session *new; int i; - BUILD_BUG_ON(struct_size(new, se_slots, NFSD_MAX_SLOTS_PER_SESSION) - > PAGE_SIZE); - - new = kzalloc(struct_size(new, se_slots, numslots), GFP_KERNEL); + new = kzalloc(sizeof(*new), GFP_KERNEL); if (!new) return NULL; + xa_init(&new->se_slots); /* allocate each struct nfsd4_slot and data cache in one piece */ for (i = 0; i < numslots; i++) { - new->se_slots[i] = kzalloc(slotsize, GFP_KERNEL); - if (!new->se_slots[i]) + struct nfsd4_slot *slot; + slot = kzalloc(slotsize, GFP_KERNEL); + if (!slot) goto out_free; + if (xa_is_err(xa_store(&new->se_slots, i, slot, GFP_KERNEL))) { + kfree(slot); + goto out_free; + } } memcpy(&new->se_fchannel, fattrs, sizeof(struct nfsd4_channel_attrs)); @@ -2017,7 +2023,8 @@ static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fattrs, return new; out_free: while (i--) - kfree(new->se_slots[i]); + kfree(xa_load(&new->se_slots, i)); + xa_destroy(&new->se_slots); kfree(new); return NULL; } @@ -2124,6 +2131,7 @@ static void nfsd4_del_conns(struct nfsd4_session *s) static void __free_session(struct nfsd4_session *ses) { free_session_slots(ses); + xa_destroy(&ses->se_slots); kfree(ses); } @@ -4292,7 +4300,7 @@ nfsd4_sequence(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, if (seq->slotid >= session->se_fchannel.maxreqs) goto out_put_session; - slot = session->se_slots[seq->slotid]; + slot = xa_load(&session->se_slots, seq->slotid); dprintk("%s: slotid %d\n", __func__, seq->slotid); /* We do not negotiate the number of slots yet, so set the diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index 554041da8593..e97626916a68 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -245,8 +245,10 @@ static inline struct nfs4_delegation *delegstateid(struct nfs4_stid *s) return container_of(s, struct nfs4_delegation, dl_stid); } -/* Maximum number of slots per session. 160 is useful for long haul TCP */ -#define NFSD_MAX_SLOTS_PER_SESSION 160 +/* Maximum number of slots per session. A large number can be need to + * get good throughput on high-latency servers. + */ +#define NFSD_MAX_SLOTS_PER_SESSION 2048 /* Maximum session per slot cache size */ #define NFSD_SLOT_CACHE_SIZE 2048 /* Maximum number of NFSD_SLOT_CACHE_SIZE slots per session */ @@ -345,7 +347,7 @@ struct nfsd4_session { struct nfsd4_cb_sec se_cb_sec; struct list_head se_conns; u32 se_cb_seq_nr[NFSD_BC_SLOT_TABLE_SIZE]; - struct nfsd4_slot *se_slots[]; /* forward channel slots */ + struct xarray se_slots; /* forward channel slots */ }; /* formatted contents of nfs4_sessionid */ From patchwork Tue Nov 19 00:41:29 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: NeilBrown X-Patchwork-Id: 13879328 Received: from smtp-out2.suse.de (smtp-out2.suse.de [195.135.223.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CD02E18E20 for ; Tue, 19 Nov 2024 00:49:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.135.223.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731977400; cv=none; b=tsRxZ9EMmrMpLOnnVMi5H5jjMoTy2hoD0ouutNH7smjizy0gnAvIQjwq2egpoGW6mB34I7XdLFSEqEcjjgnfHMji49piI7AEmlsC6nPO7akpctXYbpX5UiLozLFXo8wjFQTuvIAOFwt+m6j4oyCHrXcKMbU+XPx6Rc+F/OkuLLQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731977400; c=relaxed/simple; bh=NYfxZWwGMxSInK4b0K9r2+YNEM0+yOZ3RW5TQpN5vO4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=gr199+U02HZobo08AVHOuwasGLtWoLU6Ik3NKDfMVfbaV5gE21hK5u6tLYvgPbspGwTm1WQAS+yoAPAfy+/+EU4330PpePQ3Rd1RvQEgS51M4obK7EIG2vCVwqCGE7AqbiM59AtXbNSwvd5yIsNf54OziONzAhJyO9vhLcq0Xbc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de; spf=pass smtp.mailfrom=suse.de; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b=NZvRvIzv; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=CamQHQKN; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b=NZvRvIzv; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=CamQHQKN; arc=none smtp.client-ip=195.135.223.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="NZvRvIzv"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="CamQHQKN"; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="NZvRvIzv"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="CamQHQKN" Received: from imap1.dmz-prg2.suse.org (unknown [10.150.64.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id 0F1F21F365; Tue, 19 Nov 2024 00:49:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1731977397; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=eg2D7vWVz6PPbsD+bVxGyTL21LciB3dWtu7/UQBsUZI=; b=NZvRvIzvPcCx0/fC3EPRVOQ9DbcdXlsGdNb/+9aFy4Qqa6+jmxYZ/hyebeCWsqAlOqp56L iuzpg3IZab5ZM+9elbyy3o5LWcS/iaT0gIMXGpTqzLt3/2kkghcwR5dxh5l8gUAJvkD9A7 SbRHBzSoFyaIxcan4ho3R2ip/GWeULQ= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1731977397; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=eg2D7vWVz6PPbsD+bVxGyTL21LciB3dWtu7/UQBsUZI=; b=CamQHQKNoYDO2Ue4Xo/ar467aFAynfelrLhVqbp8NvmA/EGxAm3YwmgOt0vZM751RObv+u nRY3RSSGYANJ4WDw== Authentication-Results: smtp-out2.suse.de; none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1731977397; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=eg2D7vWVz6PPbsD+bVxGyTL21LciB3dWtu7/UQBsUZI=; b=NZvRvIzvPcCx0/fC3EPRVOQ9DbcdXlsGdNb/+9aFy4Qqa6+jmxYZ/hyebeCWsqAlOqp56L iuzpg3IZab5ZM+9elbyy3o5LWcS/iaT0gIMXGpTqzLt3/2kkghcwR5dxh5l8gUAJvkD9A7 SbRHBzSoFyaIxcan4ho3R2ip/GWeULQ= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1731977397; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=eg2D7vWVz6PPbsD+bVxGyTL21LciB3dWtu7/UQBsUZI=; b=CamQHQKNoYDO2Ue4Xo/ar467aFAynfelrLhVqbp8NvmA/EGxAm3YwmgOt0vZM751RObv+u nRY3RSSGYANJ4WDw== Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id BC55B1376E; Tue, 19 Nov 2024 00:49:54 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id RvoiHbLgO2ejJgAAD6G6ig (envelope-from ); Tue, 19 Nov 2024 00:49:54 +0000 From: NeilBrown To: Chuck Lever , Jeff Layton Cc: linux-nfs@vger.kernel.org, Olga Kornievskaia , Dai Ngo , Tom Talpey Subject: [PATCH 2/6] nfsd: remove artificial limits on the session-based DRC Date: Tue, 19 Nov 2024 11:41:29 +1100 Message-ID: <20241119004928.3245873-3-neilb@suse.de> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241119004928.3245873-1-neilb@suse.de> References: <20241119004928.3245873-1-neilb@suse.de> Precedence: bulk X-Mailing-List: linux-nfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Spam-Level: X-Spamd-Result: default: False [-2.80 / 50.00]; BAYES_HAM(-3.00)[100.00%]; MID_CONTAINS_FROM(1.00)[]; NEURAL_HAM_LONG(-1.00)[-1.000]; R_MISSING_CHARSET(0.50)[]; NEURAL_HAM_SHORT(-0.20)[-1.000]; MIME_GOOD(-0.10)[text/plain]; DKIM_SIGNED(0.00)[suse.de:s=susede2_rsa,suse.de:s=susede2_ed25519]; TO_MATCH_ENVRCPT_ALL(0.00)[]; TO_DN_SOME(0.00)[]; FUZZY_BLOCKED(0.00)[rspamd.com]; MIME_TRACE(0.00)[0:+]; ARC_NA(0.00)[]; RCVD_TLS_ALL(0.00)[]; R_RATELIMIT(0.00)[from(RLewrxuus8mos16izbn)]; FROM_HAS_DN(0.00)[]; RCPT_COUNT_FIVE(0.00)[6]; FROM_EQ_ENVFROM(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[]; RCVD_COUNT_TWO(0.00)[2]; DBL_BLOCKED_OPENRESOLVER(0.00)[suse.de:email,suse.de:mid] X-Spam-Score: -2.80 X-Spam-Flag: NO Rather than guessing how much space it might be safe to use for the DRC, simply try allocating slots and be prepared to accept failure. The first slot for each session is allocated with GFP_KERNEL which is unlikely to fail. Subsequent slots are allocated with the addition of __GFP_NORETRY which is expected to fail if there isn't much free memory. This is probably too aggressive but clears the way for adding a shrinker interface to free extra slots when memory is tight. Signed-off-by: NeilBrown --- fs/nfsd/nfs4state.c | 91 +++++++-------------------------------------- fs/nfsd/nfsd.h | 3 -- fs/nfsd/nfssvc.c | 32 ---------------- 3 files changed, 14 insertions(+), 112 deletions(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index b48c1423d89b..3889ba1c653f 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -1938,65 +1938,13 @@ static inline u32 slot_bytes(struct nfsd4_channel_attrs *ca) return size + sizeof(struct nfsd4_slot); } -/* - * XXX: If we run out of reserved DRC memory we could (up to a point) - * re-negotiate active sessions and reduce their slot usage to make - * room for new connections. For now we just fail the create session. - */ -static u32 nfsd4_get_drc_mem(struct nfsd4_channel_attrs *ca, struct nfsd_net *nn) -{ - u32 slotsize = slot_bytes(ca); - u32 num = ca->maxreqs; - unsigned long avail, total_avail; - unsigned int scale_factor; - - spin_lock(&nfsd_drc_lock); - if (nfsd_drc_max_mem > nfsd_drc_mem_used) - total_avail = nfsd_drc_max_mem - nfsd_drc_mem_used; - else - /* We have handed out more space than we chose in - * set_max_drc() to allow. That isn't really a - * problem as long as that doesn't make us think we - * have lots more due to integer overflow. - */ - total_avail = 0; - avail = min((unsigned long)NFSD_MAX_MEM_PER_SESSION, total_avail); - /* - * Never use more than a fraction of the remaining memory, - * unless it's the only way to give this client a slot. - * The chosen fraction is either 1/8 or 1/number of threads, - * whichever is smaller. This ensures there are adequate - * slots to support multiple clients per thread. - * Give the client one slot even if that would require - * over-allocation--it is better than failure. - */ - scale_factor = max_t(unsigned int, 8, nn->nfsd_serv->sv_nrthreads); - - avail = clamp_t(unsigned long, avail, slotsize, - total_avail/scale_factor); - num = min_t(int, num, avail / slotsize); - num = max_t(int, num, 1); - nfsd_drc_mem_used += num * slotsize; - spin_unlock(&nfsd_drc_lock); - - return num; -} - -static void nfsd4_put_drc_mem(struct nfsd4_channel_attrs *ca) -{ - int slotsize = slot_bytes(ca); - - spin_lock(&nfsd_drc_lock); - nfsd_drc_mem_used -= slotsize * ca->maxreqs; - spin_unlock(&nfsd_drc_lock); -} - static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fattrs, struct nfsd4_channel_attrs *battrs) { int numslots = fattrs->maxreqs; int slotsize = slot_bytes(fattrs); struct nfsd4_session *new; + struct nfsd4_slot *slot; int i; new = kzalloc(sizeof(*new), GFP_KERNEL); @@ -2004,17 +1952,20 @@ static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fattrs, return NULL; xa_init(&new->se_slots); /* allocate each struct nfsd4_slot and data cache in one piece */ - for (i = 0; i < numslots; i++) { - struct nfsd4_slot *slot; - slot = kzalloc(slotsize, GFP_KERNEL); + slot = kzalloc(slotsize, GFP_KERNEL); + if (!slot || xa_is_err(xa_store(&new->se_slots, 0, slot, GFP_KERNEL))) + goto out_free; + + for (i = 1; i < numslots; i++) { + slot = kzalloc(slotsize, GFP_KERNEL | __GFP_NORETRY); if (!slot) - goto out_free; + break; if (xa_is_err(xa_store(&new->se_slots, i, slot, GFP_KERNEL))) { kfree(slot); - goto out_free; + break; } } - + fattrs->maxreqs = i; memcpy(&new->se_fchannel, fattrs, sizeof(struct nfsd4_channel_attrs)); new->se_cb_slot_avail = ~0U; new->se_cb_highest_slot = min(battrs->maxreqs - 1, @@ -2022,8 +1973,7 @@ static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fattrs, spin_lock_init(&new->se_lock); return new; out_free: - while (i--) - kfree(xa_load(&new->se_slots, i)); + kfree(slot); xa_destroy(&new->se_slots); kfree(new); return NULL; @@ -2138,7 +2088,6 @@ static void __free_session(struct nfsd4_session *ses) static void free_session(struct nfsd4_session *ses) { nfsd4_del_conns(ses); - nfsd4_put_drc_mem(&ses->se_fchannel); __free_session(ses); } @@ -3800,17 +3749,6 @@ static __be32 check_forechannel_attrs(struct nfsd4_channel_attrs *ca, struct nfs ca->maxresp_cached = min_t(u32, ca->maxresp_cached, NFSD_SLOT_CACHE_SIZE + NFSD_MIN_HDR_SEQ_SZ); ca->maxreqs = min_t(u32, ca->maxreqs, NFSD_MAX_SLOTS_PER_SESSION); - /* - * Note decreasing slot size below client's request may make it - * difficult for client to function correctly, whereas - * decreasing the number of slots will (just?) affect - * performance. When short on memory we therefore prefer to - * decrease number of slots instead of their size. Clients that - * request larger slots than they need will get poor results: - * Note that we always allow at least one slot, because our - * accounting is soft and provides no guarantees either way. - */ - ca->maxreqs = nfsd4_get_drc_mem(ca, nn); return nfs_ok; } @@ -3888,11 +3826,11 @@ nfsd4_create_session(struct svc_rqst *rqstp, return status; status = check_backchannel_attrs(&cr_ses->back_channel); if (status) - goto out_release_drc_mem; + goto out_err; status = nfserr_jukebox; new = alloc_session(&cr_ses->fore_channel, &cr_ses->back_channel); if (!new) - goto out_release_drc_mem; + goto out_err; conn = alloc_conn_from_crses(rqstp, cr_ses); if (!conn) goto out_free_session; @@ -4001,8 +3939,7 @@ nfsd4_create_session(struct svc_rqst *rqstp, free_conn(conn); out_free_session: __free_session(new); -out_release_drc_mem: - nfsd4_put_drc_mem(&cr_ses->fore_channel); +out_err: return status; } diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h index f007699aa397..e2997f0ffbc5 100644 --- a/fs/nfsd/nfsd.h +++ b/fs/nfsd/nfsd.h @@ -88,9 +88,6 @@ struct nfsd_genl_rqstp { extern struct svc_program nfsd_programs[]; extern const struct svc_version nfsd_version2, nfsd_version3, nfsd_version4; extern struct mutex nfsd_mutex; -extern spinlock_t nfsd_drc_lock; -extern unsigned long nfsd_drc_max_mem; -extern unsigned long nfsd_drc_mem_used; extern atomic_t nfsd_th_cnt; /* number of available threads */ extern const struct seq_operations nfs_exports_op; diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 49e2f32102ab..3dbaefc96608 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -70,16 +70,6 @@ static __be32 nfsd_init_request(struct svc_rqst *, */ DEFINE_MUTEX(nfsd_mutex); -/* - * nfsd_drc_lock protects nfsd_drc_max_pages and nfsd_drc_pages_used. - * nfsd_drc_max_pages limits the total amount of memory available for - * version 4.1 DRC caches. - * nfsd_drc_pages_used tracks the current version 4.1 DRC memory usage. - */ -DEFINE_SPINLOCK(nfsd_drc_lock); -unsigned long nfsd_drc_max_mem; -unsigned long nfsd_drc_mem_used; - #if IS_ENABLED(CONFIG_NFS_LOCALIO) static const struct svc_version *localio_versions[] = { [1] = &localio_version1, @@ -575,27 +565,6 @@ void nfsd_reset_versions(struct nfsd_net *nn) } } -/* - * Each session guarantees a negotiated per slot memory cache for replies - * which in turn consumes memory beyond the v2/v3/v4.0 server. A dedicated - * NFSv4.1 server might want to use more memory for a DRC than a machine - * with mutiple services. - * - * Impose a hard limit on the number of pages for the DRC which varies - * according to the machines free pages. This is of course only a default. - * - * For now this is a #defined shift which could be under admin control - * in the future. - */ -static void set_max_drc(void) -{ - #define NFSD_DRC_SIZE_SHIFT 7 - nfsd_drc_max_mem = (nr_free_buffer_pages() - >> NFSD_DRC_SIZE_SHIFT) * PAGE_SIZE; - nfsd_drc_mem_used = 0; - dprintk("%s nfsd_drc_max_mem %lu \n", __func__, nfsd_drc_max_mem); -} - static int nfsd_get_default_max_blksize(void) { struct sysinfo i; @@ -678,7 +647,6 @@ int nfsd_create_serv(struct net *net) nn->nfsd_serv = serv; spin_unlock(&nfsd_notifier_lock); - set_max_drc(); /* check if the notifier is already set */ if (atomic_inc_return(&nfsd_notifier_refcount) == 1) { register_inetaddr_notifier(&nfsd_inetaddr_notifier); From patchwork Tue Nov 19 00:41:30 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: NeilBrown X-Patchwork-Id: 13879329 Received: from smtp-out2.suse.de (smtp-out2.suse.de [195.135.223.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2C703E571 for ; Tue, 19 Nov 2024 00:50:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.135.223.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731977405; cv=none; b=BtfWpZsu+1daxsz1x8yoJYQhS2P2Zv6h76dc681ZyJXkCZR2gKlO7JVAjrx0UFQaHXge0XhcZL9yZMPXhbl4IfQMJUu9rTlNEyzbmZyTVNR6H+zO8exEHuSbJQxWa37Bo+C69YDC5By+iFMSCkkrCiVu6u5PUhJraGwemaebAI0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731977405; c=relaxed/simple; bh=nv2OhHLvRI06c7/bf5/928BhbsznlXoRRvHCrYadVXA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=uZPlnHqCqqA0ePia5bKUZ428vixS4DAKOqIl2euP9MucxMvG7LPi+pkEbXJvJjT50gb6/evLrRI5hQuvk8iPC0+WqLjuSdijnMHqLVMYUP52Atwc6g92RHMWg1DwL9XQCrjfR/ZDV+L6CTJ+Rn4uTzUI5o7gMvai/cmwfUKeQRM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de; spf=pass smtp.mailfrom=suse.de; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b=A3n+zD34; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=RdFF7Ny9; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b=A3n+zD34; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=RdFF7Ny9; arc=none smtp.client-ip=195.135.223.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="A3n+zD34"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="RdFF7Ny9"; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="A3n+zD34"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="RdFF7Ny9" Received: from imap1.dmz-prg2.suse.org (imap1.dmz-prg2.suse.org [IPv6:2a07:de40:b281:104:10:150:64:97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id 61F951F365; Tue, 19 Nov 2024 00:50:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1731977402; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=He3dF+y1EhfRnTFDK8MXC2b6YL7EaEzK9vNuO9UjBYY=; b=A3n+zD34IGbYxTDvLiBjzGSq+7EboKwBB8OBST7EH0yfvhvKWVOrr2yFfsypWDRqMTNTb+ bLFjI3/YbaGBJdErAOneWrW0LC00ev3vVxH8Joil7UnYDPWiy9BAaoDroQW3Cau46wewpj Ltxn3vlHwBcbobcWCsz/kZm3To+chuA= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1731977402; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=He3dF+y1EhfRnTFDK8MXC2b6YL7EaEzK9vNuO9UjBYY=; b=RdFF7Ny9G4Y06hA0+8uLtYmHtmFCyTejJn8FxoM148hcJwt2eJx2yTBZZ//BxKWVdUqwz3 /2K90+Knn8VTtKDg== Authentication-Results: smtp-out2.suse.de; dkim=pass header.d=suse.de header.s=susede2_rsa header.b=A3n+zD34; dkim=pass header.d=suse.de header.s=susede2_ed25519 header.b=RdFF7Ny9 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1731977402; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=He3dF+y1EhfRnTFDK8MXC2b6YL7EaEzK9vNuO9UjBYY=; b=A3n+zD34IGbYxTDvLiBjzGSq+7EboKwBB8OBST7EH0yfvhvKWVOrr2yFfsypWDRqMTNTb+ bLFjI3/YbaGBJdErAOneWrW0LC00ev3vVxH8Joil7UnYDPWiy9BAaoDroQW3Cau46wewpj Ltxn3vlHwBcbobcWCsz/kZm3To+chuA= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1731977402; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=He3dF+y1EhfRnTFDK8MXC2b6YL7EaEzK9vNuO9UjBYY=; b=RdFF7Ny9G4Y06hA0+8uLtYmHtmFCyTejJn8FxoM148hcJwt2eJx2yTBZZ//BxKWVdUqwz3 /2K90+Knn8VTtKDg== Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id 5542D1376E; Tue, 19 Nov 2024 00:50:00 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id e0rzA7jgO2eqJgAAD6G6ig (envelope-from ); Tue, 19 Nov 2024 00:50:00 +0000 From: NeilBrown To: Chuck Lever , Jeff Layton Cc: linux-nfs@vger.kernel.org, Olga Kornievskaia , Dai Ngo , Tom Talpey Subject: [PATCH 3/6] nfsd: add session slot count to /proc/fs/nfsd/clients/*/info Date: Tue, 19 Nov 2024 11:41:30 +1100 Message-ID: <20241119004928.3245873-4-neilb@suse.de> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241119004928.3245873-1-neilb@suse.de> References: <20241119004928.3245873-1-neilb@suse.de> Precedence: bulk X-Mailing-List: linux-nfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Rspamd-Queue-Id: 61F951F365 X-Spam-Score: -3.01 X-Rspamd-Action: no action X-Spamd-Result: default: False [-3.01 / 50.00]; BAYES_HAM(-3.00)[100.00%]; MID_CONTAINS_FROM(1.00)[]; NEURAL_HAM_LONG(-1.00)[-1.000]; R_MISSING_CHARSET(0.50)[]; R_DKIM_ALLOW(-0.20)[suse.de:s=susede2_rsa,suse.de:s=susede2_ed25519]; NEURAL_HAM_SHORT(-0.20)[-1.000]; MIME_GOOD(-0.10)[text/plain]; MX_GOOD(-0.01)[]; DBL_BLOCKED_OPENRESOLVER(0.00)[suse.de:dkim,suse.de:mid,suse.de:email]; FROM_HAS_DN(0.00)[]; ARC_NA(0.00)[]; MIME_TRACE(0.00)[0:+]; R_RATELIMIT(0.00)[from(RLewrxuus8mos16izbn)]; TO_DN_SOME(0.00)[]; TO_MATCH_ENVRCPT_ALL(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[]; FROM_EQ_ENVFROM(0.00)[]; DKIM_SIGNED(0.00)[suse.de:s=susede2_rsa,suse.de:s=susede2_ed25519]; FUZZY_BLOCKED(0.00)[rspamd.com]; RCVD_COUNT_TWO(0.00)[2]; RCVD_TLS_ALL(0.00)[]; RCPT_COUNT_FIVE(0.00)[6]; DKIM_TRACE(0.00)[suse.de:+] X-Rspamd-Server: rspamd1.dmz-prg2.suse.org X-Spam-Flag: NO X-Spam-Level: Each client now reports the number of slots allocated in each session. Signed-off-by: NeilBrown --- fs/nfsd/nfs4state.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 3889ba1c653f..31ff9f92a895 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -2642,6 +2642,7 @@ static const char *cb_state2str(int state) static int client_info_show(struct seq_file *m, void *v) { struct inode *inode = file_inode(m->file); + struct nfsd4_session *ses; struct nfs4_client *clp; u64 clid; @@ -2678,6 +2679,13 @@ static int client_info_show(struct seq_file *m, void *v) seq_printf(m, "callback address: \"%pISpc\"\n", &clp->cl_cb_conn.cb_addr); seq_printf(m, "admin-revoked states: %d\n", atomic_read(&clp->cl_admin_revoked)); + seq_printf(m, "session slots:"); + spin_lock(&clp->cl_lock); + list_for_each_entry(ses, &clp->cl_sessions, se_perclnt) + seq_printf(m, " %u", ses->se_fchannel.maxreqs); + spin_unlock(&clp->cl_lock); + seq_puts(m, "\n"); + drop_client(clp); return 0; From patchwork Tue Nov 19 00:41:31 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: NeilBrown X-Patchwork-Id: 13879330 Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.223.130]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 51D781BC2A for ; Tue, 19 Nov 2024 00:50:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.135.223.130 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731977410; cv=none; b=D3C9qirPoTEFp+Rb5mE3Rb+yYYPemOcOqDZahL405WB/zqPJTvAU1beZqkA44sfo4vuHw58bOR5wkjkYpxChT0HGn4q3RBSLMaAjx6q7JOtvUYlGqdRjiL5wPHu7De4Zf1nwGiLv9tzcHdXDTgOWFSJMtcxtZ7xSvGV/s5zeJHM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731977410; c=relaxed/simple; bh=RJteXuvL0W5dfWk03EbYTanEqmBGaxiMqvMNBe8I7jc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=jhuRO4LiEiww6r8QCktWNq72KUwKoHpa/Lj2vi8CbIHjU/ysqb4HfmRgOiM+UWzJWS6/mzvxBiDT2vW8k8s27xCB6EiAeSHb6veA+Zs8JrdwgCi4rePd7CYQVWWEc6f5qwUhzlNkhMmPlv81HHYJkmGUF8PnSDJDrFXybcv2pjM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de; spf=pass smtp.mailfrom=suse.de; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b=1qhYN/AL; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=jj4OBlzn; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b=1qhYN/AL; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=jj4OBlzn; arc=none smtp.client-ip=195.135.223.130 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="1qhYN/AL"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="jj4OBlzn"; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="1qhYN/AL"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="jj4OBlzn" Received: from imap1.dmz-prg2.suse.org (unknown [10.150.64.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id AA75D218B5; Tue, 19 Nov 2024 00:50:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1731977407; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=HNPpi4BWqN0rgNRytN6u3NrSLAfARCynp6N0siX2U/s=; b=1qhYN/AL2jWqLFexjDtVTwiRdGUh1r+QrvKdk7GAM0V+B3i4weyefGaqvYfWZXOYnmJPVI v4EJfCk8lZ1Tdqy+FkJKz8m8u2WczqfQugUxYCzUGsrtwWvCNzETzy84CBxIqVx26yF73Z fzrfCJuJBlXa2hdC6vXysB37iOYAcl8= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1731977407; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=HNPpi4BWqN0rgNRytN6u3NrSLAfARCynp6N0siX2U/s=; b=jj4OBlznD3vBw+qCLo2yjJarLy0+K4GTJeji4hbODK/eYRC84LOTarcv1FVCAlje/ow05V kFabzn2tHu/eDeCA== Authentication-Results: smtp-out1.suse.de; none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1731977407; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=HNPpi4BWqN0rgNRytN6u3NrSLAfARCynp6N0siX2U/s=; b=1qhYN/AL2jWqLFexjDtVTwiRdGUh1r+QrvKdk7GAM0V+B3i4weyefGaqvYfWZXOYnmJPVI v4EJfCk8lZ1Tdqy+FkJKz8m8u2WczqfQugUxYCzUGsrtwWvCNzETzy84CBxIqVx26yF73Z fzrfCJuJBlXa2hdC6vXysB37iOYAcl8= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1731977407; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=HNPpi4BWqN0rgNRytN6u3NrSLAfARCynp6N0siX2U/s=; b=jj4OBlznD3vBw+qCLo2yjJarLy0+K4GTJeji4hbODK/eYRC84LOTarcv1FVCAlje/ow05V kFabzn2tHu/eDeCA== Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id A8C321376E; Tue, 19 Nov 2024 00:50:05 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id ZFJRGL3gO2e5JgAAD6G6ig (envelope-from ); Tue, 19 Nov 2024 00:50:05 +0000 From: NeilBrown To: Chuck Lever , Jeff Layton Cc: linux-nfs@vger.kernel.org, Olga Kornievskaia , Dai Ngo , Tom Talpey Subject: [PATCH 4/6] nfsd: allocate new session-based DRC slots on demand. Date: Tue, 19 Nov 2024 11:41:31 +1100 Message-ID: <20241119004928.3245873-5-neilb@suse.de> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241119004928.3245873-1-neilb@suse.de> References: <20241119004928.3245873-1-neilb@suse.de> Precedence: bulk X-Mailing-List: linux-nfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Spam-Level: X-Spamd-Result: default: False [-2.80 / 50.00]; BAYES_HAM(-3.00)[100.00%]; MID_CONTAINS_FROM(1.00)[]; NEURAL_HAM_LONG(-1.00)[-1.000]; R_MISSING_CHARSET(0.50)[]; NEURAL_HAM_SHORT(-0.20)[-1.000]; MIME_GOOD(-0.10)[text/plain]; RCVD_VIA_SMTP_AUTH(0.00)[]; MIME_TRACE(0.00)[0:+]; R_RATELIMIT(0.00)[from(RLewrxuus8mos16izbn)]; ARC_NA(0.00)[]; TO_DN_SOME(0.00)[]; DKIM_SIGNED(0.00)[suse.de:s=susede2_rsa,suse.de:s=susede2_ed25519]; FUZZY_BLOCKED(0.00)[rspamd.com]; FROM_EQ_ENVFROM(0.00)[]; FROM_HAS_DN(0.00)[]; RCPT_COUNT_FIVE(0.00)[6]; RCVD_COUNT_TWO(0.00)[2]; TO_MATCH_ENVRCPT_ALL(0.00)[]; DBL_BLOCKED_OPENRESOLVER(0.00)[suse.de:email,suse.de:mid]; RCVD_TLS_ALL(0.00)[] X-Spam-Score: -2.80 X-Spam-Flag: NO If a client ever uses the highest available slot for a given session, attempt to allocate another slot so there is room for the client to use more slots if wanted. GFP_NOWAIT is used so if there is not plenty of free memory, failure is expected - which is what we want. It also allows the allocation while holding a spinlock. We would expect to stablise with one more slot available than the client actually uses. Now that we grow the slot table on demand we can start with a smaller allocation. Define NFSD_MAX_INITIAL_SLOTS and allocate at most that many when session is created. Signed-off-by: NeilBrown --- fs/nfsd/nfs4state.c | 32 ++++++++++++++++++++++++++------ fs/nfsd/state.h | 2 ++ 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 31ff9f92a895..fb522165b376 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -1956,7 +1956,7 @@ static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fattrs, if (!slot || xa_is_err(xa_store(&new->se_slots, 0, slot, GFP_KERNEL))) goto out_free; - for (i = 1; i < numslots; i++) { + for (i = 1; i < numslots && i < NFSD_MAX_INITIAL_SLOTS; i++) { slot = kzalloc(slotsize, GFP_KERNEL | __GFP_NORETRY); if (!slot) break; @@ -4248,11 +4248,6 @@ nfsd4_sequence(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, slot = xa_load(&session->se_slots, seq->slotid); dprintk("%s: slotid %d\n", __func__, seq->slotid); - /* We do not negotiate the number of slots yet, so set the - * maxslots to the session maxreqs which is used to encode - * sr_highest_slotid and the sr_target_slot id to maxslots */ - seq->maxslots = session->se_fchannel.maxreqs; - trace_nfsd_slot_seqid_sequence(clp, seq, slot); status = check_slot_seqid(seq->seqid, slot->sl_seqid, slot->sl_flags & NFSD4_SLOT_INUSE); @@ -4302,6 +4297,31 @@ nfsd4_sequence(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, cstate->session = session; cstate->clp = clp; + /* + * If the client ever uses the highest available slot, + * gently try to allocate another one. + */ + if (seq->slotid == session->se_fchannel.maxreqs - 1 && + session->se_fchannel.maxreqs < NFSD_MAX_SLOTS_PER_SESSION) { + int s = session->se_fchannel.maxreqs; + + /* + * GFP_NOWAIT is a low-priority non-blocking allocation + * which can be used under client_lock and only succeeds + * if there is plenty of memory. + * Use GFP_ATOMIC which is higher priority for xa_store() + * so we are less likely to waste the effort of the first + * allocation. + */ + slot = kzalloc(slot_bytes(&session->se_fchannel), GFP_NOWAIT); + if (slot && !xa_is_err(xa_store(&session->se_slots, s, slot, + GFP_ATOMIC))) + session->se_fchannel.maxreqs += 1; + else + kfree(slot); + } + seq->maxslots = session->se_fchannel.maxreqs; + out: switch (clp->cl_cb_state) { case NFSD4_CB_DOWN: diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index e97626916a68..a14a823670e9 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -249,6 +249,8 @@ static inline struct nfs4_delegation *delegstateid(struct nfs4_stid *s) * get good throughput on high-latency servers. */ #define NFSD_MAX_SLOTS_PER_SESSION 2048 +/* Maximum number of slots per session to allocate for CREATE_SESSION */ +#define NFSD_MAX_INITIAL_SLOTS 32 /* Maximum session per slot cache size */ #define NFSD_SLOT_CACHE_SIZE 2048 /* Maximum number of NFSD_SLOT_CACHE_SIZE slots per session */ From patchwork Tue Nov 19 00:41:32 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: NeilBrown X-Patchwork-Id: 13879331 Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.223.130]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AB0D58825 for ; Tue, 19 Nov 2024 00:50:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.135.223.130 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731977421; cv=none; b=OhyM5vPftQr68l5X/DzjVWmJobzTTrXvgG8WYu1r8WzMjHGV7h8VUpJ0RwvbIiLiiytwhJOkfp+w3WBtiq9/j/nk5ick1vMOkz8aswqb+5UpWkbtlR4jJjkV61xLjKQeZ4PqONsx5Mr2lxbu/q7qF5cJhvmAGTUK2iqTMsnSiz4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731977421; c=relaxed/simple; bh=W+znEoAxtV+1FLMr//hhIt2VIf31MYjjvq9SjswbqUU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=sx+1dxcK4F20LkES37z+hTIUsiw5rI8je2V7btpIRK+bZwPphhGS+mG2CpL9JjOgE3+cSN6pQAQguAZp0uct7u0vlRulVe4fAqC16vCFMzoiFg3Ig8I54B8DCOMKZuqlVnl9IHYD4ExOJjlbO+uLvokMr6qCIV5v024iS0s5CS0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de; spf=pass smtp.mailfrom=suse.de; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b=dubt1w3a; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=7MSbYIuD; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b=dubt1w3a; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=7MSbYIuD; arc=none smtp.client-ip=195.135.223.130 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="dubt1w3a"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="7MSbYIuD"; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="dubt1w3a"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="7MSbYIuD" Received: from imap1.dmz-prg2.suse.org (unknown [10.150.64.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id 2E90E21757; Tue, 19 Nov 2024 00:50:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1731977417; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=fukzpdoR2OmTjwQuqs98Rm+SyCkObZk2NvCX5odXncs=; b=dubt1w3atcT0DBsARoMMv/aGbIddgiX0nzCXZ7hu3a1CMTQNtUing0i4iRIO0AbIFuQCt0 cflSYPMnBW8jDkD2g7vRNkNIC4uNq08ldL/ciI4sKU4/NeLu2uQLdJJwNm4hJwL1yneDBX co+YPuyjtmrmwVJm9i8IWv9CIVGjioE= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1731977417; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=fukzpdoR2OmTjwQuqs98Rm+SyCkObZk2NvCX5odXncs=; b=7MSbYIuDgkjlX0kl1mSN9hKrTK218f/x3ZHij0uRTYSWvwnxfsTFCprW0IOHK1QiDu5xgz 8lLjkdiqgGASxODg== Authentication-Results: smtp-out1.suse.de; none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1731977417; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=fukzpdoR2OmTjwQuqs98Rm+SyCkObZk2NvCX5odXncs=; b=dubt1w3atcT0DBsARoMMv/aGbIddgiX0nzCXZ7hu3a1CMTQNtUing0i4iRIO0AbIFuQCt0 cflSYPMnBW8jDkD2g7vRNkNIC4uNq08ldL/ciI4sKU4/NeLu2uQLdJJwNm4hJwL1yneDBX co+YPuyjtmrmwVJm9i8IWv9CIVGjioE= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1731977417; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=fukzpdoR2OmTjwQuqs98Rm+SyCkObZk2NvCX5odXncs=; b=7MSbYIuDgkjlX0kl1mSN9hKrTK218f/x3ZHij0uRTYSWvwnxfsTFCprW0IOHK1QiDu5xgz 8lLjkdiqgGASxODg== Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id 232CD1376E; Tue, 19 Nov 2024 00:50:14 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id SEwLM8bgO2fAJgAAD6G6ig (envelope-from ); Tue, 19 Nov 2024 00:50:14 +0000 From: NeilBrown To: Chuck Lever , Jeff Layton Cc: linux-nfs@vger.kernel.org, Olga Kornievskaia , Dai Ngo , Tom Talpey Subject: [PATCH 5/6] nfsd: add support for freeing unused session-DRC slots Date: Tue, 19 Nov 2024 11:41:32 +1100 Message-ID: <20241119004928.3245873-6-neilb@suse.de> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241119004928.3245873-1-neilb@suse.de> References: <20241119004928.3245873-1-neilb@suse.de> Precedence: bulk X-Mailing-List: linux-nfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Spam-Level: X-Spamd-Result: default: False [-2.80 / 50.00]; BAYES_HAM(-3.00)[100.00%]; MID_CONTAINS_FROM(1.00)[]; NEURAL_HAM_LONG(-1.00)[-1.000]; R_MISSING_CHARSET(0.50)[]; NEURAL_HAM_SHORT(-0.20)[-1.000]; MIME_GOOD(-0.10)[text/plain]; RCVD_VIA_SMTP_AUTH(0.00)[]; MIME_TRACE(0.00)[0:+]; R_RATELIMIT(0.00)[from(RLewrxuus8mos16izbn)]; ARC_NA(0.00)[]; TO_DN_SOME(0.00)[]; DKIM_SIGNED(0.00)[suse.de:s=susede2_rsa,suse.de:s=susede2_ed25519]; FUZZY_BLOCKED(0.00)[rspamd.com]; FROM_EQ_ENVFROM(0.00)[]; FROM_HAS_DN(0.00)[]; RCPT_COUNT_FIVE(0.00)[6]; RCVD_COUNT_TWO(0.00)[2]; TO_MATCH_ENVRCPT_ALL(0.00)[]; DBL_BLOCKED_OPENRESOLVER(0.00)[suse.de:email,suse.de:mid]; RCVD_TLS_ALL(0.00)[] X-Spam-Score: -2.80 X-Spam-Flag: NO Reducing the number of slots in the session slot table requires confirmation from the client. This patch adds reduce_session_slots() which starts the process of getting confirmation, but never calls it. That will come in a later patch. Before we can free a slot we need to confirm that the client won't try to use it again. This involves returning a lower cr_maxrequests in a SEQUENCE reply and then seeing a ca_maxrequests on the same slot which is not larger than we limit we are trying to impose. So for each slot we need to remember that we have sent a reduced cr_maxrequests. To achieve this we introduce a concept of request "generations". Each time we decide to reduce cr_maxrequests we increment the generation number, and record this when we return the lower cr_maxrequests to the client. When a slot with the current generation reports a low ca_maxrequests, we commit to that level and free extra slots. We use an 8 bit generation number (64 seems wasteful) and if it cycles we iterate all slots and reset the generation number to avoid false matches. When we free a slot we store the seqid in the slot pointer so that it can be restored when we reactivate the slot. The RFC can be read as suggesting that the slot number could restart from one after a slot is retired and reactivated, but also suggests that retiring slots is not required. So when we reactive a slot we accept with the next seqid in sequence, or 1. When decoding sa_highest_slotid into maxslots we need to add 1 - this matches how it is encoded for the reply. Signed-off-by: NeilBrown --- fs/nfsd/nfs4state.c | 81 ++++++++++++++++++++++++++++++++++++++------- fs/nfsd/nfs4xdr.c | 5 +-- fs/nfsd/state.h | 4 +++ fs/nfsd/xdr4.h | 2 -- 4 files changed, 76 insertions(+), 16 deletions(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index fb522165b376..0625b0aec6b8 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -1910,17 +1910,55 @@ gen_sessionid(struct nfsd4_session *ses) #define NFSD_MIN_HDR_SEQ_SZ (24 + 12 + 44) static void -free_session_slots(struct nfsd4_session *ses) +free_session_slots(struct nfsd4_session *ses, int from) { int i; - for (i = 0; i < ses->se_fchannel.maxreqs; i++) { + if (from >= ses->se_fchannel.maxreqs) + return; + + for (i = from; i < ses->se_fchannel.maxreqs; i++) { struct nfsd4_slot *slot = xa_load(&ses->se_slots, i); - xa_erase(&ses->se_slots, i); + /* + * Save the seqid in case we reactivate this slot. + * This will never require a memory allocation so GFP + * flag is irrelevant + */ + xa_store(&ses->se_slots, i, xa_mk_value(slot->sl_seqid), + GFP_ATOMIC); free_svc_cred(&slot->sl_cred); kfree(slot); } + ses->se_fchannel.maxreqs = from; + if (ses->se_target_maxslots > from) + ses->se_target_maxslots = from; +} + +static int __maybe_unused +reduce_session_slots(struct nfsd4_session *ses, int dec) +{ + struct nfsd_net *nn = net_generic(ses->se_client->net, + nfsd_net_id); + int ret = 0; + + if (ses->se_target_maxslots <= 1) + return ret; + if (!spin_trylock(&nn->client_lock)) + return ret; + ret = min(dec, ses->se_target_maxslots-1); + ses->se_target_maxslots -= ret; + ses->se_slot_gen += 1; + if (ses->se_slot_gen == 0) { + int i; + ses->se_slot_gen = 1; + for (i = 0; i < ses->se_fchannel.maxreqs; i++) { + struct nfsd4_slot *slot = xa_load(&ses->se_slots, i); + slot->sl_generation = 0; + } + } + spin_unlock(&nn->client_lock); + return ret; } /* @@ -1967,6 +2005,7 @@ static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fattrs, } fattrs->maxreqs = i; memcpy(&new->se_fchannel, fattrs, sizeof(struct nfsd4_channel_attrs)); + new->se_target_maxslots = i; new->se_cb_slot_avail = ~0U; new->se_cb_highest_slot = min(battrs->maxreqs - 1, NFSD_BC_SLOT_TABLE_SIZE - 1); @@ -2080,7 +2119,7 @@ static void nfsd4_del_conns(struct nfsd4_session *s) static void __free_session(struct nfsd4_session *ses) { - free_session_slots(ses); + free_session_slots(ses, 0); xa_destroy(&ses->se_slots); kfree(ses); } @@ -3687,10 +3726,10 @@ nfsd4_exchange_id_release(union nfsd4_op_u *u) kfree(exid->server_impl_name); } -static __be32 check_slot_seqid(u32 seqid, u32 slot_seqid, bool slot_inuse) +static __be32 check_slot_seqid(u32 seqid, u32 slot_seqid, u8 flags) { /* The slot is in use, and no response has been sent. */ - if (slot_inuse) { + if (flags & NFSD4_SLOT_INUSE) { if (seqid == slot_seqid) return nfserr_jukebox; else @@ -3699,6 +3738,8 @@ static __be32 check_slot_seqid(u32 seqid, u32 slot_seqid, bool slot_inuse) /* Note unsigned 32-bit arithmetic handles wraparound: */ if (likely(seqid == slot_seqid + 1)) return nfs_ok; + if ((flags & NFSD4_SLOT_REUSED) && seqid == 1) + return nfs_ok; if (seqid == slot_seqid) return nfserr_replay_cache; return nfserr_seq_misordered; @@ -4249,8 +4290,7 @@ nfsd4_sequence(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, dprintk("%s: slotid %d\n", __func__, seq->slotid); trace_nfsd_slot_seqid_sequence(clp, seq, slot); - status = check_slot_seqid(seq->seqid, slot->sl_seqid, - slot->sl_flags & NFSD4_SLOT_INUSE); + status = check_slot_seqid(seq->seqid, slot->sl_seqid, slot->sl_flags); if (status == nfserr_replay_cache) { status = nfserr_seq_misordered; if (!(slot->sl_flags & NFSD4_SLOT_INITIALIZED)) @@ -4275,6 +4315,12 @@ nfsd4_sequence(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, if (status) goto out_put_session; + if (session->se_target_maxslots < session->se_fchannel.maxreqs && + slot->sl_generation == session->se_slot_gen && + seq->maxslots <= session->se_target_maxslots) + /* Client acknowledged our reduce maxreqs */ + free_session_slots(session, session->se_target_maxslots); + buflen = (seq->cachethis) ? session->se_fchannel.maxresp_cached : session->se_fchannel.maxresp_sz; @@ -4285,8 +4331,9 @@ nfsd4_sequence(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, svc_reserve(rqstp, buflen); status = nfs_ok; - /* Success! bump slot seqid */ + /* Success! accept new slot seqid */ slot->sl_seqid = seq->seqid; + slot->sl_flags &= ~NFSD4_SLOT_REUSED; slot->sl_flags |= NFSD4_SLOT_INUSE; if (seq->cachethis) slot->sl_flags |= NFSD4_SLOT_CACHETHIS; @@ -4302,8 +4349,10 @@ nfsd4_sequence(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, * gently try to allocate another one. */ if (seq->slotid == session->se_fchannel.maxreqs - 1 && + session->se_target_maxslots >= session->se_fchannel.maxreqs && session->se_fchannel.maxreqs < NFSD_MAX_SLOTS_PER_SESSION) { int s = session->se_fchannel.maxreqs; + void *prev_slot; /* * GFP_NOWAIT is a low-priority non-blocking allocation @@ -4314,13 +4363,21 @@ nfsd4_sequence(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, * allocation. */ slot = kzalloc(slot_bytes(&session->se_fchannel), GFP_NOWAIT); + prev_slot = xa_load(&session->se_slots, s); + if (xa_is_value(prev_slot) && slot) { + slot->sl_seqid = xa_to_value(prev_slot); + slot->sl_flags |= NFSD4_SLOT_REUSED; + } if (slot && !xa_is_err(xa_store(&session->se_slots, s, slot, - GFP_ATOMIC))) + GFP_ATOMIC))) { session->se_fchannel.maxreqs += 1; - else + session->se_target_maxslots = session->se_fchannel.maxreqs; + } else { kfree(slot); + } } - seq->maxslots = session->se_fchannel.maxreqs; + seq->maxslots = max(session->se_target_maxslots, seq->maxslots); + seq->target_maxslots = session->se_target_maxslots; out: switch (clp->cl_cb_state) { diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 5c79494bd20b..b281a2198ff3 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -1905,7 +1905,8 @@ nfsd4_decode_sequence(struct nfsd4_compoundargs *argp, return nfserr_bad_xdr; seq->seqid = be32_to_cpup(p++); seq->slotid = be32_to_cpup(p++); - seq->maxslots = be32_to_cpup(p++); + /* sa_highest_slotid counts from 0 but maxslots counts from 1 ... */ + seq->maxslots = be32_to_cpup(p++) + 1; seq->cachethis = be32_to_cpup(p); seq->status_flags = 0; @@ -5054,7 +5055,7 @@ nfsd4_encode_sequence(struct nfsd4_compoundres *resp, __be32 nfserr, if (nfserr != nfs_ok) return nfserr; /* sr_target_highest_slotid */ - nfserr = nfsd4_encode_slotid4(xdr, seq->maxslots - 1); + nfserr = nfsd4_encode_slotid4(xdr, seq->target_maxslots - 1); if (nfserr != nfs_ok) return nfserr; /* sr_status_flags */ diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index a14a823670e9..ea6659d52be2 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -268,7 +268,9 @@ struct nfsd4_slot { #define NFSD4_SLOT_CACHETHIS (1 << 1) #define NFSD4_SLOT_INITIALIZED (1 << 2) #define NFSD4_SLOT_CACHED (1 << 3) +#define NFSD4_SLOT_REUSED (1 << 4) u8 sl_flags; + u8 sl_generation; char sl_data[]; }; @@ -350,6 +352,8 @@ struct nfsd4_session { struct list_head se_conns; u32 se_cb_seq_nr[NFSD_BC_SLOT_TABLE_SIZE]; struct xarray se_slots; /* forward channel slots */ + u8 se_slot_gen; + u32 se_target_maxslots; }; /* formatted contents of nfs4_sessionid */ diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h index 382cc1389396..c26ba86dbdfd 100644 --- a/fs/nfsd/xdr4.h +++ b/fs/nfsd/xdr4.h @@ -576,9 +576,7 @@ struct nfsd4_sequence { u32 slotid; /* request/response */ u32 maxslots; /* request/response */ u32 cachethis; /* request */ -#if 0 u32 target_maxslots; /* response */ -#endif /* not yet */ u32 status_flags; /* response */ }; From patchwork Tue Nov 19 00:41:33 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: NeilBrown X-Patchwork-Id: 13879332 Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.223.130]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 672238825 for ; Tue, 19 Nov 2024 00:50:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.135.223.130 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731977431; cv=none; b=Z4ko2gRHtQjQtxTUbiVSBs158NmMhb7I+w7q1XFCAmbmy3xzmYDGRGxGIAcCyFtmrbsUfIFqGn7MxFY3JgftDVJ+ntCTqECJ+LzPDq4LAZzy2KADh/wvWWc10DqNXq5pBtyH81UzaZQ9lA7KCJXWyts9sD8gNvBfhdwlhe0aMPw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731977431; c=relaxed/simple; bh=BIdOVcuAUbFwmTjUzn6M/lI8oC8MPaFvY43LkiyhIXE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=h+seJorc45z3r/G0D4nMa/EW/A/w+7M0cl7jtSCUoAAd/tqiTKQj4OobcscjwnVZxJPBwBeIBrdnXwl3nEZDMXu6wHxrI7jafpTRVM4CX3k/6g9wAYRqnir43bQNOcthwKNbBvKTYeeWqe/9cAMs5kTfTKt10IE2gAxY7mfbDjk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de; spf=pass smtp.mailfrom=suse.de; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b=dzuQrhX7; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=J8J8U/f+; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b=dzuQrhX7; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=J8J8U/f+; arc=none smtp.client-ip=195.135.223.130 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="dzuQrhX7"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="J8J8U/f+"; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="dzuQrhX7"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="J8J8U/f+" Received: from imap1.dmz-prg2.suse.org (unknown [10.150.64.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id B570321757; Tue, 19 Nov 2024 00:50:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1731977426; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=bBLfYchDQ2mEzlzN4+iUrMrVp11dAzvrj3g/Q3iZdks=; b=dzuQrhX7R67yCcaX5BV9pOJKjgl+iHHQdTJg3PvpCWW50pKpla7mBpN+qdifD37sD0tazy MaXF9CdMBxdYHosHMdbMwToscyw9Wp0c/t7lZ1S7OnQioqdLctfpLsiPj4ZIQbZcC+YMJo BhVZIsJ5lKCT1TGyPY2KGTsW0GjJF+8= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1731977426; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=bBLfYchDQ2mEzlzN4+iUrMrVp11dAzvrj3g/Q3iZdks=; b=J8J8U/f+8UvgUTiYHgVtrg3moQw6o5Oh+e7j8QRzr2ottzGA8rxEYhtzCPnZ2AOuhuN4vF hWpZNHNYDCY8X6CQ== Authentication-Results: smtp-out1.suse.de; none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1731977426; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=bBLfYchDQ2mEzlzN4+iUrMrVp11dAzvrj3g/Q3iZdks=; b=dzuQrhX7R67yCcaX5BV9pOJKjgl+iHHQdTJg3PvpCWW50pKpla7mBpN+qdifD37sD0tazy MaXF9CdMBxdYHosHMdbMwToscyw9Wp0c/t7lZ1S7OnQioqdLctfpLsiPj4ZIQbZcC+YMJo BhVZIsJ5lKCT1TGyPY2KGTsW0GjJF+8= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1731977426; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=bBLfYchDQ2mEzlzN4+iUrMrVp11dAzvrj3g/Q3iZdks=; b=J8J8U/f+8UvgUTiYHgVtrg3moQw6o5Oh+e7j8QRzr2ottzGA8rxEYhtzCPnZ2AOuhuN4vF hWpZNHNYDCY8X6CQ== Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id ACAD21376E; Tue, 19 Nov 2024 00:50:24 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id 1/QIGdDgO2fHJgAAD6G6ig (envelope-from ); Tue, 19 Nov 2024 00:50:24 +0000 From: NeilBrown To: Chuck Lever , Jeff Layton Cc: linux-nfs@vger.kernel.org, Olga Kornievskaia , Dai Ngo , Tom Talpey Subject: [PATCH 6/6] nfsd: add shrinker to reduce number of slots allocated per session Date: Tue, 19 Nov 2024 11:41:33 +1100 Message-ID: <20241119004928.3245873-7-neilb@suse.de> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241119004928.3245873-1-neilb@suse.de> References: <20241119004928.3245873-1-neilb@suse.de> Precedence: bulk X-Mailing-List: linux-nfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Spam-Level: X-Spamd-Result: default: False [-2.80 / 50.00]; BAYES_HAM(-3.00)[100.00%]; MID_CONTAINS_FROM(1.00)[]; NEURAL_HAM_LONG(-1.00)[-1.000]; R_MISSING_CHARSET(0.50)[]; NEURAL_HAM_SHORT(-0.20)[-1.000]; MIME_GOOD(-0.10)[text/plain]; RCVD_VIA_SMTP_AUTH(0.00)[]; MIME_TRACE(0.00)[0:+]; R_RATELIMIT(0.00)[from(RLewrxuus8mos16izbn)]; ARC_NA(0.00)[]; TO_DN_SOME(0.00)[]; DKIM_SIGNED(0.00)[suse.de:s=susede2_rsa,suse.de:s=susede2_ed25519]; FUZZY_BLOCKED(0.00)[rspamd.com]; FROM_EQ_ENVFROM(0.00)[]; FROM_HAS_DN(0.00)[]; RCPT_COUNT_FIVE(0.00)[6]; RCVD_COUNT_TWO(0.00)[2]; TO_MATCH_ENVRCPT_ALL(0.00)[]; DBL_BLOCKED_OPENRESOLVER(0.00)[suse.de:email,suse.de:mid]; RCVD_TLS_ALL(0.00)[] X-Spam-Score: -2.80 X-Spam-Flag: NO Add a shrinker which frees unused slots and may ask the clients to use fewer slots on each session. Each session now tracks se_client_maxreqs which is the most recent max-requests-in-use reported by the client, and se_target_maxreqs which is a target number of requests which is reduced by the shrinker. The shrinker iterates over all sessions on all client in all net-namespaces and reduces the target by 1 for each. The shrinker may get called multiple times to reduce by more than 1 each. If se_target_maxreqs is above se_client_maxreqs, those slots can be freed immediately. If not the client will be ask to reduce its usage and as the usage goes down slots will be freed. Once the usage has dropped to match the target, the target can be increased if the client uses all available slots and if a GFP_NOWAIT allocation succeeds. Signed-off-by: NeilBrown --- fs/nfsd/nfs4state.c | 72 ++++++++++++++++++++++++++++++++++++++++++--- fs/nfsd/state.h | 1 + 2 files changed, 69 insertions(+), 4 deletions(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 0625b0aec6b8..ac49c3bd0dcb 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -1909,6 +1909,16 @@ gen_sessionid(struct nfsd4_session *ses) */ #define NFSD_MIN_HDR_SEQ_SZ (24 + 12 + 44) +static struct shrinker *nfsd_slot_shrinker; +static DEFINE_SPINLOCK(nfsd_session_list_lock); +static LIST_HEAD(nfsd_session_list); +/* The sum of "target_slots-1" on every session. The shrinker can push this + * down, though it can take a little while for the memory to actually + * be freed. The "-1" is because we can never free slot 0 while the + * session is active. + */ +static atomic_t nfsd_total_target_slots = ATOMIC_INIT(0); + static void free_session_slots(struct nfsd4_session *ses, int from) { @@ -1931,11 +1941,14 @@ free_session_slots(struct nfsd4_session *ses, int from) kfree(slot); } ses->se_fchannel.maxreqs = from; - if (ses->se_target_maxslots > from) - ses->se_target_maxslots = from; + if (ses->se_target_maxslots > from) { + int new_target = from ?: 1; + atomic_sub(ses->se_target_maxslots - new_target, &nfsd_total_target_slots); + ses->se_target_maxslots = new_target; + } } -static int __maybe_unused +static int reduce_session_slots(struct nfsd4_session *ses, int dec) { struct nfsd_net *nn = net_generic(ses->se_client->net, @@ -1948,6 +1961,7 @@ reduce_session_slots(struct nfsd4_session *ses, int dec) return ret; ret = min(dec, ses->se_target_maxslots-1); ses->se_target_maxslots -= ret; + atomic_sub(ret, &nfsd_total_target_slots); ses->se_slot_gen += 1; if (ses->se_slot_gen == 0) { int i; @@ -2006,6 +2020,7 @@ static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fattrs, fattrs->maxreqs = i; memcpy(&new->se_fchannel, fattrs, sizeof(struct nfsd4_channel_attrs)); new->se_target_maxslots = i; + atomic_add(i - 1, &nfsd_total_target_slots); new->se_cb_slot_avail = ~0U; new->se_cb_highest_slot = min(battrs->maxreqs - 1, NFSD_BC_SLOT_TABLE_SIZE - 1); @@ -2130,6 +2145,36 @@ static void free_session(struct nfsd4_session *ses) __free_session(ses); } +static unsigned long +nfsd_slot_count(struct shrinker *s, struct shrink_control *sc) +{ + unsigned long cnt = atomic_read(&nfsd_total_target_slots); + + return cnt ? cnt : SHRINK_EMPTY; +} + +static unsigned long +nfsd_slot_scan(struct shrinker *s, struct shrink_control *sc) +{ + struct nfsd4_session *ses; + unsigned long scanned = 0; + unsigned long freed = 0; + + spin_lock(&nfsd_session_list_lock); + list_for_each_entry(ses, &nfsd_session_list, se_all_sessions) { + freed += reduce_session_slots(ses, 1); + scanned += 1; + if (scanned >= sc->nr_to_scan) { + /* Move starting point for next scan */ + list_move(&nfsd_session_list, &ses->se_all_sessions); + break; + } + } + spin_unlock(&nfsd_session_list_lock); + sc->nr_scanned = scanned; + return freed; +} + static void init_session(struct svc_rqst *rqstp, struct nfsd4_session *new, struct nfs4_client *clp, struct nfsd4_create_session *cses) { int idx; @@ -2154,6 +2199,10 @@ static void init_session(struct svc_rqst *rqstp, struct nfsd4_session *new, stru list_add(&new->se_perclnt, &clp->cl_sessions); spin_unlock(&clp->cl_lock); + spin_lock(&nfsd_session_list_lock); + list_add_tail(&new->se_all_sessions, &nfsd_session_list); + spin_unlock(&nfsd_session_list_lock); + { struct sockaddr *sa = svc_addr(rqstp); /* @@ -2223,6 +2272,9 @@ unhash_session(struct nfsd4_session *ses) spin_lock(&ses->se_client->cl_lock); list_del(&ses->se_perclnt); spin_unlock(&ses->se_client->cl_lock); + spin_lock(&nfsd_session_list_lock); + list_del(&ses->se_all_sessions); + spin_unlock(&nfsd_session_list_lock); } /* SETCLIENTID and SETCLIENTID_CONFIRM Helper functions */ @@ -4335,6 +4387,7 @@ nfsd4_sequence(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, slot->sl_seqid = seq->seqid; slot->sl_flags &= ~NFSD4_SLOT_REUSED; slot->sl_flags |= NFSD4_SLOT_INUSE; + slot->sl_generation = session->se_slot_gen; if (seq->cachethis) slot->sl_flags |= NFSD4_SLOT_CACHETHIS; else @@ -4371,6 +4424,8 @@ nfsd4_sequence(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, if (slot && !xa_is_err(xa_store(&session->se_slots, s, slot, GFP_ATOMIC))) { session->se_fchannel.maxreqs += 1; + atomic_add(session->se_fchannel.maxreqs - session->se_target_maxslots, + &nfsd_total_target_slots); session->se_target_maxslots = session->se_fchannel.maxreqs; } else { kfree(slot); @@ -8779,7 +8834,6 @@ nfs4_state_start_net(struct net *net) } /* initialization to perform when the nfsd service is started: */ - int nfs4_state_start(void) { @@ -8789,6 +8843,15 @@ nfs4_state_start(void) if (ret) return ret; + nfsd_slot_shrinker = shrinker_alloc(0, "nfsd-DRC-slot"); + if (!nfsd_slot_shrinker) { + rhltable_destroy(&nfs4_file_rhltable); + return -ENOMEM; + } + nfsd_slot_shrinker->count_objects = nfsd_slot_count; + nfsd_slot_shrinker->scan_objects = nfsd_slot_scan; + shrinker_register(nfsd_slot_shrinker); + set_max_delegations(); return 0; } @@ -8830,6 +8893,7 @@ void nfs4_state_shutdown(void) { rhltable_destroy(&nfs4_file_rhltable); + shrinker_free(nfsd_slot_shrinker); } static void diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index ea6659d52be2..0e320ba097f2 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -345,6 +345,7 @@ struct nfsd4_session { bool se_dead; struct list_head se_hash; /* hash by sessionid */ struct list_head se_perclnt; + struct list_head se_all_sessions;/* global list of sessions */ struct nfs4_client *se_client; struct nfs4_sessionid se_sessionid; struct nfsd4_channel_attrs se_fchannel;