From patchwork Wed Nov 13 05:38:34 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: NeilBrown X-Patchwork-Id: 13873181 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 BEDEF1632E8 for ; Wed, 13 Nov 2024 05:54: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=1731477245; cv=none; b=iNI3lsnQGAaB3R2827m+Q8q1sNovl/bXtnVEwCIThlWGpfwW4Vf1u+h++LWzKw+sdQLfbWLd2KO4RGbiXLaQV4BC89WE3Oj5uJZKJgRmMKV/FyC/VwCznsLqAwoQtaHRKClCh+qgTuWh9AxP8ZWzBTM+iw5dVJz3BmvIMRIs2eU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731477245; c=relaxed/simple; bh=FbjzFYVG8NjR2zInSlmwoUV6vo0MMVBCCcvXpbdSe7g=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=HarbNqCVe0qRQHbCmAJJyAzlzZxXab1j62hgIo2PRBEDeCXfWY39AaJJ4TQ0pAEhDLdidIOi4WfKAZ6LyO4ukQYZq8LVOIUhL2y52DiH77GnY2kOEJj5dEZLFHFp3JHFXUAY/Cb2lXw7qEUrXbzpJnW6RNsBYlTfihrUf37w0SE= 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=SwHwtqvt; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=FM0jpPoC; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b=of61QU/a; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=RSeVpRv+; 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="SwHwtqvt"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="FM0jpPoC"; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="of61QU/a"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="RSeVpRv+" 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 C9D8E1F365; Wed, 13 Nov 2024 05:54:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1731477242; 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=bSizj0r6GMrBZ02dwSsfSG2SBy80koqTOIQwdMfa7HU=; b=SwHwtqvt6442MSepHbbTcAit7MUdHnRpT3JsDyaaUzZiBwJB4O2k+wiKCpyXUYiB8CBWi4 2GZnBOpIy2RmbWpLOc6mj2cnJj/hQt8MW3aevLsRLg5v5OYG5/eaoOmCELQXChfruAjnF3 wHa5bXwVFicFrwP7p7B+PSlPHQt1SVA= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1731477242; 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=bSizj0r6GMrBZ02dwSsfSG2SBy80koqTOIQwdMfa7HU=; b=FM0jpPoCyE/6+sTEWbx4X1dvlJt8zEaXEOhY7elwHT7vUJZGy2ErTd4/i+ebspX5kvsGy1 cOnI2lb6Jdf2oZDw== Authentication-Results: smtp-out2.suse.de; dkim=pass header.d=suse.de header.s=susede2_rsa header.b="of61QU/a"; dkim=pass header.d=suse.de header.s=susede2_ed25519 header.b=RSeVpRv+ DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1731477241; 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=bSizj0r6GMrBZ02dwSsfSG2SBy80koqTOIQwdMfa7HU=; b=of61QU/aQzXAV/qMFbA/hUjrzU07soAwnmgjX1lvynt+8wLZilNbPG7k4/mAY5/vlnOGzr ZQkI9p/qCEW4r4RZOJ115gHFD5HY7HEmFStr7jqJfsbf5jcEwn2XGLh8zv4Mv1tZBOqkXD /XOEABh3Qvk7V8GnFJ4KYmgxLfG/Dvo= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1731477241; 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=bSizj0r6GMrBZ02dwSsfSG2SBy80koqTOIQwdMfa7HU=; b=RSeVpRv+hRFJoAccb7jScnbOptkqJ6NySERFuCclanI6FLyzwisqs6vTfuUNc05x+kEpTY GG5S+jGtt1DUtFCQ== 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 66DD713890; Wed, 13 Nov 2024 05:53:59 +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 DfWsB/c+NGeNfQAAD6G6ig (envelope-from ); Wed, 13 Nov 2024 05:53:59 +0000 From: NeilBrown To: Chuck Lever , Jeff Layton Cc: linux-nfs@vger.kernel.org, Olga Kornievskaia , Dai Ngo , Tom Talpey Subject: [PATCH 1/4] nfsd: remove artificial limits on the session-based DRC Date: Wed, 13 Nov 2024 16:38:34 +1100 Message-ID: <20241113055345.494856-2-neilb@suse.de> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241113055345.494856-1-neilb@suse.de> References: <20241113055345.494856-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: C9D8E1F365 X-Spam-Level: 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:email,suse.de:dkim,suse.de:mid]; ASN(0.00)[asn:25478, ipnet:::/0, country:RU]; ARC_NA(0.00)[]; FROM_HAS_DN(0.00)[]; TO_DN_SOME(0.00)[]; MIME_TRACE(0.00)[0:+]; 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: rspamd2.dmz-prg2.suse.org X-Rspamd-Action: no action X-Spam-Score: -3.01 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. Also *always* allow NFSD_MAX_SLOTS_PER_SESSION slot pointers per session. This allows the session to be allocated before we know how many slots we will successfully allocate, and will be useful when we starting dynamically increasing the number of allocated slots. Signed-off-by: NeilBrown --- fs/nfsd/nfs4state.c | 91 +++++++-------------------------------------- fs/nfsd/nfsd.h | 3 -- fs/nfsd/nfssvc.c | 32 ---------------- fs/nfsd/state.h | 2 +- 4 files changed, 14 insertions(+), 114 deletions(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 551d2958ec29..2dcba0c83c10 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -1935,59 +1935,6 @@ 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) { @@ -1996,26 +1943,27 @@ 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); + BUILD_BUG_ON(sizeof(new) > PAGE_SIZE); - new = kzalloc(struct_size(new, se_slots, numslots), GFP_KERNEL); + new = kzalloc(sizeof(*new), GFP_KERNEL); if (!new) return NULL; /* 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); + new->se_slots[0] = kzalloc(slotsize, GFP_KERNEL); + if (!new->se_slots[0]) + goto out_free; + + for (i = 1; i < numslots; i++) { + new->se_slots[i] = kzalloc(slotsize, GFP_KERNEL | __GFP_NORETRY); if (!new->se_slots[i]) - goto out_free; + break; } - + fattrs->maxreqs = i; memcpy(&new->se_fchannel, fattrs, sizeof(struct nfsd4_channel_attrs)); memcpy(&new->se_bchannel, battrs, sizeof(struct nfsd4_channel_attrs)); return new; out_free: - while (i--) - kfree(new->se_slots[i]); kfree(new); return NULL; } @@ -2128,7 +2076,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); } @@ -3748,17 +3695,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; } @@ -3836,11 +3772,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; @@ -3950,8 +3886,7 @@ nfsd4_create_session(struct svc_rqst *rqstp, expire_client(old); 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 4b56ba1e8e48..3eb21e63b921 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); diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index 35b3564c065f..c052e9eea81b 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -310,7 +310,7 @@ struct nfsd4_session { struct list_head se_conns; u32 se_cb_prog; u32 se_cb_seq_nr; - struct nfsd4_slot *se_slots[]; /* forward channel slots */ + struct nfsd4_slot *se_slots[NFSD_MAX_SLOTS_PER_SESSION]; /* forward channel slots */ }; /* formatted contents of nfs4_sessionid */ From patchwork Wed Nov 13 05:38:35 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: NeilBrown X-Patchwork-Id: 13873182 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 0008E2309AE for ; Wed, 13 Nov 2024 05:54:08 +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=1731477250; cv=none; b=MLxPAliEO+Npl1JcoyxBXi9c/pkGSR3kxboJJJtdp7WhBRHOSrxDAUAs7/4Ns0OPAH/dM2mS6IR9lmOOWt5d6QHwv/8KMGjsD8InSfHAwPtEQM30I2cT0mGrom9U5NtTj687PCkcEBexUIwTjPY/PKV+9ikk+O6oSDZ64GGHSw4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731477250; c=relaxed/simple; bh=bvbhobzw/zRzH4V2Hi5D+LejyrLlBvNh1CnPdazMw38=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=jzekodJ8rfz5dIMWAF0OYoxNT7/ArWrqU14WTerboAq7eNGGHWfgiOHxoutuEE1i1DYAf7zU2ZI/7eoED8PI3UUBMQqdNOy6eRoy+yALgxjPqwgc/lW62mBolpScXB/BJAGE448vWAaFOIzOwJ9Rlc1qWIzJ+Lu0vL6VEj/GZUY= 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=EWYDWOnC; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=jXedBEZw; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b=EWYDWOnC; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=jXedBEZw; 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="EWYDWOnC"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="jXedBEZw"; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="EWYDWOnC"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="jXedBEZw" 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 333CF1F37C; Wed, 13 Nov 2024 05:54:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1731477247; 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=lzX+qC534JJcA9uid6IS+aRdRdskaikQAuxnrYz8eDA=; b=EWYDWOnCTORUAoaY1vIGhVIiLQoiNd/l5lpEClX/JRCYjmZFaIbxzivObNcNhLUoQJLpr6 Tdlibnh+9DCCdBRIjR9Ih1ZAvUnxD3xcIKxCC/JpmVh35yZ7zUT0T35gEP+7EpYRryqq4i T84dC9OiPe0tWdyrM2ieFJ47tV86hug= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1731477247; 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=lzX+qC534JJcA9uid6IS+aRdRdskaikQAuxnrYz8eDA=; b=jXedBEZwqKLhzGeB/d5MaQj4e8ruSXQ821Z44YI+Vfj/ZbEvUtGNNC6WXlusJ1DeMMsjJ8 6DsrQIuB2RNTQoBQ== Authentication-Results: smtp-out2.suse.de; none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1731477247; 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=lzX+qC534JJcA9uid6IS+aRdRdskaikQAuxnrYz8eDA=; b=EWYDWOnCTORUAoaY1vIGhVIiLQoiNd/l5lpEClX/JRCYjmZFaIbxzivObNcNhLUoQJLpr6 Tdlibnh+9DCCdBRIjR9Ih1ZAvUnxD3xcIKxCC/JpmVh35yZ7zUT0T35gEP+7EpYRryqq4i T84dC9OiPe0tWdyrM2ieFJ47tV86hug= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1731477247; 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=lzX+qC534JJcA9uid6IS+aRdRdskaikQAuxnrYz8eDA=; b=jXedBEZwqKLhzGeB/d5MaQj4e8ruSXQ821Z44YI+Vfj/ZbEvUtGNNC6WXlusJ1DeMMsjJ8 6DsrQIuB2RNTQoBQ== 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 25EFD13890; Wed, 13 Nov 2024 05:54:04 +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 afyZM/w+NGeSfQAAD6G6ig (envelope-from ); Wed, 13 Nov 2024 05:54:04 +0000 From: NeilBrown To: Chuck Lever , Jeff Layton Cc: linux-nfs@vger.kernel.org, Olga Kornievskaia , Dai Ngo , Tom Talpey Subject: [PATCH 2/4] nfsd: allocate new session-based DRC slots on demand. Date: Wed, 13 Nov 2024 16:38:35 +1100 Message-ID: <20241113055345.494856-3-neilb@suse.de> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241113055345.494856-1-neilb@suse.de> References: <20241113055345.494856-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-Score: -2.80 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:mid,suse.de:email]; RCVD_TLS_ALL(0.00)[] X-Spam-Flag: NO X-Spam-Level: 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_UNUSED_SLOTS and allocate at most that many when session is created. Signed-off-by: NeilBrown --- fs/nfsd/nfs4state.c | 22 ++++++++++++++++------ fs/nfsd/state.h | 2 ++ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 2dcba0c83c10..683bb908039b 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -1953,7 +1953,7 @@ static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fattrs, if (!new->se_slots[0]) goto out_free; - for (i = 1; i < numslots; i++) { + for (i = 1; i < numslots && i < NFSD_MAX_UNUSED_SLOTS; i++) { new->se_slots[i] = kzalloc(slotsize, GFP_KERNEL | __GFP_NORETRY); if (!new->se_slots[i]) break; @@ -4187,11 +4187,6 @@ nfsd4_sequence(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, slot = 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); @@ -4241,6 +4236,21 @@ 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; + + session->se_slots[s] = kzalloc(slot_bytes(&session->se_fchannel), + GFP_NOWAIT); + if (session->se_slots[s]) + session->se_fchannel.maxreqs += 1; + } + 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 c052e9eea81b..012b68a0bafa 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -215,6 +215,8 @@ static inline struct nfs4_delegation *delegstateid(struct nfs4_stid *s) /* 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 that are allocated by unused */ +#define NFSD_MAX_UNUSED_SLOTS 6 /* Maximum session per slot cache size */ #define NFSD_SLOT_CACHE_SIZE 2048 /* Maximum number of NFSD_SLOT_CACHE_SIZE slots per session */ From patchwork Wed Nov 13 05:38:36 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: NeilBrown X-Patchwork-Id: 13873183 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 691A51714A8 for ; Wed, 13 Nov 2024 05:54:15 +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=1731477257; cv=none; b=ORmwx3/jbDv+1OWKP+5PWjvk60u16GTQJwzZp4omCrwe4BSChlipLVaJ98jf21Aavc+4BnpsQ6MvSwm2JlPKjSNZpGgQaU3PyP5S7LeIwvKKYGHBwl9Pln7WsoTH0H4/W03oxedNkdScLAQMSZc/X2uiywmiLxj82fGVfQe2IKY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731477257; c=relaxed/simple; bh=CLtreox0NRnKElIsQB+6pPr7emiNOIuz5JRiVVirs+M=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=U26UzCHQavDb/uMIrb4GD+QS8Rm1BWhcGW2ItkynReRSVIS8FFooTboDu6aMOHP1sbD4OUSuJbGsiY/oCnVJuFhCMN42wRsP7NdE2aKq1Z8myJEZW2CoXEo3JwUhFL2ECOptmYS3yMsxdv18Kh0UDj2lWZXH8VRDo6WRI77GiVc= 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=vGBFws1Q; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=Irv7UYsI; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b=w1B8l8c1; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=L6mjnozM; 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="vGBFws1Q"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="Irv7UYsI"; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="w1B8l8c1"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="L6mjnozM" 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 9FAE61F365; Wed, 13 Nov 2024 05:54:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1731477253; 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=RIqMQ61JhhGJ1qI1S9DraRk8NA5yvbgGVN70rWkZk68=; b=vGBFws1QQ2sK9x3L9Z9iL8utM1qrNZNQfR38KeIS9hB61updek3XCvzYHvoLPIn+DrBavO NtbMzCUDFdBLkYLBF4/HkJB7opwhvIsEwDz2VUbapVxdpQfU29/lE+gU/UTxTt+94wGUvx cdnS5owUJb2CchQS9mME2Z67D1uGgDI= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1731477253; 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=RIqMQ61JhhGJ1qI1S9DraRk8NA5yvbgGVN70rWkZk68=; b=Irv7UYsI5/co9fBsFrL2K40ElHnYrKH3zaf16jIt4k5A2Q7Ay65p6Bk3gJEBcb+56OndA4 zbTLtS4D+yBmhJAg== Authentication-Results: smtp-out2.suse.de; none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1731477252; 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=RIqMQ61JhhGJ1qI1S9DraRk8NA5yvbgGVN70rWkZk68=; b=w1B8l8c1d3tFrgZcsPnQdj0AGQeHuOk7upEiF8xUJlFer7X/9yHgpOn68MFgv3UY5Asw2c 9kwYbpn6cwLISgXOc7gInm6F+iJ5oh/sWqvUzH6jl8JZnOWhH4397ucXFoyhE1//QtP+Vr eHJTnb2V/bNs80O6a5597pkyPl9yEi4= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1731477252; 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=RIqMQ61JhhGJ1qI1S9DraRk8NA5yvbgGVN70rWkZk68=; b=L6mjnozMjpIvtPqL5aSuI2UurvdjJCV9Zfc9BKXKhwp5Qb69MpQcjbdVPXtzMdZJ5/Sl7y ex5xEFj6IFVPcZAA== 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 87AE713890; Wed, 13 Nov 2024 05:54:10 +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 p6LUDwI/NGeXfQAAD6G6ig (envelope-from ); Wed, 13 Nov 2024 05:54:10 +0000 From: NeilBrown To: Chuck Lever , Jeff Layton Cc: linux-nfs@vger.kernel.org, Olga Kornievskaia , Dai Ngo , Tom Talpey Subject: [PATCH 3/4] nfsd: free unused session-DRC slots Date: Wed, 13 Nov 2024 16:38:36 +1100 Message-ID: <20241113055345.494856-4-neilb@suse.de> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241113055345.494856-1-neilb@suse.de> References: <20241113055345.494856-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 When the client confirms that some currently allocated DRC slots are not used, free some. We currently keep 6 (NFSD_MAX_UNUSED_SLOTS) unused slots to support bursts of client activity. This could be tuned with a shrinker. 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 requires the seqid for each slot to increment on each request and does not permit it ever to be reset. We 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 | 25 +++++++++++++++++++------ fs/nfsd/nfs4xdr.c | 3 ++- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 683bb908039b..15de62416243 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -1910,14 +1910,21 @@ 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++) { + uintptr_t seqid = ses->se_slots[i]->sl_seqid; free_svc_cred(&ses->se_slots[i]->sl_cred); kfree(ses->se_slots[i]); + /* Save the seqid in case we reactivate this slot */ + ses->se_slots[i] = (void *)seqid; } + ses->se_fchannel.maxreqs = from; } /* @@ -2069,7 +2076,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); kfree(ses); } @@ -4214,6 +4221,9 @@ nfsd4_sequence(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, if (status) goto out_put_session; + /* If there are lots of unused slots, free some */ + free_session_slots(session, seq->maxslots + NFSD_MAX_UNUSED_SLOTS); + buflen = (seq->cachethis) ? session->se_fchannel.maxresp_cached : session->se_fchannel.maxresp_sz; @@ -4244,10 +4254,13 @@ nfsd4_sequence(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, session->se_fchannel.maxreqs < NFSD_MAX_SLOTS_PER_SESSION) { int s = session->se_fchannel.maxreqs; - session->se_slots[s] = kzalloc(slot_bytes(&session->se_fchannel), - GFP_NOWAIT); - if (session->se_slots[s]) + struct nfsd4_slot *slot = kzalloc(slot_bytes(&session->se_fchannel), + GFP_NOWAIT); + if (slot) { + slot->sl_seqid = (uintptr_t)session->se_slots[s]; + session->se_slots[s] = slot; session->se_fchannel.maxreqs += 1; + } } seq->maxslots = session->se_fchannel.maxreqs; diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index f118921250c3..846ed52fdaf5 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -1884,7 +1884,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; From patchwork Wed Nov 13 05:38:37 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: NeilBrown X-Patchwork-Id: 13873184 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 CCBE62309AE for ; Wed, 13 Nov 2024 05:54:19 +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=1731477261; cv=none; b=LYUXVXYm5qVeXnEekoKRadF8jaZ2jaNr2UFjZvYeoPVCzqjzJYhyFg+hk1i905H+oB0DqGFSLiGHgLNuvLAFhG2Ey2C1ZlnSQImWfJGXbQmloEf8HegDKh+9i7PspkFsJ07edqSFfvHfH5o2A0Ni18FgDo44XB8XFkqe18Myu0w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731477261; c=relaxed/simple; bh=JN8Y1zraGSF5kDeBBKTwC/r5Hzulb+OXLKf2/MASB5A=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=sHhXQH8cL7UdOY/x2wQ53al4tEdAPIzLxXsnMko0LNojNW+UwHShSmsbcDc2eSfULFEtDnMTIINL7nmIOtg9ii87Lf5GsHa6WZHoBvyc/ixClmTdTeyf/MxdU8UCQ4tPU3Rmud2wdUXAVfS1Ltd+0Xm6wo/polRC+R4iBGnWD3o= 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=dnC3S6CF; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=2Oy9yYh/; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b=dnC3S6CF; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=2Oy9yYh/; 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="dnC3S6CF"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="2Oy9yYh/"; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="dnC3S6CF"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="2Oy9yYh/" 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 0E117211E9; Wed, 13 Nov 2024 05:54:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1731477258; 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=cHRnBhukkWMtu08x+fOXswoZ2TBLYJ6Z4NIVMjU42Ss=; b=dnC3S6CFHedwpRx74eqykRpGTD+sxrkGJ2qw8hiQoeWcIxs1MOC05QmDGLxKywfaVEPUje ZK8Fvh9CJoIw0+rkMIMyP1uApxPd68B2Ktmua/83t9+PRj7IzsG+SpX4U6IgNY8DuzlQfg aZWbEWSnQe0dZUtpBn4Rs2M9nF7SCdY= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1731477258; 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=cHRnBhukkWMtu08x+fOXswoZ2TBLYJ6Z4NIVMjU42Ss=; b=2Oy9yYh/GRmBwc+Zu+CMXnoLmAfAxP59pu4O1gKRrA5AOFmOXbP9ZXcEuTvp6MGHnS5JIM uS3mpg4A0+AfRgDA== Authentication-Results: smtp-out1.suse.de; none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1731477258; 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=cHRnBhukkWMtu08x+fOXswoZ2TBLYJ6Z4NIVMjU42Ss=; b=dnC3S6CFHedwpRx74eqykRpGTD+sxrkGJ2qw8hiQoeWcIxs1MOC05QmDGLxKywfaVEPUje ZK8Fvh9CJoIw0+rkMIMyP1uApxPd68B2Ktmua/83t9+PRj7IzsG+SpX4U6IgNY8DuzlQfg aZWbEWSnQe0dZUtpBn4Rs2M9nF7SCdY= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1731477258; 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=cHRnBhukkWMtu08x+fOXswoZ2TBLYJ6Z4NIVMjU42Ss=; b=2Oy9yYh/GRmBwc+Zu+CMXnoLmAfAxP59pu4O1gKRrA5AOFmOXbP9ZXcEuTvp6MGHnS5JIM uS3mpg4A0+AfRgDA== 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 F3B8913890; Wed, 13 Nov 2024 05:54:15 +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 eCgzKgc/NGegfQAAD6G6ig (envelope-from ); Wed, 13 Nov 2024 05:54:15 +0000 From: NeilBrown To: Chuck Lever , Jeff Layton Cc: linux-nfs@vger.kernel.org, Olga Kornievskaia , Dai Ngo , Tom Talpey Subject: [PATCH 4/4] nfsd: add shrinker to reduce number of slots allocated per session Date: Wed, 13 Nov 2024 16:38:37 +1100 Message-ID: <20241113055345.494856-5-neilb@suse.de> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241113055345.494856-1-neilb@suse.de> References: <20241113055345.494856-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 | 82 ++++++++++++++++++++++++++++++++++++++++++++- fs/nfsd/nfs4xdr.c | 2 +- fs/nfsd/state.h | 3 ++ fs/nfsd/xdr4.h | 2 -- 4 files changed, 85 insertions(+), 4 deletions(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 15de62416243..bbc365002885 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -1925,6 +1925,8 @@ free_session_slots(struct nfsd4_session *ses, int from) ses->se_slots[i] = (void *)seqid; } ses->se_fchannel.maxreqs = from; + if (ses->se_target_maxreqs > from) + ses->se_target_maxreqs = from; } /* @@ -1968,6 +1970,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)); memcpy(&new->se_bchannel, battrs, sizeof(struct nfsd4_channel_attrs)); + new->se_target_maxreqs = i; return new; out_free: @@ -2086,6 +2089,57 @@ static void free_session(struct nfsd4_session *ses) __free_session(ses); } + +static DEFINE_SPINLOCK(nfsd_session_list_lock); +static LIST_HEAD(nfsd_session_list); + +static unsigned long +nfsd_slot_count(struct shrinker *s, struct shrink_control *sc) +{ + struct nfsd4_session *ses; + unsigned long cnt = 0; + + spin_lock(&nfsd_session_list_lock); + list_for_each_entry(ses, &nfsd_session_list, se_all_sessions) + if (ses->se_target_maxreqs > 1) + cnt += ses->se_target_maxreqs - 1; + spin_unlock(&nfsd_session_list_lock); + 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) { + struct nfsd_net *nn = net_generic(ses->se_client->net, + nfsd_net_id); + + spin_lock(&nn->client_lock); + if (ses->se_fchannel.maxreqs > 1 && + ses->se_target_maxreqs > 1) { + freed += 1; + ses->se_target_maxreqs -= 1; + free_session_slots(ses, max(ses->se_target_maxreqs, + ses->se_client_maxreqs)); + } + spin_unlock(&nn->client_lock); + 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; @@ -2107,6 +2161,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); /* @@ -2176,6 +2234,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 */ @@ -4221,8 +4282,11 @@ nfsd4_sequence(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, if (status) goto out_put_session; - /* If there are lots of unused slots, free some */ + /* we can safely free some slots */ free_session_slots(session, seq->maxslots + NFSD_MAX_UNUSED_SLOTS); + free_session_slots(session, max(seq->maxslots, + session->se_target_maxreqs)); + session->se_client_maxreqs = seq->maxslots; buflen = (seq->cachethis) ? session->se_fchannel.maxresp_cached : @@ -4251,6 +4315,7 @@ 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_maxreqs >= session->se_fchannel.maxreqs && session->se_fchannel.maxreqs < NFSD_MAX_SLOTS_PER_SESSION) { int s = session->se_fchannel.maxreqs; @@ -4260,9 +4325,11 @@ nfsd4_sequence(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, slot->sl_seqid = (uintptr_t)session->se_slots[s]; session->se_slots[s] = slot; session->se_fchannel.maxreqs += 1; + session->se_target_maxreqs = session->se_fchannel.maxreqs; } } seq->maxslots = session->se_fchannel.maxreqs; + seq->target_maxslots = session->se_target_maxreqs; out: switch (clp->cl_cb_state) { @@ -8653,6 +8720,8 @@ nfs4_state_start_net(struct net *net) /* initialization to perform when the nfsd service is started: */ +static struct shrinker *nfsd_slot_shrinker; + int nfs4_state_start(void) { @@ -8662,6 +8731,16 @@ 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; + nfsd_slot_shrinker->seeks = 1; + shrinker_register(nfsd_slot_shrinker); + set_max_delegations(); return 0; } @@ -8703,6 +8782,7 @@ void nfs4_state_shutdown(void) { rhltable_destroy(&nfs4_file_rhltable); + shrinker_free(nfsd_slot_shrinker); } static void diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 846ed52fdaf5..ac3376c2e5cc 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -4956,7 +4956,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 012b68a0bafa..a25f3cfaab09 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -304,12 +304,15 @@ struct nfsd4_session { /* See SESSION4_PERSIST, etc. for standard flags; this is internal-only: */ #define NFS4_SESSION_DEAD 0x010 u32 se_flags; + 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; struct nfsd4_channel_attrs se_bchannel; struct nfsd4_cb_sec se_cb_sec; struct list_head se_conns; + u8 se_target_maxreqs; + u8 se_client_maxreqs; u32 se_cb_prog; u32 se_cb_seq_nr; struct nfsd4_slot *se_slots[NFSD_MAX_SLOTS_PER_SESSION]; /* forward channel slots */ diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h index 2a21a7662e03..71b87190a4a6 100644 --- a/fs/nfsd/xdr4.h +++ b/fs/nfsd/xdr4.h @@ -575,9 +575,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 */ };