From nobody Thu Dec 18 03:20:29 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 68BF72153D8 for ; Wed, 6 Aug 2025 20:37:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512652; cv=none; b=HhkBVIHTb/ns+jArIOg+BygjAnD+fB9+e/Z3v133nV7TcO511rRwGHqzTJS1FLJpdIvhMS0WvQKa+FCn2QA7lYc/8qg3dfMHhPH/i7byZw04xMXDtf4xWSNzDfkp3DWF7Ls3B7r24sujbwEqT1dSoHo7a0Agsl0YfSO25/zKBGM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512652; c=relaxed/simple; bh=iwlGvKhOI+i6VMNnthS81ctLD77v4aMMHF6SciyVTrI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=lo2eRMzaUeASUWGSPkQVW0Pwv6xulW0IUVSikY+ExgI3gC28Tkv7r8UOxGiyDqs7vVZeAIAESfHiwRoWikQgjj+qVZFpP9KiM43+QZ1BNkiEz8yv8Wz3W9TQAefhgNkmKJ9TGK8JYdH8YPIo5vGgpPCP83aTwurAaTfTU9c2Vqc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=ieFnWq7I; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="ieFnWq7I" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1754512649; h=from:from:reply-to:subject:subject: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=nWtz3qSueBra8NkVdEcoiYIsFsfLvyAM7VI8XyjxQXc=; b=ieFnWq7ID5fTVIMHRrkbn5SeM6lsZ5jwKIzcVZ1oI3gnB+EXnRiHHibI5PtuRQUh9TrXdE i48NYvAvc7fsZ93josMTS8wYRlNyKzLLJmbcKQw+9YJXjYRVaHNB6M4G4ENMQ4w+LwFcdw 9xsveb32WrHAZm4+mI2RAc8M3X4UNkM= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-644-zdZ0tj3ZOWm2-1A-aEehfw-1; Wed, 06 Aug 2025 16:37:24 -0400 X-MC-Unique: zdZ0tj3ZOWm2-1A-aEehfw-1 X-Mimecast-MFC-AGG-ID: zdZ0tj3ZOWm2-1A-aEehfw_1754512639 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 5F19E180034A; Wed, 6 Aug 2025 20:37:19 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.17]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id A294D1800447; Wed, 6 Aug 2025 20:37:16 +0000 (UTC) From: David Howells To: Steve French Cc: David Howells , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Wang Zhaolong , Stefan Metzmacher , Mina Almasry , linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [RFC PATCH 01/31] iov_iter: Move ITER_DISCARD and ITER_XARRAY iteration out-of-line Date: Wed, 6 Aug 2025 21:36:22 +0100 Message-ID: <20250806203705.2560493-2-dhowells@redhat.com> In-Reply-To: <20250806203705.2560493-1-dhowells@redhat.com> References: <20250806203705.2560493-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Content-Type: text/plain; charset="utf-8" Move ITER_DISCARD and ITER_XARRAY iteration out-of-line in preparation of adding other iteration types which will also be out-of-line. Signed-off-by: David Howells --- include/linux/iov_iter.h | 77 +++----------------------------------- lib/iov_iter.c | 81 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 72 deletions(-) diff --git a/include/linux/iov_iter.h b/include/linux/iov_iter.h index c4aa58032faf..0c47933df517 100644 --- a/include/linux/iov_iter.h +++ b/include/linux/iov_iter.h @@ -17,6 +17,9 @@ typedef size_t (*iov_step_f)(void *iter_base, size_t prog= ress, size_t len, typedef size_t (*iov_ustep_f)(void __user *iter_base, size_t progress, siz= e_t len, void *priv, void *priv2); =20 +size_t __iterate_and_advance2(struct iov_iter *iter, size_t len, void *pri= v, + void *priv2, iov_ustep_f ustep, iov_step_f step); + /* * Handle ITER_UBUF. */ @@ -195,72 +198,6 @@ size_t iterate_folioq(struct iov_iter *iter, size_t le= n, void *priv, void *priv2 return progress; } =20 -/* - * Handle ITER_XARRAY. - */ -static __always_inline -size_t iterate_xarray(struct iov_iter *iter, size_t len, void *priv, void = *priv2, - iov_step_f step) -{ - struct folio *folio; - size_t progress =3D 0; - loff_t start =3D iter->xarray_start + iter->iov_offset; - pgoff_t index =3D start / PAGE_SIZE; - XA_STATE(xas, iter->xarray, index); - - rcu_read_lock(); - xas_for_each(&xas, folio, ULONG_MAX) { - size_t remain, consumed, offset, part, flen; - - if (xas_retry(&xas, folio)) - continue; - if (WARN_ON(xa_is_value(folio))) - break; - if (WARN_ON(folio_test_hugetlb(folio))) - break; - - offset =3D offset_in_folio(folio, start + progress); - flen =3D min(folio_size(folio) - offset, len); - - while (flen) { - void *base =3D kmap_local_folio(folio, offset); - - part =3D min_t(size_t, flen, - PAGE_SIZE - offset_in_page(offset)); - remain =3D step(base, progress, part, priv, priv2); - kunmap_local(base); - - consumed =3D part - remain; - progress +=3D consumed; - len -=3D consumed; - - if (remain || len =3D=3D 0) - goto out; - flen -=3D consumed; - offset +=3D consumed; - } - } - -out: - rcu_read_unlock(); - iter->iov_offset +=3D progress; - iter->count -=3D progress; - return progress; -} - -/* - * Handle ITER_DISCARD. - */ -static __always_inline -size_t iterate_discard(struct iov_iter *iter, size_t len, void *priv, void= *priv2, - iov_step_f step) -{ - size_t progress =3D len; - - iter->count -=3D progress; - return progress; -} - /** * iterate_and_advance2 - Iterate over an iterator * @iter: The iterator to iterate over. @@ -306,9 +243,7 @@ size_t iterate_and_advance2(struct iov_iter *iter, size= _t len, void *priv, return iterate_kvec(iter, len, priv, priv2, step); if (iov_iter_is_folioq(iter)) return iterate_folioq(iter, len, priv, priv2, step); - if (iov_iter_is_xarray(iter)) - return iterate_xarray(iter, len, priv, priv2, step); - return iterate_discard(iter, len, priv, priv2, step); + return __iterate_and_advance2(iter, len, priv, priv2, ustep, step); } =20 /** @@ -370,9 +305,7 @@ size_t iterate_and_advance_kernel(struct iov_iter *iter= , size_t len, void *priv, return iterate_kvec(iter, len, priv, priv2, step); if (iov_iter_is_folioq(iter)) return iterate_folioq(iter, len, priv, priv2, step); - if (iov_iter_is_xarray(iter)) - return iterate_xarray(iter, len, priv, priv2, step); - return iterate_discard(iter, len, priv, priv2, step); + return __iterate_and_advance2(iter, len, priv, priv2, NULL, step); } =20 #endif /* _LINUX_IOV_ITER_H */ diff --git a/lib/iov_iter.c b/lib/iov_iter.c index f9193f952f49..53e58903fe75 100644 --- a/lib/iov_iter.c +++ b/lib/iov_iter.c @@ -1928,3 +1928,84 @@ ssize_t iov_iter_extract_pages(struct iov_iter *i, return -EFAULT; } EXPORT_SYMBOL_GPL(iov_iter_extract_pages); + +/* + * Handle ITER_XARRAY. + */ +static __always_inline +size_t iterate_xarray(struct iov_iter *iter, size_t len, void *priv, void = *priv2, + iov_step_f step) +{ + struct folio *folio; + size_t progress =3D 0; + loff_t start =3D iter->xarray_start + iter->iov_offset; + pgoff_t index =3D start / PAGE_SIZE; + XA_STATE(xas, iter->xarray, index); + + rcu_read_lock(); + xas_for_each(&xas, folio, ULONG_MAX) { + size_t remain, consumed, offset, part, flen; + + if (xas_retry(&xas, folio)) + continue; + if (WARN_ON(xa_is_value(folio))) + break; + if (WARN_ON(folio_test_hugetlb(folio))) + break; + + offset =3D offset_in_folio(folio, start + progress); + flen =3D min(folio_size(folio) - offset, len); + + while (flen) { + void *base =3D kmap_local_folio(folio, offset); + + part =3D min_t(size_t, flen, + PAGE_SIZE - offset_in_page(offset)); + remain =3D step(base, progress, part, priv, priv2); + kunmap_local(base); + + consumed =3D part - remain; + progress +=3D consumed; + len -=3D consumed; + + if (remain || len =3D=3D 0) + goto out; + flen -=3D consumed; + offset +=3D consumed; + } + } + +out: + rcu_read_unlock(); + iter->iov_offset +=3D progress; + iter->count -=3D progress; + return progress; +} + +/* + * Handle ITER_DISCARD. + */ +static __always_inline +size_t iterate_discard(struct iov_iter *iter, size_t len, void *priv, void= *priv2, + iov_step_f step) +{ + size_t progress =3D len; + + iter->count -=3D progress; + return progress; +} + +/* + * Out of line iteration for iterator types that don't need such fast hand= ling. + */ +size_t __iterate_and_advance2(struct iov_iter *iter, size_t len, void *pri= v, + void *priv2, iov_ustep_f ustep, iov_step_f step) +{ + if (iov_iter_is_discard(iter)) + return iterate_discard(iter, len, priv, priv2, step); + if (iov_iter_is_xarray(iter)) + return iterate_xarray(iter, len, priv, priv2, step); + WARN_ON(1); + return 0; +} +EXPORT_SYMBOL(__iterate_and_advance2); From nobody Thu Dec 18 03:20:29 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 27DCC220696 for ; Wed, 6 Aug 2025 20:37:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512650; cv=none; b=jeS7v683qkj4lQwgIhTosj5/xJsfWaynPgAwBz3JteKiULFQsBrgalV2IIrDuTgt7W4vQOBNbkK0dyggQPcgwl8dYsV0XGZbYL0Hh8kTMlaM4O+JFjuU0Nn70/7epaSJ+6ZU0rAhLs/K2LS4YiX1T1Le9HkBjrY3NoJY57gCm08= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512650; c=relaxed/simple; bh=IxfYgpq4zI1Te11jMIH8dX44DMx4OX/xULaiW/AQDpA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Kxzu0+1uX/D2Sn1In0XUyCbQR5N40jAiOHgj+954vafzSgE4LNPC9iPvQY74lSDJMQ4H4WD8hUoQqpo/PpdFtVLXTM2w7rKvA9yTX7QUH8djZdAxoJEDuyLFuCFMEeXpmlyW2PWg8RSXXbcwmNH8ASpUcB7h6o4FpeXA/zvk78A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=CojMqfrC; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="CojMqfrC" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1754512647; h=from:from:reply-to:subject:subject: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=T8je+m+XOI8RLg+bFiBwLQKIpAh8fOcOUNT1OPWucvo=; b=CojMqfrCGtrSBc8R0omxqCdXMD3H/ob5kBk10sYPINfyfU46ltlLnyT2XwQh5MyFNKXfgd XwJhzmKRtYyNvkpM/lt2FiUmJWLYB7adrqpP2FNW998YZdjpEttX+M22IQMax5EE4GMu9C JfAraO7MKf6KpVGfoh2KLgjCIKVQhDo= Received: from mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-148-kGr1uHtwOcOlY7cxv64jkA-1; Wed, 06 Aug 2025 16:37:25 -0400 X-MC-Unique: kGr1uHtwOcOlY7cxv64jkA-1 X-Mimecast-MFC-AGG-ID: kGr1uHtwOcOlY7cxv64jkA_1754512644 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id DE71E1955EC7; Wed, 6 Aug 2025 20:37:23 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.17]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 019A319560AD; Wed, 6 Aug 2025 20:37:20 +0000 (UTC) From: David Howells To: Steve French Cc: David Howells , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Wang Zhaolong , Stefan Metzmacher , Mina Almasry , linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [RFC PATCH 02/31] iov_iter: Add a segmented queue of bio_vec[] Date: Wed, 6 Aug 2025 21:36:23 +0100 Message-ID: <20250806203705.2560493-3-dhowells@redhat.com> In-Reply-To: <20250806203705.2560493-1-dhowells@redhat.com> References: <20250806203705.2560493-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 Content-Type: text/plain; charset="utf-8" Add a segmented queue of bio_vec[]. This allows an indefinite quantity of elements to be handled. A rolling buffer can also be implemented over them where new bio_vecs can be added to the leading edge and spent bio_vecs can be cleared from the trailing edge. Signed-off-by: David Howells --- include/linux/bvec.h | 13 ++ include/linux/uio.h | 11 ++ lib/iov_iter.c | 325 ++++++++++++++++++++++++++++++++++++- lib/tests/kunit_iov_iter.c | 196 ++++++++++++++++++++++ 4 files changed, 543 insertions(+), 2 deletions(-) diff --git a/include/linux/bvec.h b/include/linux/bvec.h index 0a80e1f9aa20..7986c9019fa0 100644 --- a/include/linux/bvec.h +++ b/include/linux/bvec.h @@ -298,4 +298,17 @@ static inline phys_addr_t bvec_phys(const struct bio_v= ec *bvec) return page_to_phys(bvec->bv_page) + bvec->bv_offset; } =20 +/* + * Segmented bio_vec queue. These can be linked together to form messages= of + * indefinite length and iterated over with an ITER_BVECQ iterator. + */ +struct bvecq { + struct bvecq *next; /* Next bvec in the list or NULL */ + struct bvecq *prev; /* Prev bvec in the list or NULL */ + u16 max_segs; /* Number of elements allocated in bv[] */ + u16 nr_segs; /* Number of elements in bv[] used */ + u16 cleared; /* Number of elements used in bv[] cleared */ + struct bio_vec bv[] __counted_by(max_segs); +}; + #endif /* __LINUX_BVEC_H */ diff --git a/include/linux/uio.h b/include/linux/uio.h index 2e86c653186c..2c04646be91a 100644 --- a/include/linux/uio.h +++ b/include/linux/uio.h @@ -27,6 +27,7 @@ enum iter_type { ITER_BVEC, ITER_KVEC, ITER_FOLIOQ, + ITER_BVECQ, ITER_XARRAY, ITER_DISCARD, }; @@ -69,6 +70,7 @@ struct iov_iter { const struct kvec *kvec; const struct bio_vec *bvec; const struct folio_queue *folioq; + const struct bvecq *bvecq; struct xarray *xarray; void __user *ubuf; }; @@ -78,6 +80,7 @@ struct iov_iter { union { unsigned long nr_segs; u8 folioq_slot; + u16 bvecq_slot; loff_t xarray_start; }; }; @@ -150,6 +153,11 @@ static inline bool iov_iter_is_folioq(const struct iov= _iter *i) return iov_iter_type(i) =3D=3D ITER_FOLIOQ; } =20 +static inline bool iov_iter_is_bvecq(const struct iov_iter *i) +{ + return iov_iter_type(i) =3D=3D ITER_BVECQ; +} + static inline bool iov_iter_is_xarray(const struct iov_iter *i) { return iov_iter_type(i) =3D=3D ITER_XARRAY; @@ -300,6 +308,9 @@ void iov_iter_discard(struct iov_iter *i, unsigned int = direction, size_t count); void iov_iter_folio_queue(struct iov_iter *i, unsigned int direction, const struct folio_queue *folioq, unsigned int first_slot, unsigned int offset, size_t count); +void iov_iter_bvec_queue(struct iov_iter *i, unsigned int direction, + const struct bvecq *bvecq, + unsigned int first_slot, unsigned int offset, size_t count); void iov_iter_xarray(struct iov_iter *i, unsigned int direction, struct xa= rray *xarray, loff_t start, size_t count); ssize_t iov_iter_get_pages2(struct iov_iter *i, struct page **pages, diff --git a/lib/iov_iter.c b/lib/iov_iter.c index 53e58903fe75..aefd41f689b7 100644 --- a/lib/iov_iter.c +++ b/lib/iov_iter.c @@ -559,6 +559,39 @@ static void iov_iter_folioq_advance(struct iov_iter *i= , size_t size) i->folioq =3D folioq; } =20 +static void iov_iter_bvecq_advance(struct iov_iter *i, size_t by) +{ + const struct bvecq *bq =3D i->bvecq; + unsigned int slot =3D i->bvecq_slot; + + if (!i->count) + return; + i->count -=3D by; + + if (slot >=3D bq->nr_segs) { + bq =3D bq->next; + slot =3D 0; + } + + by +=3D i->iov_offset; /* From beginning of current segment. */ + do { + size_t len =3D bq->bv[slot].bv_len; + + if (likely(by < len)) + break; + by -=3D len; + slot++; + if (slot >=3D bq->nr_segs && bq->next) { + bq =3D bq->next; + slot =3D 0; + } + } while (by); + + i->iov_offset =3D by; + i->bvecq_slot =3D slot; + i->bvecq =3D bq; +} + void iov_iter_advance(struct iov_iter *i, size_t size) { if (unlikely(i->count < size)) @@ -573,6 +606,8 @@ void iov_iter_advance(struct iov_iter *i, size_t size) iov_iter_bvec_advance(i, size); } else if (iov_iter_is_folioq(i)) { iov_iter_folioq_advance(i, size); + } else if (iov_iter_is_bvecq(i)) { + iov_iter_bvecq_advance(i, size); } else if (iov_iter_is_discard(i)) { i->count -=3D size; } @@ -605,6 +640,32 @@ static void iov_iter_folioq_revert(struct iov_iter *i,= size_t unroll) i->folioq =3D folioq; } =20 +static void iov_iter_bvecq_revert(struct iov_iter *i, size_t unroll) +{ + const struct bvecq *bq =3D i->bvecq; + unsigned int slot =3D i->bvecq_slot; + + for (;;) { + size_t len; + + if (slot =3D=3D 0) { + bq =3D bq->prev; + slot =3D bq->nr_segs; + } + slot--; + + len =3D bq->bv[slot].bv_len; + if (unroll <=3D len) { + i->iov_offset =3D len - unroll; + break; + } + unroll -=3D len; + } + + i->bvecq_slot =3D slot; + i->bvecq =3D bq; +} + void iov_iter_revert(struct iov_iter *i, size_t unroll) { if (!unroll) @@ -639,6 +700,9 @@ void iov_iter_revert(struct iov_iter *i, size_t unroll) } else if (iov_iter_is_folioq(i)) { i->iov_offset =3D 0; iov_iter_folioq_revert(i, unroll); + } else if (iov_iter_is_bvecq(i)) { + i->iov_offset =3D 0; + iov_iter_bvecq_revert(i, unroll); } else { /* same logics for iovec and kvec */ const struct iovec *iov =3D iter_iov(i); while (1) { @@ -666,9 +730,12 @@ size_t iov_iter_single_seg_count(const struct iov_iter= *i) if (iov_iter_is_bvec(i)) return min(i->count, i->bvec->bv_len - i->iov_offset); } + if (!i->count) + return 0; if (unlikely(iov_iter_is_folioq(i))) - return !i->count ? 0 : - umin(folioq_folio_size(i->folioq, i->folioq_slot), i->count); + return umin(folioq_folio_size(i->folioq, i->folioq_slot), i->count); + if (unlikely(iov_iter_is_bvecq(i))) + return min(i->count, i->bvecq->bv[i->bvecq_slot].bv_len - i->iov_offset); return i->count; } EXPORT_SYMBOL(iov_iter_single_seg_count); @@ -735,6 +802,35 @@ void iov_iter_folio_queue(struct iov_iter *i, unsigned= int direction, } EXPORT_SYMBOL(iov_iter_folio_queue); =20 +/** + * iov_iter_bvec_queue - Initialise an I/O iterator to use a segmented bve= c queue + * @i: The iterator to initialise. + * @direction: The direction of the transfer. + * @bvecq: The starting point in the bvec queue. + * @first_slot: The first slot in the bvec queue to use + * @offset: The offset into the bvec in the first slot to start at + * @count: The size of the I/O buffer in bytes. + * + * Set up an I/O iterator to either draw data out of the buffers attached = to an + * inode or to inject data into those buffers. The pages *must* be preven= ted + * from evaporation, either by the caller. + */ +void iov_iter_bvec_queue(struct iov_iter *i, unsigned int direction, + const struct bvecq *bvecq, unsigned int first_slot, + unsigned int offset, size_t count) +{ + BUG_ON(direction & ~1); + *i =3D (struct iov_iter) { + .iter_type =3D ITER_BVECQ, + .data_source =3D direction, + .bvecq =3D bvecq, + .bvecq_slot =3D first_slot, + .count =3D count, + .iov_offset =3D offset, + }; +} +EXPORT_SYMBOL(iov_iter_bvec_queue); + /** * iov_iter_xarray - Initialise an I/O iterator to use the pages in an xar= ray * @i: The iterator to initialise. @@ -834,6 +930,42 @@ static bool iov_iter_aligned_bvec(const struct iov_ite= r *i, unsigned addr_mask, return true; } =20 +static bool iov_iter_aligned_bvecq(const struct iov_iter *iter, unsigned l= ong addr_mask, + unsigned long len_mask) +{ + const struct bvecq *bq =3D iter->bvecq; + unsigned int slot =3D iter->bvecq_slot; + size_t skip =3D iter->iov_offset; + size_t size =3D iter->count; + + if (slot =3D=3D bq->nr_segs) { + /* The iterator may have been extended. */ + bq =3D bq->next; + slot =3D 0; + } + + for (;;) { + const struct bio_vec *bvec =3D &bq->bv[slot]; + size_t part; + + part =3D umin(bvec->bv_len - skip, size); + if (part & len_mask) + return false; + if ((bvec->bv_offset + skip) & addr_mask) + return false; + if (part >=3D size) + return true; + + size -=3D part; + skip =3D 0; + slot++; + if (slot =3D=3D bq->nr_segs) { + bq++; + slot =3D 0; + } + } +} + /** * iov_iter_is_aligned() - Check if the addresses and lengths of each segm= ents * are aligned to the parameters. @@ -875,6 +1007,9 @@ bool iov_iter_is_aligned(const struct iov_iter *i, uns= igned addr_mask, return false; } =20 + if (iov_iter_is_bvecq(i)) + return iov_iter_aligned_bvecq(i, addr_mask, len_mask); + return true; } EXPORT_SYMBOL_GPL(iov_iter_is_aligned); @@ -922,6 +1057,40 @@ static unsigned long iov_iter_alignment_bvec(const st= ruct iov_iter *i) return res; } =20 +static unsigned long iov_iter_alignment_bvecq(const struct iov_iter *iter) +{ + const struct bvecq *bq =3D iter->bvecq; + unsigned long res =3D 0; + unsigned int slot =3D iter->bvecq_slot; + size_t skip =3D iter->iov_offset; + size_t size =3D iter->count; + + if (slot =3D=3D bq->nr_segs) { + /* The iterator may have been extended. */ + bq =3D bq->next; + slot =3D 0; + } + + for (;;) { + const struct bio_vec *bvec =3D &bq->bv[slot]; + size_t part; + + part =3D umin(bvec->bv_len - skip, size); + res |=3D bvec->bv_offset + skip; + res |=3D part; + + size -=3D part; + skip =3D 0; + slot++; + if (slot =3D=3D bq->nr_segs) { + bq++; + slot =3D 0; + } + } + + return res; +} + unsigned long iov_iter_alignment(const struct iov_iter *i) { if (likely(iter_is_ubuf(i))) { @@ -941,6 +1110,8 @@ unsigned long iov_iter_alignment(const struct iov_iter= *i) /* With both xarray and folioq types, we're dealing with whole folios. */ if (iov_iter_is_folioq(i)) return i->iov_offset | i->count; + if (iov_iter_is_bvecq(i)) + return iov_iter_alignment_bvecq(i); if (iov_iter_is_xarray(i)) return (i->xarray_start + i->iov_offset) | i->count; =20 @@ -1275,6 +1446,38 @@ static int bvec_npages(const struct iov_iter *i, int= maxpages) return npages; } =20 +static size_t iov_npages_bvecq(const struct iov_iter *iter, size_t maxpage= s) +{ + const struct bvecq *bq =3D iter->bvecq; + unsigned int slot =3D iter->bvecq_slot; + size_t npages =3D 0; + size_t skip =3D iter->iov_offset; + size_t size =3D iter->count; + + if (slot =3D=3D bq->nr_segs) { + /* The iterator may have been extended. */ + bq =3D bq->next; + slot =3D 0; + } + + do { + const struct bio_vec *bvec =3D &bq->bv[slot]; + size_t offs =3D (bvec->bv_offset + skip) % PAGE_SIZE; + size_t part =3D umin(bvec->bv_len - skip, size); + + npages +=3D DIV_ROUND_UP(offs + part, PAGE_SIZE); + + size -=3D part; + skip =3D 0; + slot++; + if (slot =3D=3D bq->nr_segs) { + bq++; + slot =3D 0; + } + } while (npages > maxpages); + return umin(npages, maxpages); +} + int iov_iter_npages(const struct iov_iter *i, int maxpages) { if (unlikely(!i->count)) @@ -1294,6 +1497,8 @@ int iov_iter_npages(const struct iov_iter *i, int max= pages) int npages =3D DIV_ROUND_UP(offset + i->count, PAGE_SIZE); return min(npages, maxpages); } + if (iov_iter_is_bvecq(i)) + return iov_npages_bvecq(i, maxpages); if (iov_iter_is_xarray(i)) { unsigned offset =3D (i->xarray_start + i->iov_offset) % PAGE_SIZE; int npages =3D DIV_ROUND_UP(offset + i->count, PAGE_SIZE); @@ -1637,6 +1842,65 @@ static ssize_t iov_iter_extract_folioq_pages(struct = iov_iter *i, return extracted; } =20 +/* + * Extract a list of virtually contiguous pages from an ITER_BVECQ iterato= r. + * This does not get references on the pages, nor does it get a pin on the= m. + */ +static ssize_t iov_iter_extract_bvecq_pages(struct iov_iter *i, + struct page ***pages, size_t maxsize, + unsigned int maxpages, + iov_iter_extraction_t extraction_flags, + size_t *offset0) +{ + const struct bvecq *bq =3D i->bvecq; + struct bvec_iter bi; + size_t size =3D 0; + int k =3D 0; + + bi.bi_idx =3D i->bvecq_slot; + bi.bi_size =3D maxsize; + bi.bi_bvec_done =3D i->iov_offset; + + maxpages =3D want_pages_array(pages, maxsize, i->iov_offset, maxpages); + + while (bi.bi_size && bi.bi_idx < bq->nr_segs) { + struct bio_vec bv =3D bvec_iter_bvec(bq->bv, bi); + + /* + * The iov_iter_extract_pages interface only allows an offset + * into the first page. Break out of the loop if we see an + * offset into subsequent pages, the caller will have to call + * iov_iter_extract_pages again for the reminder. + */ + if (k) { + if (bv.bv_offset) + break; + } else { + *offset0 =3D bv.bv_offset; + } + + (*pages)[k++] =3D bv.bv_page; + size +=3D bv.bv_len; + + if (k >=3D maxpages) + break; + + /* + * We are done when the end of the bvec doesn't align to a page + * boundary as that would create a hole in the returned space. + * The caller will handle this with another call to + * iov_iter_extract_pages. + */ + if (bv.bv_offset + bv.bv_len !=3D PAGE_SIZE) + break; + + bvec_iter_advance_single(bq->bv, &bi, bv.bv_len); + } + + iov_iter_advance(i, size); + return size; +} + /* * Extract a list of contiguous pages from an ITER_XARRAY iterator. This = does not * get references on the pages, nor does it get a pin on them. @@ -1921,6 +2185,10 @@ ssize_t iov_iter_extract_pages(struct iov_iter *i, return iov_iter_extract_folioq_pages(i, pages, maxsize, maxpages, extraction_flags, offset0); + if (iov_iter_is_bvecq(i)) + return iov_iter_extract_bvecq_pages(i, pages, maxsize, + maxpages, extraction_flags, + offset0); if (iov_iter_is_xarray(i)) return iov_iter_extract_xarray_pages(i, pages, maxsize, maxpages, extraction_flags, @@ -1995,6 +2263,57 @@ size_t iterate_discard(struct iov_iter *iter, size_t= len, void *priv, void *priv return progress; } =20 +/* + * Handle ITER_BVECQ. + */ +static __always_inline +size_t iterate_bvecq(struct iov_iter *iter, size_t len, void *priv, void *= priv2, + iov_step_f step) +{ + const struct bvecq *bq =3D iter->bvecq; + unsigned int slot =3D iter->bvecq_slot; + size_t progress =3D 0, skip =3D iter->iov_offset; + + if (slot =3D=3D bq->nr_segs) { + /* The iterator may have been extended. */ + bq =3D bq->next; + slot =3D 0; + } + + do { + const struct bio_vec *bvec =3D &bq->bv[slot]; + struct page *page =3D bvec->bv_page + (bvec->bv_offset + skip) / PAGE_SI= ZE; + size_t part, remain, consumed; + size_t poff =3D (bvec->bv_offset + skip) % PAGE_SIZE; + void *base; + + part =3D umin(umin(bvec->bv_len, PAGE_SIZE - poff), len); + base =3D kmap_local_page(page) + poff; + remain =3D step(base, progress, part, priv, priv2); + kunmap_local(base); + consumed =3D part - remain; + len -=3D consumed; + progress +=3D consumed; + skip +=3D consumed; + if (skip >=3D bvec->bv_len) { + skip =3D 0; + slot++; + if (slot =3D=3D bq->nr_segs) { + bq =3D bq->next; + slot =3D 0; + } + } + if (remain) + break; + } while (len); + + iter->bvecq_slot =3D slot; + iter->bvecq =3D bq; + iter->iov_offset =3D skip; + iter->count -=3D progress; + return progress; +} + /* * Out of line iteration for iterator types that don't need such fast hand= ling. */ @@ -2003,6 +2322,8 @@ size_t __iterate_and_advance2(struct iov_iter *iter, = size_t len, void *priv, { if (iov_iter_is_discard(iter)) return iterate_discard(iter, len, priv, priv2, step); + if (iov_iter_is_bvecq(iter)) + return iterate_bvecq(iter, len, priv, priv2, step); if (iov_iter_is_xarray(iter)) return iterate_xarray(iter, len, priv, priv2, step); WARN_ON(1); diff --git a/lib/tests/kunit_iov_iter.c b/lib/tests/kunit_iov_iter.c index 48342736d016..4c62b509c949 100644 --- a/lib/tests/kunit_iov_iter.c +++ b/lib/tests/kunit_iov_iter.c @@ -536,6 +536,200 @@ static void __init iov_kunit_copy_from_folioq(struct = kunit *test) KUNIT_SUCCEED(test); } =20 +static void iov_kunit_destroy_bvecq(void *data) +{ + struct bvecq *bq, *next; + + for (bq =3D data; bq; bq =3D next) { + next =3D bq->next; + for (int i =3D 0; i < bq->nr_segs; i++) + if (bq->bv[i].bv_page) + put_page(bq->bv[i].bv_page); + kfree(bq); + } +} + +static struct bvecq *iov_kunit_alloc_bvecq(struct kunit *test, unsigned in= t max_segs) +{ + struct bvecq *bq; + + bq =3D kzalloc(struct_size(bq, bv, max_segs), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, bq); + bq->max_segs =3D max_segs; + return bq; +} + +static struct bvecq *iov_kunit_create_bvecq(struct kunit *test, unsigned i= nt max_segs) +{ + struct bvecq *bq; + + bq =3D iov_kunit_alloc_bvecq(test, max_segs); + kunit_add_action_or_reset(test, iov_kunit_destroy_bvecq, bq); + return bq; +} + +static void __init iov_kunit_load_bvecq(struct kunit *test, + struct iov_iter *iter, int dir, + struct bvecq *bq_head, + struct page **pages, size_t npages) +{ + struct bvecq *bq =3D bq_head; + size_t size =3D 0; + + for (int i =3D 0; i < npages; i++) { + if (bq->nr_segs >=3D bq->max_segs) { + bq->next =3D iov_kunit_alloc_bvecq(test, 8); + bq->next->prev =3D bq; + bq =3D bq->next; + } + bvec_set_page(&bq->bv[bq->nr_segs], pages[i], PAGE_SIZE, 0); + bq->nr_segs++; + size +=3D PAGE_SIZE; + } + iov_iter_bvec_queue(iter, dir, bq_head, 0, 0, size); +} + +#if 0 +static void dump_bvecq(const struct bvecq *bq) +{ + int j =3D 0; + + printk("Dump:\n"); + for (; bq; bq =3D bq->next, j++) { + for (int i =3D 0; i < bq->nr_segs; i++) { + const struct bio_vec *bv =3D &bq->bv[i]; + + printk(" [%x:%02x] %lx %04x %04x\n", + j, i, page_to_pfn(bv->bv_page), bv->bv_offset, bv->bv_len); + } + } +} +#endif + +/* + * Test copying to a ITER_BVECQ-type iterator. + */ +static void __init iov_kunit_copy_to_bvecq(struct kunit *test) +{ + const struct kvec_test_range *pr; + struct iov_iter iter; + struct bvecq *bq; + struct page **spages, **bpages; + u8 *scratch, *buffer; + size_t bufsize, npages, size, copied; + int i, patt; + + bufsize =3D 0x100000; + npages =3D bufsize / PAGE_SIZE; + + bq =3D iov_kunit_create_bvecq(test, 8); + + scratch =3D iov_kunit_create_buffer(test, &spages, npages); + for (i =3D 0; i < bufsize; i++) + scratch[i] =3D pattern(i); + + buffer =3D iov_kunit_create_buffer(test, &bpages, npages); + memset(buffer, 0, bufsize); + + iov_kunit_load_bvecq(test, &iter, READ, bq, bpages, npages); + + i =3D 0; + for (pr =3D kvec_test_ranges; pr->from >=3D 0; pr++) { + size =3D pr->to - pr->from; + KUNIT_ASSERT_LE(test, pr->to, bufsize); + + iov_iter_bvec_queue(&iter, READ, bq, 0, 0, pr->to); + iov_iter_advance(&iter, pr->from); + copied =3D copy_to_iter(scratch + i, size, &iter); + + KUNIT_EXPECT_EQ(test, copied, size); + KUNIT_EXPECT_EQ(test, iter.count, 0); + i +=3D size; + if (test->status =3D=3D KUNIT_FAILURE) + goto stop; + } + + /* Build the expected image in the scratch buffer. */ + patt =3D 0; + memset(scratch, 0, bufsize); + for (pr =3D kvec_test_ranges; pr->from >=3D 0; pr++) + for (i =3D pr->from; i < pr->to; i++) + scratch[i] =3D pattern(patt++); + + /* Compare the images */ + for (i =3D 0; i < bufsize; i++) { + KUNIT_EXPECT_EQ_MSG(test, buffer[i], scratch[i], "at i=3D%x", i); + if (buffer[i] !=3D scratch[i]) + return; + } + +stop: + KUNIT_SUCCEED(test); +} + +/* + * Test copying from a ITER_BVECQ-type iterator. + */ +static void __init iov_kunit_copy_from_bvecq(struct kunit *test) +{ + const struct kvec_test_range *pr; + struct iov_iter iter; + struct bvecq *bq; + struct page **spages, **bpages; + u8 *scratch, *buffer; + size_t bufsize, npages, size, copied; + int i, j; + + bufsize =3D 0x100000; + npages =3D bufsize / PAGE_SIZE; + + bq =3D iov_kunit_create_bvecq(test, 8); + + buffer =3D iov_kunit_create_buffer(test, &bpages, npages); + for (i =3D 0; i < bufsize; i++) + buffer[i] =3D pattern(i); + + scratch =3D iov_kunit_create_buffer(test, &spages, npages); + memset(scratch, 0, bufsize); + + iov_kunit_load_bvecq(test, &iter, READ, bq, bpages, npages); + + i =3D 0; + for (pr =3D kvec_test_ranges; pr->from >=3D 0; pr++) { + size =3D pr->to - pr->from; + KUNIT_ASSERT_LE(test, pr->to, bufsize); + + iov_iter_bvec_queue(&iter, WRITE, bq, 0, 0, pr->to); + iov_iter_advance(&iter, pr->from); + copied =3D copy_from_iter(scratch + i, size, &iter); + + KUNIT_EXPECT_EQ(test, copied, size); + KUNIT_EXPECT_EQ(test, iter.count, 0); + i +=3D size; + } + + /* Build the expected image in the main buffer. */ + i =3D 0; + memset(buffer, 0, bufsize); + for (pr =3D kvec_test_ranges; pr->from >=3D 0; pr++) { + for (j =3D pr->from; j < pr->to; j++) { + buffer[i++] =3D pattern(j); + if (i >=3D bufsize) + goto stop; + } + } +stop: + + /* Compare the images */ + for (i =3D 0; i < bufsize; i++) { + KUNIT_EXPECT_EQ_MSG(test, scratch[i], buffer[i], "at i=3D%x", i); + if (scratch[i] !=3D buffer[i]) + return; + } + + KUNIT_SUCCEED(test); +} + static void iov_kunit_destroy_xarray(void *data) { struct xarray *xarray =3D data; @@ -1016,6 +1210,8 @@ static struct kunit_case __refdata iov_kunit_cases[] = =3D { KUNIT_CASE(iov_kunit_copy_from_bvec), KUNIT_CASE(iov_kunit_copy_to_folioq), KUNIT_CASE(iov_kunit_copy_from_folioq), + KUNIT_CASE(iov_kunit_copy_to_bvecq), + KUNIT_CASE(iov_kunit_copy_from_bvecq), KUNIT_CASE(iov_kunit_copy_to_xarray), KUNIT_CASE(iov_kunit_copy_from_xarray), KUNIT_CASE(iov_kunit_extract_pages_kvec), From nobody Thu Dec 18 03:20:29 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2857C28ECDF for ; Wed, 6 Aug 2025 20:37:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512656; cv=none; b=MXw3CM/Ivn4RtxcRFh4wBZd6rRlshlBPqCO0FlCFUgTPwgq2l7h4w30f+KqvsqIBxGuQghLyca9zb6sYu3qV4pL6wc8B5nJ5fn+188AmRuh6IVFsodMHuITnZ+IJal9uf28fBpgqUVU0fAYC0nIaaAwqFdobJl8auW5GK2pU+Jw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512656; c=relaxed/simple; bh=zFXr2oXQU+wPk/q5XsK8v86y9WuV/IbDF9bSqLPil4Y=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=sZn/DkRApeLkIIMRijFqtWA8AcawOWUQzBvoNuai7mHpgyHfQMYXRdHNK5ak0seSnfReOaSLTXSPoHWW0JrieFkDmdPmTRWKC6STZNFyVY0xyQCjpYL+FnoLwOobxSjQMhzScpVKthVBr1DygAMOiqJdq60L7p33iCVwJ1A4MiE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=Bxs4OCqa; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="Bxs4OCqa" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1754512654; h=from:from:reply-to:subject:subject: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=0mTAcddqTdegcI9wUTwXmRYAU82kYQG5FuBK4SvQ8fY=; b=Bxs4OCqaoNQhRZeq1lzpsebWXbB3xTmZA7YvzZE/OHUxWUkoONnZfekSvGVC5vxDapglcO hV2xDM+Q/Z4m1pqgkVMyD3Wpxqjb9eB6pcHjJa9bKhkb0iPzFQD07vyfIz9pnIX4vA3Sio alx2+h5schh8i3id4140A4gtgyDO0r8= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-651-BqD1cXXONoq46jbUZGk4Yw-1; Wed, 06 Aug 2025 16:37:31 -0400 X-MC-Unique: BqD1cXXONoq46jbUZGk4Yw-1 X-Mimecast-MFC-AGG-ID: BqD1cXXONoq46jbUZGk4Yw_1754512649 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 39AE618003FC; Wed, 6 Aug 2025 20:37:29 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.17]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 9CFD630001A2; Wed, 6 Aug 2025 20:37:25 +0000 (UTC) From: David Howells To: Steve French Cc: David Howells , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Wang Zhaolong , Stefan Metzmacher , Mina Almasry , linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org, netfs@lists.linux.dev, linux-fsdevel@vger.kernel.org Subject: [RFC PATCH 03/31] netfs: Provide facility to alloc buffer in a bvecq Date: Wed, 6 Aug 2025 21:36:24 +0100 Message-ID: <20250806203705.2560493-4-dhowells@redhat.com> In-Reply-To: <20250806203705.2560493-1-dhowells@redhat.com> References: <20250806203705.2560493-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Content-Type: text/plain; charset="utf-8" Provide facility to allocate a series of bvecq structs and to attach sufficient pages to that series to provide a buffer for the specified amount of space. This can be used to do things like creating an encryption buffer in cifs and it can then be attached to an ITER_BVECQ iterator and passed to a socket. Signed-off-by: David Howells cc: Steve French cc: Paulo Alcantara cc: Shyam Prasad N cc: Tom Talpey cc: linux-cifs@vger.kernel.org cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/netfs/Makefile | 1 + fs/netfs/buffer.c | 101 ++++++++++++++++++++++++++++++++++++++++++ include/linux/netfs.h | 4 ++ 3 files changed, 106 insertions(+) create mode 100644 fs/netfs/buffer.c diff --git a/fs/netfs/Makefile b/fs/netfs/Makefile index b43188d64bd8..afab6603bd98 100644 --- a/fs/netfs/Makefile +++ b/fs/netfs/Makefile @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 =20 netfs-y :=3D \ + buffer.o \ buffered_read.o \ buffered_write.o \ direct_read.o \ diff --git a/fs/netfs/buffer.c b/fs/netfs/buffer.c new file mode 100644 index 000000000000..1e4ed2746e95 --- /dev/null +++ b/fs/netfs/buffer.c @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Buffering helpers for bvec_queues + * + * Copyright (C) 2025 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + */ +#include "internal.h" + +void dump_bvecq(const struct bvecq *bq) +{ + int b =3D 0; + + for (; bq; bq =3D bq->next, b++) { + printk("BQ[%u] %u/%u\n", b, bq->nr_segs, bq->max_segs); + for (int s =3D 0; s < bq->nr_segs; s++) { + const struct bio_vec *bv =3D &bq->bv[s]; + printk("BQ[%u:%u] %10lx %04x %04x %u\n", + b, s, + bv->bv_page ? page_to_pfn(bv->bv_page) : 0, + bv->bv_offset, bv->bv_len, + page_count(bv->bv_page)); + } + } +} + +/** + * netfs_alloc_bvecq_buffer - Allocate buffer space into a bvec queue + * @size: Target size of the buffer. + * @pre_slots: Number of preamble slots to set aside + * @gfp: The allocation constraints. + */ +struct bvecq *netfs_alloc_bvecq_buffer(size_t size, unsigned int pre_slots= , gfp_t gfp) +{ + struct bvecq *head =3D NULL, *tail =3D NULL, *p =3D NULL; + size_t count =3D DIV_ROUND_UP(size, PAGE_SIZE); + int max_segs =3D 32; + + _enter("%zx,%zx,%u", size, count, pre_slots); + + do { + struct page **pages; + int want, got; + + p =3D kzalloc(struct_size(p, bv, max_segs), gfp); + if (!p) + goto oom; + if (tail) { + tail->next =3D p; + p->prev =3D tail; + } else { + head =3D p; + } + tail =3D p; + pages =3D (struct page **)&p->bv[max_segs]; + pages -=3D max_segs - pre_slots; + + want =3D umin(count, max_segs - pre_slots); + got =3D alloc_pages_bulk(gfp, want, pages); + if (got < want) { + for (int i =3D 0; i < got; i++) + __free_page(pages[i]); + goto oom; + } + + tail->max_segs =3D max_segs; + tail->nr_segs =3D pre_slots + got; + for (int i =3D 0; i < got; i++) { + int j =3D pre_slots + i; + set_page_count(pages[i], 1); + bvec_set_page(&tail->bv[j], pages[i], PAGE_SIZE, 0); + } + + count -=3D got; + pre_slots =3D 0; + } while (count > 0); + + return head; +oom: + netfs_free_bvecq_buffer(head); + return NULL; +} +EXPORT_SYMBOL(netfs_alloc_bvecq_buffer); + +/** + * netfs_free_bvecq_buffer - Free a bvec queue + * @bq: The start of the folio queue to free + * + * Free up a chain of bvecqs and the pages it points to. + */ +void netfs_free_bvecq_buffer(struct bvecq *bq) +{ + struct bvecq *next; + + for (; bq; bq =3D next) { + for (int seg =3D 0; seg < bq->nr_segs; seg++) + __free_page(bq->bv[seg].bv_page); + next =3D bq->next; + kfree(bq); + } +} +EXPORT_SYMBOL(netfs_free_bvecq_buffer); diff --git a/include/linux/netfs.h b/include/linux/netfs.h index f43f075852c0..8756129b7472 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -23,6 +23,7 @@ enum netfs_sreq_ref_trace; typedef struct mempool_s mempool_t; struct folio_queue; +struct bvecq; =20 /** * folio_start_private_2 - Start an fscache write on a folio. [DEPRECATED] @@ -462,6 +463,9 @@ int netfs_alloc_folioq_buffer(struct address_space *map= ping, struct folio_queue **_buffer, size_t *_cur_size, ssize_t size, gfp_t gfp); void netfs_free_folioq_buffer(struct folio_queue *fq); +void dump_bvecq(const struct bvecq *bq); +struct bvecq *netfs_alloc_bvecq_buffer(size_t size, unsigned int pre_slots= , gfp_t gfp); +void netfs_free_bvecq_buffer(struct bvecq *bq); =20 /** * netfs_inode - Get the netfs inode context from the inode From nobody Thu Dec 18 03:20:29 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3812B2BD5B9 for ; Wed, 6 Aug 2025 20:37:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512663; cv=none; b=RFtxGzEFCq7o87OQiDc9gNbfqXDOSYDyLtArOOYB3laEsNaTUeBAG6jyb0wKYlOqZ33fgncOTusc9rdUvrQM28Zvx2dBWHIgL699cgHPYWVjjyAz3HI2vB01MdPEuvl62BGrqmvVJm0P+I7bJ3JLBUgY2NNKNZazC2cIhYindjw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512663; c=relaxed/simple; bh=Cz7mmpHuGqCeQqdDmoKo+SSe5T0TEhmQR5v3P1DDHuo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=u1DkI3Ka2xXfT7dCzr2063l2Nv0T0DU2d0V9kUE4h74y/WFA1AXUGD5ZnOiD8ZewMkRizdnylri9uQ1NmAjl3qM0M/epkCSlI/Yr90QmbbyZM+vPTSw6PDv68GY+uilS3TYnYAW2MSpnrsbiQTH1tiNADMOj4RvBJ7WWrYS7L2s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=P7WhLWBr; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="P7WhLWBr" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1754512660; h=from:from:reply-to:subject:subject: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=Pgw2HEBWL/o6lds7Ytffz5iXDstSedUrccIm0ypOU1Q=; b=P7WhLWBrEkZ8amiwptCKGkf4Cn06TtL6KTCgUREXfQpW2nQOFmJ4VZkIfNrKt/BynUyiGY gM2Z6W4RtTgC/UenmoR7Eem1QKnxoc7lg71scyqG4AQwGJBM8h2K1WBEi4SUnYx/NFDwSJ bBgD7y0FElvyFONI6YTSPEyyizmoN1w= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-203-39d-sI9KMkumubDWD5AxSg-1; Wed, 06 Aug 2025 16:37:35 -0400 X-MC-Unique: 39d-sI9KMkumubDWD5AxSg-1 X-Mimecast-MFC-AGG-ID: 39d-sI9KMkumubDWD5AxSg_1754512654 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 0A1A218002B4; Wed, 6 Aug 2025 20:37:34 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.17]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id AAE81180047F; Wed, 6 Aug 2025 20:37:30 +0000 (UTC) From: David Howells To: Steve French Cc: David Howells , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Wang Zhaolong , Stefan Metzmacher , Mina Almasry , linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org, netfs@lists.linux.dev, linux-fsdevel@vger.kernel.org Subject: [RFC PATCH 04/31] cifs, nls: Provide unicode size determination func Date: Wed, 6 Aug 2025 21:36:25 +0100 Message-ID: <20250806203705.2560493-5-dhowells@redhat.com> In-Reply-To: <20250806203705.2560493-1-dhowells@redhat.com> References: <20250806203705.2560493-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Howells cc: Steve French cc: Paulo Alcantara cc: Shyam Prasad N cc: Tom Talpey cc: linux-cifs@vger.kernel.org cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/nls/nls_base.c | 33 ++++++++++++++++++++++++++++++ fs/smb/client/cifs_unicode.c | 39 ++++++++++++++++++++++++++++++++++++ fs/smb/client/cifs_unicode.h | 2 ++ include/linux/nls.h | 1 + 4 files changed, 75 insertions(+) diff --git a/fs/nls/nls_base.c b/fs/nls/nls_base.c index 18d597e49a19..f6927c7d9fe1 100644 --- a/fs/nls/nls_base.c +++ b/fs/nls/nls_base.c @@ -171,6 +171,39 @@ int utf8s_to_utf16s(const u8 *s, int inlen, enum utf16= _endian endian, } EXPORT_SYMBOL(utf8s_to_utf16s); =20 +/** + * utf8s_to_len_utf16s - Determine the length of a conversion of UTF8 to U= TF16. + * @s: The source utf8 string + * @inlen: The length of the string + */ +ssize_t utf8s_to_len_utf16s(const u8 *s, int inlen) +{ + unicode_t u; + size_t outcount =3D 0; + int size; + + while (inlen > 0 && *s) { + if (*s & 0x80) { + size =3D utf8_to_utf32(s, inlen, &u); + if (size < 0) + return -EINVAL; + s +=3D size; + inlen -=3D size; + + if (u >=3D PLANE_SIZE) + outcount +=3D 2; + else + outcount++; + } else { + s++; + outcount++; + inlen--; + } + } + return outcount * sizeof(wchar_t); +} +EXPORT_SYMBOL(utf8s_to_len_utf16s); + static inline unsigned long get_utf16(unsigned c, enum utf16_endian endian) { switch (endian) { diff --git a/fs/smb/client/cifs_unicode.c b/fs/smb/client/cifs_unicode.c index 4cc6e0896fad..ba4b361613f6 100644 --- a/fs/smb/client/cifs_unicode.c +++ b/fs/smb/client/cifs_unicode.c @@ -290,6 +290,45 @@ cifs_strtoUTF16(__le16 *to, const char *from, int len, return i; } =20 +/* + * Work out how long a string will be once converted to UTF16 in bytes. T= his + * does not include a NUL terminator. + */ +size_t cifs_size_strtoUTF16(const char *from, int len, + const struct nls_table *codepage) +{ + wchar_t wchar_to; /* needed to quiet sparse */ + ssize_t out_len =3D 0; + int charlen; + + /* special case for utf8 to handle no plane0 chars */ + if (strcmp(codepage->charset, "utf8") =3D=3D 0) { + out_len =3D utf8s_to_len_utf16s(from, len); + if (out_len >=3D 0) + goto success; + /* + * On failure, fall back to UCS encoding as this function + * should not return negative values currently can fail only if + * source contains invalid encoded characters + */ + } + + for (; len && *from; len -=3D charlen) { + charlen =3D codepage->char2uni(from, len, &wchar_to); + if (charlen < 1) { + cifs_dbg(VFS, "strtoUTF16: char2uni of 0x%x returned %d\n", + *from, charlen); + /* Replace with a question mark */ + charlen =3D 1; + } + from +=3D charlen; + out_len +=3D 2; + } + +success: + return out_len; +} + /* * cifs_utf16_bytes - how long will a string be after conversion? * @utf16 - pointer to input string diff --git a/fs/smb/client/cifs_unicode.h b/fs/smb/client/cifs_unicode.h index e137a0dfbbe9..c3519a46a2b5 100644 --- a/fs/smb/client/cifs_unicode.h +++ b/fs/smb/client/cifs_unicode.h @@ -60,6 +60,8 @@ int cifs_from_utf16(char *to, const __le16 *from, int tol= en, int fromlen, int cifs_utf16_bytes(const __le16 *from, int maxbytes, const struct nls_table *codepage); int cifs_strtoUTF16(__le16 *, const char *, int, const struct nls_table *); +size_t cifs_size_strtoUTF16(const char *from, int len, + const struct nls_table *codepage); char *cifs_strndup_from_utf16(const char *src, const int maxlen, const bool is_unicode, const struct nls_table *codepage); diff --git a/include/linux/nls.h b/include/linux/nls.h index e0bf8367b274..026da1d5ffaa 100644 --- a/include/linux/nls.h +++ b/include/linux/nls.h @@ -56,6 +56,7 @@ extern int utf8_to_utf32(const u8 *s, int len, unicode_t = *pu); extern int utf32_to_utf8(unicode_t u, u8 *s, int maxlen); extern int utf8s_to_utf16s(const u8 *s, int len, enum utf16_endian endian, wchar_t *pwcs, int maxlen); +ssize_t utf8s_to_len_utf16s(const u8 *s, int inlen); extern int utf16s_to_utf8s(const wchar_t *pwcs, int len, enum utf16_endian endian, u8 *s, int maxlen); From nobody Thu Dec 18 03:20:29 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 610402248AF for ; Wed, 6 Aug 2025 20:37:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512671; cv=none; b=cTd4r+RolNjDdk6zuRs2IwjW1MFbgBR+nepG/OfEU7egknRVBQnBHZvlJr2CDCouWNPyOeuzHjyTl+cZw6RlkC47StE0NUyXp5MCI4oel8Hu8JbZ/LFD7O4HeiHepbP86FmZOV4fJIsy3Wy69LdwLuTcZzK+QfD77QugAjbfGH8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512671; c=relaxed/simple; bh=ppNcHhXRisKv01c9cZ1qnAtYlgHVNCWEVHkzlLJLWGA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=TjJI5g9X+pHSaF3kcAeZWGQnyVe3Zd86Ol/w0s0zuPZuQNRyH/el26L4apPi2xAcxy4qCZV1v44vEVkgURMQmhoxjq/kIKk59mtAEYxqVB9EhE1voOR0mAhHlhB+rqeaqCfUxAPsg8bpj3E/6l/gdmmFpEijP0suHMsrTXGOveM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=WVhK5kIV; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="WVhK5kIV" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1754512668; h=from:from:reply-to:subject:subject: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=emfO1GPlFwZIV8t+Z04vg+2LWJzChrqCHQ/rDncitC0=; b=WVhK5kIVmPfZBog3DEeKO/5RIeLt/vNbKaedS9RSb/X9kZB3RyCcSYDggk6scFs4wrgu0c g0qscQUslDveE3JVBKDKyoQTPYq864EOwYS+Rh0zDWf4pHrbhoisEtabaq3AKFPFUmwgPx 1A5e+6e/cApmKDjx9OqiqlDoe15wOcA= Received: from mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-307-szfcuH63M1iJfTs8avUUlQ-1; Wed, 06 Aug 2025 16:37:43 -0400 X-MC-Unique: szfcuH63M1iJfTs8avUUlQ-1 X-Mimecast-MFC-AGG-ID: szfcuH63M1iJfTs8avUUlQ_1754512659 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id D8FBC1956095; Wed, 6 Aug 2025 20:37:38 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.17]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 9B7211800446; Wed, 6 Aug 2025 20:37:35 +0000 (UTC) From: David Howells To: Steve French Cc: David Howells , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Wang Zhaolong , Stefan Metzmacher , Mina Almasry , linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org, netfs@lists.linux.dev, linux-fsdevel@vger.kernel.org Subject: [RFC PATCH 05/31] cifs: Introduce an ALIGN8() macro Date: Wed, 6 Aug 2025 21:36:26 +0100 Message-ID: <20250806203705.2560493-6-dhowells@redhat.com> In-Reply-To: <20250806203705.2560493-1-dhowells@redhat.com> References: <20250806203705.2560493-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Content-Type: text/plain; charset="utf-8" The PDU generation seems to do ALIGN(x, 8) a lot, so make a macro for that. Signed-off-by: David Howells cc: Steve French cc: Paulo Alcantara cc: Shyam Prasad N cc: Tom Talpey cc: linux-cifs@vger.kernel.org cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/smb/client/cifsglob.h | 2 ++ fs/smb/client/reparse.c | 2 +- fs/smb/client/smb2file.c | 2 +- fs/smb/client/smb2misc.c | 2 +- fs/smb/client/smb2pdu.c | 28 ++++++++++++++-------------- 5 files changed, 19 insertions(+), 17 deletions(-) diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index 89160bc34d35..67c1a63a08ba 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h @@ -2375,4 +2375,6 @@ static inline bool cifs_netbios_name(const char *name= , size_t namelen) return ret; } =20 +#define ALIGN8(x) ALIGN((x), 8) + #endif /* _CIFS_GLOB_H */ diff --git a/fs/smb/client/reparse.c b/fs/smb/client/reparse.c index 5fa29a97ac15..2622f90ebc92 100644 --- a/fs/smb/client/reparse.c +++ b/fs/smb/client/reparse.c @@ -571,7 +571,7 @@ static struct smb2_create_ea_ctx *ea_create_context(u32= dlen, size_t *cc_len) { struct smb2_create_ea_ctx *cc; =20 - *cc_len =3D round_up(sizeof(*cc) + dlen, 8); + *cc_len =3D ALIGN8(sizeof(*cc) + dlen); cc =3D kzalloc(*cc_len, GFP_KERNEL); if (!cc) return ERR_PTR(-ENOMEM); diff --git a/fs/smb/client/smb2file.c b/fs/smb/client/smb2file.c index a7f629238830..1c8fc06cd46f 100644 --- a/fs/smb/client/smb2file.c +++ b/fs/smb/client/smb2file.c @@ -48,7 +48,7 @@ static struct smb2_symlink_err_rsp *symlink_data(const st= ruct kvec *iov) cifs_dbg(FYI, "%s: skipping unhandled error context: 0x%x\n", __func__, le32_to_cpu(p->ErrorId)); =20 - len =3D ALIGN(le32_to_cpu(p->ErrorDataLength), 8); + len =3D ALIGN8(le32_to_cpu(p->ErrorDataLength)); p =3D (struct smb2_error_context_rsp *)(p->ErrorContextData + len); } while (p < end); } else if (le32_to_cpu(err->ByteCount) >=3D sizeof(*sym) && diff --git a/fs/smb/client/smb2misc.c b/fs/smb/client/smb2misc.c index cddf273c14ae..93ce9fc7b4a4 100644 --- a/fs/smb/client/smb2misc.c +++ b/fs/smb/client/smb2misc.c @@ -252,7 +252,7 @@ smb2_check_message(char *buf, unsigned int len, struct = TCP_Server_Info *server) * Some windows servers (win2016) will pad also the final * PDU in a compound to 8 bytes. */ - if (ALIGN(calc_len, 8) =3D=3D len) + if (ALIGN8(calc_len) =3D=3D len) return 0; =20 /* diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c index 2df93a75e3b8..96df4aa7a7af 100644 --- a/fs/smb/client/smb2pdu.c +++ b/fs/smb/client/smb2pdu.c @@ -619,14 +619,14 @@ build_signing_ctxt(struct smb2_signing_capabilities *= pneg_ctxt) /* * Context Data length must be rounded to multiple of 8 for some servers */ - pneg_ctxt->DataLength =3D cpu_to_le16(ALIGN(sizeof(struct smb2_signing_ca= pabilities) - + pneg_ctxt->DataLength =3D cpu_to_le16(ALIGN8(sizeof(struct smb2_signing_c= apabilities) - sizeof(struct smb2_neg_context) + - (num_algs * sizeof(u16)), 8)); + (num_algs * sizeof(u16)))); pneg_ctxt->SigningAlgorithmCount =3D cpu_to_le16(num_algs); pneg_ctxt->SigningAlgorithms[0] =3D cpu_to_le16(SIGNING_ALG_AES_CMAC); =20 ctxt_len +=3D sizeof(__le16) * num_algs; - ctxt_len =3D ALIGN(ctxt_len, 8); + ctxt_len =3D ALIGN8(ctxt_len); return ctxt_len; /* TBD add SIGNING_ALG_AES_GMAC and/or SIGNING_ALG_HMAC_SHA256 */ } @@ -663,7 +663,7 @@ build_netname_ctxt(struct smb2_netname_neg_context *pne= g_ctxt, char *hostname) /* copy up to max of first 100 bytes of server name to NetName field */ pneg_ctxt->DataLength =3D cpu_to_le16(2 * cifs_strtoUTF16(pneg_ctxt->NetN= ame, hostname, 100, cp)); /* context size is DataLength + minimal smb2_neg_context */ - return ALIGN(le16_to_cpu(pneg_ctxt->DataLength) + sizeof(struct smb2_neg_= context), 8); + return ALIGN8(le16_to_cpu(pneg_ctxt->DataLength) + sizeof(struct smb2_neg= _context)); } =20 static void @@ -709,18 +709,18 @@ assemble_neg_contexts(struct smb2_negotiate_req *req, * round up total_len of fixed part of SMB3 negotiate request to 8 * byte boundary before adding negotiate contexts */ - *total_len =3D ALIGN(*total_len, 8); + *total_len =3D ALIGN8(*total_len); =20 pneg_ctxt =3D (*total_len) + (char *)req; req->NegotiateContextOffset =3D cpu_to_le32(*total_len); =20 build_preauth_ctxt((struct smb2_preauth_neg_context *)pneg_ctxt); - ctxt_len =3D ALIGN(sizeof(struct smb2_preauth_neg_context), 8); + ctxt_len =3D ALIGN8(sizeof(struct smb2_preauth_neg_context)); *total_len +=3D ctxt_len; pneg_ctxt +=3D ctxt_len; =20 build_encrypt_ctxt((struct smb2_encryption_neg_context *)pneg_ctxt); - ctxt_len =3D ALIGN(sizeof(struct smb2_encryption_neg_context), 8); + ctxt_len =3D ALIGN8(sizeof(struct smb2_encryption_neg_context)); *total_len +=3D ctxt_len; pneg_ctxt +=3D ctxt_len; =20 @@ -749,7 +749,7 @@ assemble_neg_contexts(struct smb2_negotiate_req *req, if (server->compression.requested) { build_compression_ctxt((struct smb2_compression_capabilities_context *) pneg_ctxt); - ctxt_len =3D ALIGN(sizeof(struct smb2_compression_capabilities_context),= 8); + ctxt_len =3D ALIGN8(sizeof(struct smb2_compression_capabilities_context)= ); *total_len +=3D ctxt_len; pneg_ctxt +=3D ctxt_len; neg_context_count++; @@ -940,7 +940,7 @@ static int smb311_decode_neg_context(struct smb2_negoti= ate_rsp *rsp, * aligned offset following the previous negotiate context. */ if (i + 1 !=3D ctxt_cnt) - clen =3D ALIGN(clen, 8); + clen =3D ALIGN8(clen); if (clen > len_of_ctxts) break; =20 @@ -2631,7 +2631,7 @@ create_sd_buf(umode_t mode, bool set_owner, unsigned = int *len) unsigned int group_offset =3D 0; struct smb3_acl acl =3D {}; =20 - *len =3D round_up(sizeof(struct crt_sd_ctxt) + (sizeof(struct smb_ace) * = 4), 8); + *len =3D ALIGN8(sizeof(struct crt_sd_ctxt) + (sizeof(struct smb_ace) * 4)= ); =20 if (set_owner) { /* sizeof(struct owner_group_sids) is already multiple of 8 so no need t= o round */ @@ -2706,7 +2706,7 @@ create_sd_buf(umode_t mode, bool set_owner, unsigned = int *len) memcpy(aclptr, &acl, sizeof(struct smb3_acl)); =20 buf->ccontext.DataLength =3D cpu_to_le32(ptr - (__u8 *)&buf->sd); - *len =3D round_up((unsigned int)(ptr - (__u8 *)buf), 8); + *len =3D ALIGN8((unsigned int)(ptr - (__u8 *)buf)); =20 return buf; } @@ -2799,7 +2799,7 @@ alloc_path_with_tree_prefix(__le16 **out_path, int *o= ut_size, int *out_len, * final path needs to be 8-byte aligned as specified in * MS-SMB2 2.2.13 SMB2 CREATE Request. */ - *out_size =3D round_up(*out_len * sizeof(__le16), 8); + *out_size =3D ALIGN8(*out_len * sizeof(__le16)); *out_path =3D kzalloc(*out_size + sizeof(__le16) /* null */, GFP_KERNEL); if (!*out_path) return -ENOMEM; @@ -3064,7 +3064,7 @@ SMB2_open_init(struct cifs_tcon *tcon, struct TCP_Ser= ver_Info *server, uni_path_len =3D (2 * UniStrnlen((wchar_t *)path, PATH_MAX)) + 2; /* MUST set path len (NameLength) to 0 opening root of share */ req->NameLength =3D cpu_to_le16(uni_path_len - 2); - copy_size =3D round_up(uni_path_len, 8); + copy_size =3D ALIGN8(uni_path_len); copy_path =3D kzalloc(copy_size, GFP_KERNEL); if (!copy_path) return -ENOMEM; @@ -4490,7 +4490,7 @@ smb2_new_read_req(void **buf, unsigned int *total_len, if (request_type & CHAINED_REQUEST) { if (!(request_type & END_OF_CHAIN)) { /* next 8-byte aligned request */ - *total_len =3D ALIGN(*total_len, 8); + *total_len =3D ALIGN8(*total_len); shdr->NextCommand =3D cpu_to_le32(*total_len); } else /* END_OF_CHAIN */ shdr->NextCommand =3D 0; From nobody Thu Dec 18 03:20:29 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 07CEB22157B for ; Wed, 6 Aug 2025 20:37:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512671; cv=none; b=dHHEhEAC5MBOeE86BSS9S/8KYj/JjW9cJvAcM+x+iDXvlWZQbk7HKL04TSaZ0E2RsIG/uoyaE2zOG79yv5FhybF2Dl0QCcX5QErZgrB8TTyuJjidHJWOdl8DOsdJNml13bAzgG92HRcfTF5sWYfWMkcXLZ+6blaNjjD/1LrkUjw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512671; c=relaxed/simple; bh=li/hKqgRFk4+n+r5+SCLv4VH+KdtvY9xjpPt2/QLJ5E=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=g9XdSTC6ysuqvwdmgxtCeeEzDZcLvMbD3Mvu1lsiFpPYsl6si45mztiFG5G7V7WnJ6Nm2lmYSu8DDiyyoPgeVVpid1Q7mjqA/Lf2NJMrfCzCbxf4s13QtiOgfDxiIGZLtCnlfgWGq+QbZb6Jq/2Ppz8BBkn6FFqX9Oyo5pgOuKE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=WYjmLxdy; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="WYjmLxdy" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1754512666; h=from:from:reply-to:subject:subject: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=9TuHgqr0lIiE8hPLO+0aDHW4TmN9tj+Ru9/5tx2eGmY=; b=WYjmLxdyFo/tNEeUYgAqlF+qvwywUWAQKH9O86VepHLKo0DnXZ4ymY7pbkMvt/xlhCCLyl HUphq5O4sK/Lw3Tcwjhy7llBNYNVabZ6w5VqI7J3GJvvk66xaF527/j6Jsak/Rgwq3raIA KK2xKeIjN5CvzLN+3PJXyCX6fR7/QgU= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-626-rwyJsyy9PcqHWYVjEs9j-g-1; Wed, 06 Aug 2025 16:37:45 -0400 X-MC-Unique: rwyJsyy9PcqHWYVjEs9j-g-1 X-Mimecast-MFC-AGG-ID: rwyJsyy9PcqHWYVjEs9j-g_1754512664 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id EC19E180047F; Wed, 6 Aug 2025 20:37:43 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.17]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 735443000198; Wed, 6 Aug 2025 20:37:40 +0000 (UTC) From: David Howells To: Steve French Cc: David Howells , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Wang Zhaolong , Stefan Metzmacher , Mina Almasry , linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org, netfs@lists.linux.dev, linux-fsdevel@vger.kernel.org Subject: [RFC PATCH 06/31] cifs: Move the SMB1 transport code out of transport.c Date: Wed, 6 Aug 2025 21:36:27 +0100 Message-ID: <20250806203705.2560493-7-dhowells@redhat.com> In-Reply-To: <20250806203705.2560493-1-dhowells@redhat.com> References: <20250806203705.2560493-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Howells cc: Steve French cc: Paulo Alcantara cc: Shyam Prasad N cc: Tom Talpey cc: linux-cifs@vger.kernel.org cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/smb/client/Makefile | 2 +- fs/smb/client/cifsproto.h | 15 + fs/smb/client/cifstransport.c | 566 ++++++++++++++++++++++++++++++++++ fs/smb/client/transport.c | 559 +-------------------------------- 4 files changed, 588 insertions(+), 554 deletions(-) create mode 100644 fs/smb/client/cifstransport.c diff --git a/fs/smb/client/Makefile b/fs/smb/client/Makefile index 22023e30915b..4c97b31a25c2 100644 --- a/fs/smb/client/Makefile +++ b/fs/smb/client/Makefile @@ -32,6 +32,6 @@ cifs-$(CONFIG_CIFS_SMB_DIRECT) +=3D smbdirect.o =20 cifs-$(CONFIG_CIFS_ROOT) +=3D cifsroot.o =20 -cifs-$(CONFIG_CIFS_ALLOW_INSECURE_LEGACY) +=3D smb1ops.o cifssmb.o +cifs-$(CONFIG_CIFS_ALLOW_INSECURE_LEGACY) +=3D smb1ops.o cifssmb.o cifstra= nsport.o =20 cifs-$(CONFIG_CIFS_COMPRESSION) +=3D compress.o compress/lz77.o diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h index 045227ed4efc..8661ab105b4f 100644 --- a/fs/smb/client/cifsproto.h +++ b/fs/smb/client/cifsproto.h @@ -116,16 +116,31 @@ extern int SendReceive(const unsigned int /* xid */ ,= struct cifs_ses *, int * /* bytes returned */ , const int); extern int SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses, char *in_buf, int flags); +int cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *= server); extern struct mid_q_entry *cifs_setup_request(struct cifs_ses *, struct TCP_Server_Info *, struct smb_rqst *); extern struct mid_q_entry *cifs_setup_async_request(struct TCP_Server_Info= *, struct smb_rqst *); +int __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst, + struct smb_rqst *rqst); extern int cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, bool log_error); +int wait_for_free_request(struct TCP_Server_Info *server, const int flags, + unsigned int *instance); extern int cifs_wait_mtu_credits(struct TCP_Server_Info *server, size_t size, size_t *num, struct cifs_credits *credits); + +static inline int +send_cancel(struct TCP_Server_Info *server, struct smb_rqst *rqst, + struct mid_q_entry *mid) +{ + return server->ops->send_cancel ? + server->ops->send_cancel(server, rqst, mid) : 0; +} + +int wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *= midQ); extern int SendReceive2(const unsigned int /* xid */ , struct cifs_ses *, struct kvec *, int /* nvec to send */, int * /* type of buf returned */, const int flags, diff --git a/fs/smb/client/cifstransport.c b/fs/smb/client/cifstransport.c new file mode 100644 index 000000000000..241e0b427357 --- /dev/null +++ b/fs/smb/client/cifstransport.c @@ -0,0 +1,566 @@ +// SPDX-License-Identifier: LGPL-2.1 +/* + * + * Copyright (C) International Business Machines Corp., 2002,2008 + * Author(s): Steve French (sfrench@us.ibm.com) + * Jeremy Allison (jra@samba.org) 2006. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cifspdu.h" +#include "cifsglob.h" +#include "cifsproto.h" +#include "cifs_debug.h" +#include "smb2proto.h" +#include "smbdirect.h" +#include "compress.h" + +/* Max number of iovectors we can use off the stack when sending requests.= */ +#define CIFS_MAX_IOV_SIZE 8 + +static struct mid_q_entry * +alloc_mid(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server) +{ + struct mid_q_entry *temp; + + if (server =3D=3D NULL) { + cifs_dbg(VFS, "%s: null TCP session\n", __func__); + return NULL; + } + + temp =3D mempool_alloc(cifs_mid_poolp, GFP_NOFS); + memset(temp, 0, sizeof(struct mid_q_entry)); + kref_init(&temp->refcount); + temp->mid =3D get_mid(smb_buffer); + temp->pid =3D current->pid; + temp->command =3D cpu_to_le16(smb_buffer->Command); + cifs_dbg(FYI, "For smb_command %d\n", smb_buffer->Command); + /* easier to use jiffies */ + /* when mid allocated can be before when sent */ + temp->when_alloc =3D jiffies; + temp->server =3D server; + + /* + * The default is for the mid to be synchronous, so the + * default callback just wakes up the current task. + */ + get_task_struct(current); + temp->creator =3D current; + temp->callback =3D cifs_wake_up_task; + temp->callback_data =3D current; + + atomic_inc(&mid_count); + temp->mid_state =3D MID_REQUEST_ALLOCATED; + return temp; +} + +int +smb_send(struct TCP_Server_Info *server, struct smb_hdr *smb_buffer, + unsigned int smb_buf_length) +{ + struct kvec iov[2]; + struct smb_rqst rqst =3D { .rq_iov =3D iov, + .rq_nvec =3D 2 }; + + iov[0].iov_base =3D smb_buffer; + iov[0].iov_len =3D 4; + iov[1].iov_base =3D (char *)smb_buffer + 4; + iov[1].iov_len =3D smb_buf_length; + + return __smb_send_rqst(server, 1, &rqst); +} + +static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf, + struct mid_q_entry **ppmidQ) +{ + spin_lock(&ses->ses_lock); + if (ses->ses_status =3D=3D SES_NEW) { + if ((in_buf->Command !=3D SMB_COM_SESSION_SETUP_ANDX) && + (in_buf->Command !=3D SMB_COM_NEGOTIATE)) { + spin_unlock(&ses->ses_lock); + return -EAGAIN; + } + /* else ok - we are setting up session */ + } + + if (ses->ses_status =3D=3D SES_EXITING) { + /* check if SMB session is bad because we are setting it up */ + if (in_buf->Command !=3D SMB_COM_LOGOFF_ANDX) { + spin_unlock(&ses->ses_lock); + return -EAGAIN; + } + /* else ok - we are shutting down session */ + } + spin_unlock(&ses->ses_lock); + + *ppmidQ =3D alloc_mid(in_buf, ses->server); + if (*ppmidQ =3D=3D NULL) + return -ENOMEM; + spin_lock(&ses->server->mid_lock); + list_add_tail(&(*ppmidQ)->qhead, &ses->server->pending_mid_q); + spin_unlock(&ses->server->mid_lock); + return 0; +} + +struct mid_q_entry * +cifs_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *= rqst) +{ + int rc; + struct smb_hdr *hdr =3D (struct smb_hdr *)rqst->rq_iov[0].iov_base; + struct mid_q_entry *mid; + + if (rqst->rq_iov[0].iov_len !=3D 4 || + rqst->rq_iov[0].iov_base + 4 !=3D rqst->rq_iov[1].iov_base) + return ERR_PTR(-EIO); + + /* enable signing if server requires it */ + if (server->sign) + hdr->Flags2 |=3D SMBFLG2_SECURITY_SIGNATURE; + + mid =3D alloc_mid(hdr, server); + if (mid =3D=3D NULL) + return ERR_PTR(-ENOMEM); + + rc =3D cifs_sign_rqst(rqst, server, &mid->sequence_number); + if (rc) { + release_mid(mid); + return ERR_PTR(rc); + } + + return mid; +} + +/* + * + * Send an SMB Request. No response info (other than return code) + * needs to be parsed. + * + * flags indicate the type of request buffer and how long to wait + * and whether to log NT STATUS code (error) before mapping it to POSIX er= ror + * + */ +int +SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses, + char *in_buf, int flags) +{ + int rc; + struct kvec iov[1]; + struct kvec rsp_iov; + int resp_buf_type; + + iov[0].iov_base =3D in_buf; + iov[0].iov_len =3D get_rfc1002_length(in_buf) + 4; + flags |=3D CIFS_NO_RSP_BUF; + rc =3D SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags, &rsp_iov); + cifs_dbg(NOISY, "SendRcvNoRsp flags %d rc %d\n", flags, rc); + + return rc; +} + +int +cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, + bool log_error) +{ + unsigned int len =3D get_rfc1002_length(mid->resp_buf) + 4; + + dump_smb(mid->resp_buf, min_t(u32, 92, len)); + + /* convert the length into a more usable form */ + if (server->sign) { + struct kvec iov[2]; + int rc =3D 0; + struct smb_rqst rqst =3D { .rq_iov =3D iov, + .rq_nvec =3D 2 }; + + iov[0].iov_base =3D mid->resp_buf; + iov[0].iov_len =3D 4; + iov[1].iov_base =3D (char *)mid->resp_buf + 4; + iov[1].iov_len =3D len - 4; + /* FIXME: add code to kill session */ + rc =3D cifs_verify_signature(&rqst, server, + mid->sequence_number); + if (rc) + cifs_server_dbg(VFS, "SMB signature verification returned error =3D %d\= n", + rc); + } + + /* BB special case reconnect tid and uid here? */ + return map_and_check_smb_error(mid, log_error); +} + +struct mid_q_entry * +cifs_setup_request(struct cifs_ses *ses, struct TCP_Server_Info *ignored, + struct smb_rqst *rqst) +{ + int rc; + struct smb_hdr *hdr =3D (struct smb_hdr *)rqst->rq_iov[0].iov_base; + struct mid_q_entry *mid; + + if (rqst->rq_iov[0].iov_len !=3D 4 || + rqst->rq_iov[0].iov_base + 4 !=3D rqst->rq_iov[1].iov_base) + return ERR_PTR(-EIO); + + rc =3D allocate_mid(ses, hdr, &mid); + if (rc) + return ERR_PTR(rc); + rc =3D cifs_sign_rqst(rqst, ses->server, &mid->sequence_number); + if (rc) { + delete_mid(mid); + return ERR_PTR(rc); + } + return mid; +} + +int +SendReceive2(const unsigned int xid, struct cifs_ses *ses, + struct kvec *iov, int n_vec, int *resp_buf_type /* ret */, + const int flags, struct kvec *resp_iov) +{ + struct smb_rqst rqst; + struct kvec s_iov[CIFS_MAX_IOV_SIZE], *new_iov; + int rc; + + if (n_vec + 1 > CIFS_MAX_IOV_SIZE) { + new_iov =3D kmalloc_array(n_vec + 1, sizeof(struct kvec), + GFP_KERNEL); + if (!new_iov) { + /* otherwise cifs_send_recv below sets resp_buf_type */ + *resp_buf_type =3D CIFS_NO_BUFFER; + return -ENOMEM; + } + } else + new_iov =3D s_iov; + + /* 1st iov is a RFC1001 length followed by the rest of the packet */ + memcpy(new_iov + 1, iov, (sizeof(struct kvec) * n_vec)); + + new_iov[0].iov_base =3D new_iov[1].iov_base; + new_iov[0].iov_len =3D 4; + new_iov[1].iov_base +=3D 4; + new_iov[1].iov_len -=3D 4; + + memset(&rqst, 0, sizeof(struct smb_rqst)); + rqst.rq_iov =3D new_iov; + rqst.rq_nvec =3D n_vec + 1; + + rc =3D cifs_send_recv(xid, ses, ses->server, + &rqst, resp_buf_type, flags, resp_iov); + if (n_vec + 1 > CIFS_MAX_IOV_SIZE) + kfree(new_iov); + return rc; +} + +int +SendReceive(const unsigned int xid, struct cifs_ses *ses, + struct smb_hdr *in_buf, struct smb_hdr *out_buf, + int *pbytes_returned, const int flags) +{ + int rc =3D 0; + struct mid_q_entry *midQ; + unsigned int len =3D be32_to_cpu(in_buf->smb_buf_length); + struct kvec iov =3D { .iov_base =3D in_buf, .iov_len =3D len }; + struct smb_rqst rqst =3D { .rq_iov =3D &iov, .rq_nvec =3D 1 }; + struct cifs_credits credits =3D { .value =3D 1, .instance =3D 0 }; + struct TCP_Server_Info *server; + + if (ses =3D=3D NULL) { + cifs_dbg(VFS, "Null smb session\n"); + return -EIO; + } + server =3D ses->server; + if (server =3D=3D NULL) { + cifs_dbg(VFS, "Null tcp session\n"); + return -EIO; + } + + spin_lock(&server->srv_lock); + if (server->tcpStatus =3D=3D CifsExiting) { + spin_unlock(&server->srv_lock); + return -ENOENT; + } + spin_unlock(&server->srv_lock); + + /* Ensure that we do not send more than 50 overlapping requests + to the same server. We may make this configurable later or + use ses->maxReq */ + + if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { + cifs_server_dbg(VFS, "Invalid length, greater than maximum frame, %d\n", + len); + return -EIO; + } + + rc =3D wait_for_free_request(server, flags, &credits.instance); + if (rc) + return rc; + + /* make sure that we sign in the same order that we send on this socket + and avoid races inside tcp sendmsg code that could cause corruption + of smb data */ + + cifs_server_lock(server); + + rc =3D allocate_mid(ses, in_buf, &midQ); + if (rc) { + cifs_server_unlock(server); + /* Update # of requests on wire to server */ + add_credits(server, &credits, 0); + return rc; + } + + rc =3D cifs_sign_smb(in_buf, server, &midQ->sequence_number); + if (rc) { + cifs_server_unlock(server); + goto out; + } + + midQ->mid_state =3D MID_REQUEST_SUBMITTED; + + rc =3D smb_send(server, in_buf, len); + cifs_save_when_sent(midQ); + + if (rc < 0) + server->sequence_number -=3D 2; + + cifs_server_unlock(server); + + if (rc < 0) + goto out; + + rc =3D wait_for_response(server, midQ); + if (rc !=3D 0) { + send_cancel(server, &rqst, midQ); + spin_lock(&server->mid_lock); + if (midQ->mid_state =3D=3D MID_REQUEST_SUBMITTED || + midQ->mid_state =3D=3D MID_RESPONSE_RECEIVED) { + /* no longer considered to be "in-flight" */ + midQ->callback =3D release_mid; + spin_unlock(&server->mid_lock); + add_credits(server, &credits, 0); + return rc; + } + spin_unlock(&server->mid_lock); + } + + rc =3D cifs_sync_mid_result(midQ, server); + if (rc !=3D 0) { + add_credits(server, &credits, 0); + return rc; + } + + if (!midQ->resp_buf || !out_buf || + midQ->mid_state !=3D MID_RESPONSE_READY) { + rc =3D -EIO; + cifs_server_dbg(VFS, "Bad MID state?\n"); + goto out; + } + + *pbytes_returned =3D get_rfc1002_length(midQ->resp_buf); + memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4); + rc =3D cifs_check_receive(midQ, server, 0); +out: + delete_mid(midQ); + add_credits(server, &credits, 0); + + return rc; +} + +/* We send a LOCKINGX_CANCEL_LOCK to cause the Windows + blocking lock to return. */ + +static int +send_lock_cancel(const unsigned int xid, struct cifs_tcon *tcon, + struct smb_hdr *in_buf, + struct smb_hdr *out_buf) +{ + int bytes_returned; + struct cifs_ses *ses =3D tcon->ses; + LOCK_REQ *pSMB =3D (LOCK_REQ *)in_buf; + + /* We just modify the current in_buf to change + the type of lock from LOCKING_ANDX_SHARED_LOCK + or LOCKING_ANDX_EXCLUSIVE_LOCK to + LOCKING_ANDX_CANCEL_LOCK. */ + + pSMB->LockType =3D LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES; + pSMB->Timeout =3D 0; + pSMB->hdr.Mid =3D get_next_mid(ses->server); + + return SendReceive(xid, ses, in_buf, out_buf, + &bytes_returned, 0); +} + +int +SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, + struct smb_hdr *in_buf, struct smb_hdr *out_buf, + int *pbytes_returned) +{ + int rc =3D 0; + int rstart =3D 0; + struct mid_q_entry *midQ; + struct cifs_ses *ses; + unsigned int len =3D be32_to_cpu(in_buf->smb_buf_length); + struct kvec iov =3D { .iov_base =3D in_buf, .iov_len =3D len }; + struct smb_rqst rqst =3D { .rq_iov =3D &iov, .rq_nvec =3D 1 }; + unsigned int instance; + struct TCP_Server_Info *server; + + if (tcon =3D=3D NULL || tcon->ses =3D=3D NULL) { + cifs_dbg(VFS, "Null smb session\n"); + return -EIO; + } + ses =3D tcon->ses; + server =3D ses->server; + + if (server =3D=3D NULL) { + cifs_dbg(VFS, "Null tcp session\n"); + return -EIO; + } + + spin_lock(&server->srv_lock); + if (server->tcpStatus =3D=3D CifsExiting) { + spin_unlock(&server->srv_lock); + return -ENOENT; + } + spin_unlock(&server->srv_lock); + + /* Ensure that we do not send more than 50 overlapping requests + to the same server. We may make this configurable later or + use ses->maxReq */ + + if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { + cifs_tcon_dbg(VFS, "Invalid length, greater than maximum frame, %d\n", + len); + return -EIO; + } + + rc =3D wait_for_free_request(server, CIFS_BLOCKING_OP, &instance); + if (rc) + return rc; + + /* make sure that we sign in the same order that we send on this socket + and avoid races inside tcp sendmsg code that could cause corruption + of smb data */ + + cifs_server_lock(server); + + rc =3D allocate_mid(ses, in_buf, &midQ); + if (rc) { + cifs_server_unlock(server); + return rc; + } + + rc =3D cifs_sign_smb(in_buf, server, &midQ->sequence_number); + if (rc) { + delete_mid(midQ); + cifs_server_unlock(server); + return rc; + } + + midQ->mid_state =3D MID_REQUEST_SUBMITTED; + rc =3D smb_send(server, in_buf, len); + cifs_save_when_sent(midQ); + + if (rc < 0) + server->sequence_number -=3D 2; + + cifs_server_unlock(server); + + if (rc < 0) { + delete_mid(midQ); + return rc; + } + + /* Wait for a reply - allow signals to interrupt. */ + rc =3D wait_event_interruptible(server->response_q, + (!(midQ->mid_state =3D=3D MID_REQUEST_SUBMITTED || + midQ->mid_state =3D=3D MID_RESPONSE_RECEIVED)) || + ((server->tcpStatus !=3D CifsGood) && + (server->tcpStatus !=3D CifsNew))); + + /* Were we interrupted by a signal ? */ + spin_lock(&server->srv_lock); + if ((rc =3D=3D -ERESTARTSYS) && + (midQ->mid_state =3D=3D MID_REQUEST_SUBMITTED || + midQ->mid_state =3D=3D MID_RESPONSE_RECEIVED) && + ((server->tcpStatus =3D=3D CifsGood) || + (server->tcpStatus =3D=3D CifsNew))) { + spin_unlock(&server->srv_lock); + + if (in_buf->Command =3D=3D SMB_COM_TRANSACTION2) { + /* POSIX lock. We send a NT_CANCEL SMB to cause the + blocking lock to return. */ + rc =3D send_cancel(server, &rqst, midQ); + if (rc) { + delete_mid(midQ); + return rc; + } + } else { + /* Windows lock. We send a LOCKINGX_CANCEL_LOCK + to cause the blocking lock to return. */ + + rc =3D send_lock_cancel(xid, tcon, in_buf, out_buf); + + /* If we get -ENOLCK back the lock may have + already been removed. Don't exit in this case. */ + if (rc && rc !=3D -ENOLCK) { + delete_mid(midQ); + return rc; + } + } + + rc =3D wait_for_response(server, midQ); + if (rc) { + send_cancel(server, &rqst, midQ); + spin_lock(&server->mid_lock); + if (midQ->mid_state =3D=3D MID_REQUEST_SUBMITTED || + midQ->mid_state =3D=3D MID_RESPONSE_RECEIVED) { + /* no longer considered to be "in-flight" */ + midQ->callback =3D release_mid; + spin_unlock(&server->mid_lock); + return rc; + } + spin_unlock(&server->mid_lock); + } + + /* We got the response - restart system call. */ + rstart =3D 1; + spin_lock(&server->srv_lock); + } + spin_unlock(&server->srv_lock); + + rc =3D cifs_sync_mid_result(midQ, server); + if (rc !=3D 0) + return rc; + + /* rcvd frame is ok */ + if (out_buf =3D=3D NULL || midQ->mid_state !=3D MID_RESPONSE_READY) { + rc =3D -EIO; + cifs_tcon_dbg(VFS, "Bad MID state?\n"); + goto out; + } + + *pbytes_returned =3D get_rfc1002_length(midQ->resp_buf); + memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4); + rc =3D cifs_check_receive(midQ, server, 0); +out: + delete_mid(midQ); + if (rstart && rc =3D=3D -EACCES) + return -ERESTARTSYS; + return rc; +} diff --git a/fs/smb/client/transport.c b/fs/smb/client/transport.c index 191783f553ce..68c73e22c3c9 100644 --- a/fs/smb/client/transport.c +++ b/fs/smb/client/transport.c @@ -30,9 +30,6 @@ #include "smbdirect.h" #include "compress.h" =20 -/* Max number of iovectors we can use off the stack when sending requests.= */ -#define CIFS_MAX_IOV_SIZE 8 - void cifs_wake_up_task(struct mid_q_entry *mid) { @@ -41,42 +38,6 @@ cifs_wake_up_task(struct mid_q_entry *mid) wake_up_process(mid->callback_data); } =20 -static struct mid_q_entry * -alloc_mid(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server) -{ - struct mid_q_entry *temp; - - if (server =3D=3D NULL) { - cifs_dbg(VFS, "%s: null TCP session\n", __func__); - return NULL; - } - - temp =3D mempool_alloc(cifs_mid_poolp, GFP_NOFS); - memset(temp, 0, sizeof(struct mid_q_entry)); - kref_init(&temp->refcount); - temp->mid =3D get_mid(smb_buffer); - temp->pid =3D current->pid; - temp->command =3D cpu_to_le16(smb_buffer->Command); - cifs_dbg(FYI, "For smb_command %d\n", smb_buffer->Command); - /* easier to use jiffies */ - /* when mid allocated can be before when sent */ - temp->when_alloc =3D jiffies; - temp->server =3D server; - - /* - * The default is for the mid to be synchronous, so the - * default callback just wakes up the current task. - */ - get_task_struct(current); - temp->creator =3D current; - temp->callback =3D cifs_wake_up_task; - temp->callback_data =3D current; - - atomic_inc(&mid_count); - temp->mid_state =3D MID_REQUEST_ALLOCATED; - return temp; -} - void __release_mid(struct kref *refcount) { struct mid_q_entry *midEntry =3D @@ -269,9 +230,8 @@ smb_rqst_len(struct TCP_Server_Info *server, struct smb= _rqst *rqst) return buflen; } =20 -static int -__smb_send_rqst(struct TCP_Server_Info *server, int num_rqst, - struct smb_rqst *rqst) +int __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst, + struct smb_rqst *rqst) { int rc; struct kvec *iov; @@ -456,22 +416,6 @@ smb_send_rqst(struct TCP_Server_Info *server, int num_= rqst, return rc; } =20 -int -smb_send(struct TCP_Server_Info *server, struct smb_hdr *smb_buffer, - unsigned int smb_buf_length) -{ - struct kvec iov[2]; - struct smb_rqst rqst =3D { .rq_iov =3D iov, - .rq_nvec =3D 2 }; - - iov[0].iov_base =3D smb_buffer; - iov[0].iov_len =3D 4; - iov[1].iov_base =3D (char *)smb_buffer + 4; - iov[1].iov_len =3D smb_buf_length; - - return __smb_send_rqst(server, 1, &rqst); -} - static int wait_for_free_credits(struct TCP_Server_Info *server, const int num_credit= s, const int timeout, const int flags, @@ -626,9 +570,8 @@ wait_for_free_credits(struct TCP_Server_Info *server, c= onst int num_credits, return 0; } =20 -static int -wait_for_free_request(struct TCP_Server_Info *server, const int flags, - unsigned int *instance) +int wait_for_free_request(struct TCP_Server_Info *server, const int flags, + unsigned int *instance) { return wait_for_free_credits(server, 1, -1, flags, instance); @@ -690,40 +633,7 @@ cifs_wait_mtu_credits(struct TCP_Server_Info *server, = size_t size, return 0; } =20 -static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf, - struct mid_q_entry **ppmidQ) -{ - spin_lock(&ses->ses_lock); - if (ses->ses_status =3D=3D SES_NEW) { - if ((in_buf->Command !=3D SMB_COM_SESSION_SETUP_ANDX) && - (in_buf->Command !=3D SMB_COM_NEGOTIATE)) { - spin_unlock(&ses->ses_lock); - return -EAGAIN; - } - /* else ok - we are setting up session */ - } - - if (ses->ses_status =3D=3D SES_EXITING) { - /* check if SMB session is bad because we are setting it up */ - if (in_buf->Command !=3D SMB_COM_LOGOFF_ANDX) { - spin_unlock(&ses->ses_lock); - return -EAGAIN; - } - /* else ok - we are shutting down session */ - } - spin_unlock(&ses->ses_lock); - - *ppmidQ =3D alloc_mid(in_buf, ses->server); - if (*ppmidQ =3D=3D NULL) - return -ENOMEM; - spin_lock(&ses->server->mid_lock); - list_add_tail(&(*ppmidQ)->qhead, &ses->server->pending_mid_q); - spin_unlock(&ses->server->mid_lock); - return 0; -} - -static int -wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ) +int wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *= midQ) { int error; =20 @@ -737,34 +647,6 @@ wait_for_response(struct TCP_Server_Info *server, stru= ct mid_q_entry *midQ) return 0; } =20 -struct mid_q_entry * -cifs_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *= rqst) -{ - int rc; - struct smb_hdr *hdr =3D (struct smb_hdr *)rqst->rq_iov[0].iov_base; - struct mid_q_entry *mid; - - if (rqst->rq_iov[0].iov_len !=3D 4 || - rqst->rq_iov[0].iov_base + 4 !=3D rqst->rq_iov[1].iov_base) - return ERR_PTR(-EIO); - - /* enable signing if server requires it */ - if (server->sign) - hdr->Flags2 |=3D SMBFLG2_SECURITY_SIGNATURE; - - mid =3D alloc_mid(hdr, server); - if (mid =3D=3D NULL) - return ERR_PTR(-ENOMEM); - - rc =3D cifs_sign_rqst(rqst, server, &mid->sequence_number); - if (rc) { - release_mid(mid); - return ERR_PTR(rc); - } - - return mid; -} - /* * Send a SMB request and set the callback function in the mid to handle * the result. Caller is responsible for dealing with timeouts. @@ -845,35 +727,7 @@ cifs_call_async(struct TCP_Server_Info *server, struct= smb_rqst *rqst, return rc; } =20 -/* - * - * Send an SMB Request. No response info (other than return code) - * needs to be parsed. - * - * flags indicate the type of request buffer and how long to wait - * and whether to log NT STATUS code (error) before mapping it to POSIX er= ror - * - */ -int -SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses, - char *in_buf, int flags) -{ - int rc; - struct kvec iov[1]; - struct kvec rsp_iov; - int resp_buf_type; - - iov[0].iov_base =3D in_buf; - iov[0].iov_len =3D get_rfc1002_length(in_buf) + 4; - flags |=3D CIFS_NO_RSP_BUF; - rc =3D SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags, &rsp_iov); - cifs_dbg(NOISY, "SendRcvNoRsp flags %d rc %d\n", flags, rc); - - return rc; -} - -static int -cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *serv= er) +int cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *= server) { int rc =3D 0; =20 @@ -915,68 +769,6 @@ cifs_sync_mid_result(struct mid_q_entry *mid, struct T= CP_Server_Info *server) return rc; } =20 -static inline int -send_cancel(struct TCP_Server_Info *server, struct smb_rqst *rqst, - struct mid_q_entry *mid) -{ - return server->ops->send_cancel ? - server->ops->send_cancel(server, rqst, mid) : 0; -} - -int -cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, - bool log_error) -{ - unsigned int len =3D get_rfc1002_length(mid->resp_buf) + 4; - - dump_smb(mid->resp_buf, min_t(u32, 92, len)); - - /* convert the length into a more usable form */ - if (server->sign) { - struct kvec iov[2]; - int rc =3D 0; - struct smb_rqst rqst =3D { .rq_iov =3D iov, - .rq_nvec =3D 2 }; - - iov[0].iov_base =3D mid->resp_buf; - iov[0].iov_len =3D 4; - iov[1].iov_base =3D (char *)mid->resp_buf + 4; - iov[1].iov_len =3D len - 4; - /* FIXME: add code to kill session */ - rc =3D cifs_verify_signature(&rqst, server, - mid->sequence_number); - if (rc) - cifs_server_dbg(VFS, "SMB signature verification returned error =3D %d\= n", - rc); - } - - /* BB special case reconnect tid and uid here? */ - return map_and_check_smb_error(mid, log_error); -} - -struct mid_q_entry * -cifs_setup_request(struct cifs_ses *ses, struct TCP_Server_Info *ignored, - struct smb_rqst *rqst) -{ - int rc; - struct smb_hdr *hdr =3D (struct smb_hdr *)rqst->rq_iov[0].iov_base; - struct mid_q_entry *mid; - - if (rqst->rq_iov[0].iov_len !=3D 4 || - rqst->rq_iov[0].iov_base + 4 !=3D rqst->rq_iov[1].iov_base) - return ERR_PTR(-EIO); - - rc =3D allocate_mid(ses, hdr, &mid); - if (rc) - return ERR_PTR(rc); - rc =3D cifs_sign_rqst(rqst, ses->server, &mid->sequence_number); - if (rc) { - delete_mid(mid); - return ERR_PTR(rc); - } - return mid; -} - static void cifs_compound_callback(struct mid_q_entry *mid) { @@ -1304,345 +1096,6 @@ cifs_send_recv(const unsigned int xid, struct cifs_= ses *ses, rqst, resp_buf_type, resp_iov); } =20 -int -SendReceive2(const unsigned int xid, struct cifs_ses *ses, - struct kvec *iov, int n_vec, int *resp_buf_type /* ret */, - const int flags, struct kvec *resp_iov) -{ - struct smb_rqst rqst; - struct kvec s_iov[CIFS_MAX_IOV_SIZE], *new_iov; - int rc; - - if (n_vec + 1 > CIFS_MAX_IOV_SIZE) { - new_iov =3D kmalloc_array(n_vec + 1, sizeof(struct kvec), - GFP_KERNEL); - if (!new_iov) { - /* otherwise cifs_send_recv below sets resp_buf_type */ - *resp_buf_type =3D CIFS_NO_BUFFER; - return -ENOMEM; - } - } else - new_iov =3D s_iov; - - /* 1st iov is a RFC1001 length followed by the rest of the packet */ - memcpy(new_iov + 1, iov, (sizeof(struct kvec) * n_vec)); - - new_iov[0].iov_base =3D new_iov[1].iov_base; - new_iov[0].iov_len =3D 4; - new_iov[1].iov_base +=3D 4; - new_iov[1].iov_len -=3D 4; - - memset(&rqst, 0, sizeof(struct smb_rqst)); - rqst.rq_iov =3D new_iov; - rqst.rq_nvec =3D n_vec + 1; - - rc =3D cifs_send_recv(xid, ses, ses->server, - &rqst, resp_buf_type, flags, resp_iov); - if (n_vec + 1 > CIFS_MAX_IOV_SIZE) - kfree(new_iov); - return rc; -} - -int -SendReceive(const unsigned int xid, struct cifs_ses *ses, - struct smb_hdr *in_buf, struct smb_hdr *out_buf, - int *pbytes_returned, const int flags) -{ - int rc =3D 0; - struct mid_q_entry *midQ; - unsigned int len =3D be32_to_cpu(in_buf->smb_buf_length); - struct kvec iov =3D { .iov_base =3D in_buf, .iov_len =3D len }; - struct smb_rqst rqst =3D { .rq_iov =3D &iov, .rq_nvec =3D 1 }; - struct cifs_credits credits =3D { .value =3D 1, .instance =3D 0 }; - struct TCP_Server_Info *server; - - if (ses =3D=3D NULL) { - cifs_dbg(VFS, "Null smb session\n"); - return -EIO; - } - server =3D ses->server; - if (server =3D=3D NULL) { - cifs_dbg(VFS, "Null tcp session\n"); - return -EIO; - } - - spin_lock(&server->srv_lock); - if (server->tcpStatus =3D=3D CifsExiting) { - spin_unlock(&server->srv_lock); - return -ENOENT; - } - spin_unlock(&server->srv_lock); - - /* Ensure that we do not send more than 50 overlapping requests - to the same server. We may make this configurable later or - use ses->maxReq */ - - if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { - cifs_server_dbg(VFS, "Invalid length, greater than maximum frame, %d\n", - len); - return -EIO; - } - - rc =3D wait_for_free_request(server, flags, &credits.instance); - if (rc) - return rc; - - /* make sure that we sign in the same order that we send on this socket - and avoid races inside tcp sendmsg code that could cause corruption - of smb data */ - - cifs_server_lock(server); - - rc =3D allocate_mid(ses, in_buf, &midQ); - if (rc) { - cifs_server_unlock(server); - /* Update # of requests on wire to server */ - add_credits(server, &credits, 0); - return rc; - } - - rc =3D cifs_sign_smb(in_buf, server, &midQ->sequence_number); - if (rc) { - cifs_server_unlock(server); - goto out; - } - - midQ->mid_state =3D MID_REQUEST_SUBMITTED; - - rc =3D smb_send(server, in_buf, len); - cifs_save_when_sent(midQ); - - if (rc < 0) - server->sequence_number -=3D 2; - - cifs_server_unlock(server); - - if (rc < 0) - goto out; - - rc =3D wait_for_response(server, midQ); - if (rc !=3D 0) { - send_cancel(server, &rqst, midQ); - spin_lock(&server->mid_lock); - if (midQ->mid_state =3D=3D MID_REQUEST_SUBMITTED || - midQ->mid_state =3D=3D MID_RESPONSE_RECEIVED) { - /* no longer considered to be "in-flight" */ - midQ->callback =3D release_mid; - spin_unlock(&server->mid_lock); - add_credits(server, &credits, 0); - return rc; - } - spin_unlock(&server->mid_lock); - } - - rc =3D cifs_sync_mid_result(midQ, server); - if (rc !=3D 0) { - add_credits(server, &credits, 0); - return rc; - } - - if (!midQ->resp_buf || !out_buf || - midQ->mid_state !=3D MID_RESPONSE_READY) { - rc =3D -EIO; - cifs_server_dbg(VFS, "Bad MID state?\n"); - goto out; - } - - *pbytes_returned =3D get_rfc1002_length(midQ->resp_buf); - memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4); - rc =3D cifs_check_receive(midQ, server, 0); -out: - delete_mid(midQ); - add_credits(server, &credits, 0); - - return rc; -} - -/* We send a LOCKINGX_CANCEL_LOCK to cause the Windows - blocking lock to return. */ - -static int -send_lock_cancel(const unsigned int xid, struct cifs_tcon *tcon, - struct smb_hdr *in_buf, - struct smb_hdr *out_buf) -{ - int bytes_returned; - struct cifs_ses *ses =3D tcon->ses; - LOCK_REQ *pSMB =3D (LOCK_REQ *)in_buf; - - /* We just modify the current in_buf to change - the type of lock from LOCKING_ANDX_SHARED_LOCK - or LOCKING_ANDX_EXCLUSIVE_LOCK to - LOCKING_ANDX_CANCEL_LOCK. */ - - pSMB->LockType =3D LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES; - pSMB->Timeout =3D 0; - pSMB->hdr.Mid =3D get_next_mid(ses->server); - - return SendReceive(xid, ses, in_buf, out_buf, - &bytes_returned, 0); -} - -int -SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, - struct smb_hdr *in_buf, struct smb_hdr *out_buf, - int *pbytes_returned) -{ - int rc =3D 0; - int rstart =3D 0; - struct mid_q_entry *midQ; - struct cifs_ses *ses; - unsigned int len =3D be32_to_cpu(in_buf->smb_buf_length); - struct kvec iov =3D { .iov_base =3D in_buf, .iov_len =3D len }; - struct smb_rqst rqst =3D { .rq_iov =3D &iov, .rq_nvec =3D 1 }; - unsigned int instance; - struct TCP_Server_Info *server; - - if (tcon =3D=3D NULL || tcon->ses =3D=3D NULL) { - cifs_dbg(VFS, "Null smb session\n"); - return -EIO; - } - ses =3D tcon->ses; - server =3D ses->server; - - if (server =3D=3D NULL) { - cifs_dbg(VFS, "Null tcp session\n"); - return -EIO; - } - - spin_lock(&server->srv_lock); - if (server->tcpStatus =3D=3D CifsExiting) { - spin_unlock(&server->srv_lock); - return -ENOENT; - } - spin_unlock(&server->srv_lock); - - /* Ensure that we do not send more than 50 overlapping requests - to the same server. We may make this configurable later or - use ses->maxReq */ - - if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { - cifs_tcon_dbg(VFS, "Invalid length, greater than maximum frame, %d\n", - len); - return -EIO; - } - - rc =3D wait_for_free_request(server, CIFS_BLOCKING_OP, &instance); - if (rc) - return rc; - - /* make sure that we sign in the same order that we send on this socket - and avoid races inside tcp sendmsg code that could cause corruption - of smb data */ - - cifs_server_lock(server); - - rc =3D allocate_mid(ses, in_buf, &midQ); - if (rc) { - cifs_server_unlock(server); - return rc; - } - - rc =3D cifs_sign_smb(in_buf, server, &midQ->sequence_number); - if (rc) { - delete_mid(midQ); - cifs_server_unlock(server); - return rc; - } - - midQ->mid_state =3D MID_REQUEST_SUBMITTED; - rc =3D smb_send(server, in_buf, len); - cifs_save_when_sent(midQ); - - if (rc < 0) - server->sequence_number -=3D 2; - - cifs_server_unlock(server); - - if (rc < 0) { - delete_mid(midQ); - return rc; - } - - /* Wait for a reply - allow signals to interrupt. */ - rc =3D wait_event_interruptible(server->response_q, - (!(midQ->mid_state =3D=3D MID_REQUEST_SUBMITTED || - midQ->mid_state =3D=3D MID_RESPONSE_RECEIVED)) || - ((server->tcpStatus !=3D CifsGood) && - (server->tcpStatus !=3D CifsNew))); - - /* Were we interrupted by a signal ? */ - spin_lock(&server->srv_lock); - if ((rc =3D=3D -ERESTARTSYS) && - (midQ->mid_state =3D=3D MID_REQUEST_SUBMITTED || - midQ->mid_state =3D=3D MID_RESPONSE_RECEIVED) && - ((server->tcpStatus =3D=3D CifsGood) || - (server->tcpStatus =3D=3D CifsNew))) { - spin_unlock(&server->srv_lock); - - if (in_buf->Command =3D=3D SMB_COM_TRANSACTION2) { - /* POSIX lock. We send a NT_CANCEL SMB to cause the - blocking lock to return. */ - rc =3D send_cancel(server, &rqst, midQ); - if (rc) { - delete_mid(midQ); - return rc; - } - } else { - /* Windows lock. We send a LOCKINGX_CANCEL_LOCK - to cause the blocking lock to return. */ - - rc =3D send_lock_cancel(xid, tcon, in_buf, out_buf); - - /* If we get -ENOLCK back the lock may have - already been removed. Don't exit in this case. */ - if (rc && rc !=3D -ENOLCK) { - delete_mid(midQ); - return rc; - } - } - - rc =3D wait_for_response(server, midQ); - if (rc) { - send_cancel(server, &rqst, midQ); - spin_lock(&server->mid_lock); - if (midQ->mid_state =3D=3D MID_REQUEST_SUBMITTED || - midQ->mid_state =3D=3D MID_RESPONSE_RECEIVED) { - /* no longer considered to be "in-flight" */ - midQ->callback =3D release_mid; - spin_unlock(&server->mid_lock); - return rc; - } - spin_unlock(&server->mid_lock); - } - - /* We got the response - restart system call. */ - rstart =3D 1; - spin_lock(&server->srv_lock); - } - spin_unlock(&server->srv_lock); - - rc =3D cifs_sync_mid_result(midQ, server); - if (rc !=3D 0) - return rc; - - /* rcvd frame is ok */ - if (out_buf =3D=3D NULL || midQ->mid_state !=3D MID_RESPONSE_READY) { - rc =3D -EIO; - cifs_tcon_dbg(VFS, "Bad MID state?\n"); - goto out; - } - - *pbytes_returned =3D get_rfc1002_length(midQ->resp_buf); - memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4); - rc =3D cifs_check_receive(midQ, server, 0); -out: - delete_mid(midQ); - if (rstart && rc =3D=3D -EACCES) - return -ERESTARTSYS; - return rc; -} - /* * Discard any remaining data in the current SMB. To do this, we borrow the * current bigbuf. From nobody Thu Dec 18 03:20:29 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7A2112BE7BA for ; Wed, 6 Aug 2025 20:37:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512683; cv=none; b=M0ETfvrenrQ4pHU9Oe1lvi8V2J9YNMrm5iZ2Uiy5jV/XmeZhQO9+i7agthGlB3nqW36yKGcYonQ8h18C74ogN+oUJnHnyssCSzisC1H3KLziuF2RwW/kmH+vq/vssZfBJ3aE2W7F5r8ogoSCQyg0kwdwGCVOqMg3wxwGpMhcqus= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512683; c=relaxed/simple; bh=lqFiNLUvfj7Kj5KBjGf43wU7EG+QnbUsCo8T20T8CAY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=e6UtRd3iWVhTxm//nTh1pzGjV9KUo/rghM60BcWpqDKeHCh4S4KgTXJ4aunC/PSsckmrtzPI9DMzryHeq+MPT9mzjvGw27ZqKsL06liCsdCSxJXQxFRgO1hLUD25y6kgJFonh4Vl+5278zF0BsUgb7SE1fa8XDz8vaAtvoaFMUc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=d+CUrb6U; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="d+CUrb6U" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1754512676; h=from:from:reply-to:subject:subject: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=oW29u+3N9bVMFcNgz7z1d16605kAQozM5Ws5N/FAW5s=; b=d+CUrb6UiQsFV7mcIzkl+ugotN+9KCP4ahG6xZQvQ8cmGiqV3ZpHv/QhoDqazd9aaLGS2b B20zhme4j4b/KcdwWfHhbnRNb7SCGF4gC0gH/TIDVRilG9G45E5p/uhpb/k2s9TNLEqyYN sX7xxuWk2tDbgKSwOOfz0l6B+Wi+IEo= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-39-9vzpHMUANYGtuCfOAi7J6w-1; Wed, 06 Aug 2025 16:37:50 -0400 X-MC-Unique: 9vzpHMUANYGtuCfOAi7J6w-1 X-Mimecast-MFC-AGG-ID: 9vzpHMUANYGtuCfOAi7J6w_1754512669 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 2252B1955F44; Wed, 6 Aug 2025 20:37:49 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.17]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 955DB1800446; Wed, 6 Aug 2025 20:37:45 +0000 (UTC) From: David Howells To: Steve French Cc: David Howells , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Wang Zhaolong , Stefan Metzmacher , Mina Almasry , linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org, netfs@lists.linux.dev, linux-fsdevel@vger.kernel.org Subject: [RFC PATCH 07/31] cifs: Rename mid_q_entry to smb_message Date: Wed, 6 Aug 2025 21:36:28 +0100 Message-ID: <20250806203705.2560493-8-dhowells@redhat.com> In-Reply-To: <20250806203705.2560493-1-dhowells@redhat.com> References: <20250806203705.2560493-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Howells cc: Steve French cc: Paulo Alcantara cc: Shyam Prasad N cc: Tom Talpey cc: linux-cifs@vger.kernel.org cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/smb/client/cifs_debug.c | 14 +- fs/smb/client/cifsfs.c | 31 +++-- fs/smb/client/cifsglob.h | 48 +++---- fs/smb/client/cifsproto.h | 34 ++--- fs/smb/client/cifssmb.c | 82 ++++++------ fs/smb/client/cifstransport.c | 156 +++++++++++----------- fs/smb/client/connect.c | 152 +++++++++++----------- fs/smb/client/netmisc.c | 14 +- fs/smb/client/smb1ops.c | 46 +++---- fs/smb/client/smb2misc.c | 8 +- fs/smb/client/smb2ops.c | 122 +++++++++--------- fs/smb/client/smb2pdu.c | 47 ++++--- fs/smb/client/smb2proto.h | 10 +- fs/smb/client/smb2transport.c | 60 ++++----- fs/smb/client/transport.c | 235 +++++++++++++++++----------------- 15 files changed, 529 insertions(+), 530 deletions(-) diff --git a/fs/smb/client/cifs_debug.c b/fs/smb/client/cifs_debug.c index 3fdf75737d43..163e8954b940 100644 --- a/fs/smb/client/cifs_debug.c +++ b/fs/smb/client/cifs_debug.c @@ -300,7 +300,7 @@ static __always_inline const char *compression_alg_str(= __le16 alg) =20 static int cifs_debug_data_proc_show(struct seq_file *m, void *v) { - struct mid_q_entry *mid_entry; + struct smb_message *smb; struct TCP_Server_Info *server; struct TCP_Server_Info *chan_server; struct cifs_ses *ses; @@ -624,13 +624,13 @@ static int cifs_debug_data_proc_show(struct seq_file = *m, void *v) seq_printf(m, "\n\tServer ConnectionId: 0x%llx", chan_server->conn_id); spin_lock(&chan_server->mid_lock); - list_for_each_entry(mid_entry, &chan_server->pending_mid_q, qhead) { + list_for_each_entry(smb, &chan_server->pending_mid_q, qhead) { seq_printf(m, "\n\t\tState: %d com: %d pid: %d cbdata: %p mid %llu", - mid_entry->mid_state, - le16_to_cpu(mid_entry->command), - mid_entry->pid, - mid_entry->callback_data, - mid_entry->mid); + smb->mid_state, + le16_to_cpu(smb->command), + smb->pid, + smb->callback_data, + smb->mid); } spin_unlock(&chan_server->mid_lock); } diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c index 0a5266ecfd15..4e2a1d07125b 100644 --- a/fs/smb/client/cifsfs.c +++ b/fs/smb/client/cifsfs.c @@ -380,13 +380,13 @@ static int cifs_permission(struct mnt_idmap *idmap, =20 static struct kmem_cache *cifs_inode_cachep; static struct kmem_cache *cifs_req_cachep; -static struct kmem_cache *cifs_mid_cachep; +static struct kmem_cache *smb_message_cachep; static struct kmem_cache *cifs_sm_req_cachep; static struct kmem_cache *cifs_io_request_cachep; static struct kmem_cache *cifs_io_subrequest_cachep; mempool_t *cifs_sm_req_poolp; mempool_t *cifs_req_poolp; -mempool_t *cifs_mid_poolp; +mempool_t smb_message_pool; mempool_t cifs_io_request_pool; mempool_t cifs_io_subrequest_pool; =20 @@ -1765,28 +1765,27 @@ cifs_destroy_request_bufs(void) kmem_cache_destroy(cifs_sm_req_cachep); } =20 -static int init_mids(void) +static int init_smb_message(void) { - cifs_mid_cachep =3D kmem_cache_create("cifs_mpx_ids", - sizeof(struct mid_q_entry), 0, - SLAB_HWCACHE_ALIGN, NULL); - if (cifs_mid_cachep =3D=3D NULL) + smb_message_cachep =3D kmem_cache_create("cifs_smb_message", + sizeof(struct smb_message), 0, + SLAB_HWCACHE_ALIGN, NULL); + if (smb_message_cachep =3D=3D NULL) return -ENOMEM; =20 /* 3 is a reasonable minimum number of simultaneous operations */ - cifs_mid_poolp =3D mempool_create_slab_pool(3, cifs_mid_cachep); - if (cifs_mid_poolp =3D=3D NULL) { - kmem_cache_destroy(cifs_mid_cachep); + if (mempool_init_slab_pool(&smb_message_pool, 3, smb_message_cachep) < 0)= { + kmem_cache_destroy(smb_message_cachep); return -ENOMEM; } =20 return 0; } =20 -static void destroy_mids(void) +static void destroy_smb_message(void) { - mempool_destroy(cifs_mid_poolp); - kmem_cache_destroy(cifs_mid_cachep); + mempool_exit(&smb_message_pool); + kmem_cache_destroy(smb_message_cachep); } =20 static int cifs_init_netfs(void) @@ -1946,7 +1945,7 @@ init_cifs(void) if (rc) goto out_destroy_inodecache; =20 - rc =3D init_mids(); + rc =3D init_smb_message(); if (rc) goto out_destroy_netfs; =20 @@ -2003,7 +2002,7 @@ init_cifs(void) #endif cifs_destroy_request_bufs(); out_destroy_mids: - destroy_mids(); + destroy_smb_message(); out_destroy_netfs: cifs_destroy_netfs(); out_destroy_inodecache: @@ -2045,7 +2044,7 @@ exit_cifs(void) dfs_cache_destroy(); #endif cifs_destroy_request_bufs(); - destroy_mids(); + destroy_smb_message(); cifs_destroy_netfs(); cifs_destroy_inodecache(); destroy_workqueue(deferredclose_wq); diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index 67c1a63a08ba..5d523099e298 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h @@ -295,7 +295,7 @@ struct smb_rqst { struct folio_queue *rq_buffer; /* Buffer for encryption */ }; =20 -struct mid_q_entry; +struct smb_message; struct TCP_Server_Info; struct cifsFileInfo; struct cifs_ses; @@ -313,24 +313,24 @@ struct cifs_credits; =20 struct smb_version_operations { int (*send_cancel)(struct TCP_Server_Info *, struct smb_rqst *, - struct mid_q_entry *); + struct smb_message *smb); bool (*compare_fids)(struct cifsFileInfo *, struct cifsFileInfo *); /* setup request: allocate mid, sign message */ - struct mid_q_entry *(*setup_request)(struct cifs_ses *, + struct smb_message *(*setup_request)(struct cifs_ses *, struct TCP_Server_Info *, struct smb_rqst *); /* setup async request: allocate mid, sign message */ - struct mid_q_entry *(*setup_async_request)(struct TCP_Server_Info *, - struct smb_rqst *); + struct smb_message *(*setup_async_request)(struct TCP_Server_Info *, + struct smb_rqst *); /* check response: verify signature, map error */ - int (*check_receive)(struct mid_q_entry *, struct TCP_Server_Info *, + int (*check_receive)(struct smb_message *, struct TCP_Server_Info *, bool); void (*add_credits)(struct TCP_Server_Info *server, struct cifs_credits *credits, const int optype); void (*set_credits)(struct TCP_Server_Info *, const int); int * (*get_credits_field)(struct TCP_Server_Info *, const int); - unsigned int (*get_credits)(struct mid_q_entry *); + unsigned int (*get_credits)(struct smb_message *smb); __u64 (*get_next_mid)(struct TCP_Server_Info *); void (*revert_current_mid)(struct TCP_Server_Info *server, const unsigned int val); @@ -347,7 +347,7 @@ struct smb_version_operations { /* map smb to linux error */ int (*map_error)(char *, bool); /* find mid corresponding to the response message */ - struct mid_q_entry * (*find_mid)(struct TCP_Server_Info *, char *); + struct smb_message * (*find_mid)(struct TCP_Server_Info *, char *); void (*dump_detail)(void *buf, struct TCP_Server_Info *ptcp_info); void (*clear_stats)(struct cifs_tcon *); void (*print_stats)(struct seq_file *m, struct cifs_tcon *); @@ -355,12 +355,12 @@ struct smb_version_operations { /* verify the message */ int (*check_message)(char *, unsigned int, struct TCP_Server_Info *); bool (*is_oplock_break)(char *, struct TCP_Server_Info *); - int (*handle_cancelled_mid)(struct mid_q_entry *, struct TCP_Server_Info = *); + int (*handle_cancelled_mid)(struct smb_message *smb, struct TCP_Server_In= fo *server); void (*downgrade_oplock)(struct TCP_Server_Info *server, struct cifsInodeInfo *cinode, __u32 oplock, __u16 epoch, bool *purge_cache); /* process transaction2 response */ - bool (*check_trans2)(struct mid_q_entry *, struct TCP_Server_Info *, + bool (*check_trans2)(struct smb_message *smb, struct TCP_Server_Info *ser= ver, char *, int); /* check if we need to negotiate */ bool (*need_neg)(struct TCP_Server_Info *); @@ -597,7 +597,7 @@ struct smb_version_operations { struct smb_rqst *, struct smb_rqst *); int (*is_transform_hdr)(void *buf); int (*receive_transform)(struct TCP_Server_Info *, - struct mid_q_entry **, char **, int *); + struct smb_message **smb, char **, int *); enum securityEnum (*select_sectype)(struct TCP_Server_Info *, enum securityEnum); int (*next_header)(struct TCP_Server_Info *server, char *buf, @@ -1683,8 +1683,8 @@ static inline void cifs_stats_bytes_read(struct cifs_= tcon *tcon, * Returns zero on a successful receive, or an error. The receive state in * the TCP_Server_Info will also be updated. */ -typedef int (mid_receive_t)(struct TCP_Server_Info *server, - struct mid_q_entry *mid); +typedef int (*mid_receive_t)(struct TCP_Server_Info *server, + struct smb_message *msg); =20 /* * This is the prototype for the mid callback function. This is called onc= e the @@ -1694,17 +1694,17 @@ typedef int (mid_receive_t)(struct TCP_Server_Info = *server, * - it will be called by cifsd, with no locks held * - the mid will be removed from any lists */ -typedef void (mid_callback_t)(struct mid_q_entry *mid); +typedef void (*mid_callback_t)(struct smb_message *smb); =20 /* * This is the protopyte for mid handle function. This is called once the = mid * has been recognized after decryption of the message. */ -typedef int (mid_handle_t)(struct TCP_Server_Info *server, - struct mid_q_entry *mid); +typedef int (*mid_handle_t)(struct TCP_Server_Info *server, + struct smb_message *smb); =20 /* one of these for every pending CIFS request to the server */ -struct mid_q_entry { +struct smb_message { struct list_head qhead; /* mids waiting on reply from this server */ struct kref refcount; struct TCP_Server_Info *server; /* server corresponding to this mid */ @@ -1718,9 +1718,9 @@ struct mid_q_entry { unsigned long when_sent; /* time when smb send finished */ unsigned long when_received; /* when demux complete (taken off wire) */ #endif - mid_receive_t *receive; /* call receive callback */ - mid_callback_t *callback; /* call completion callback */ - mid_handle_t *handle; /* call handle mid callback */ + mid_receive_t receive; /* call receive callback */ + mid_callback_t callback; /* call completion callback */ + mid_handle_t handle; /* call handle mid callback */ void *callback_data; /* general purpose pointer for callback */ struct task_struct *creator; void *resp_buf; /* pointer to received SMB header */ @@ -1767,12 +1767,12 @@ static inline void cifs_num_waiters_dec(struct TCP_= Server_Info *server) } =20 #ifdef CONFIG_CIFS_STATS2 -static inline void cifs_save_when_sent(struct mid_q_entry *mid) +static inline void cifs_save_when_sent(struct smb_message *smb) { - mid->when_sent =3D jiffies; + smb->when_sent =3D jiffies; } #else -static inline void cifs_save_when_sent(struct mid_q_entry *mid) +static inline void cifs_save_when_sent(struct smb_message *smb) { } #endif @@ -2124,7 +2124,7 @@ extern __u32 cifs_lock_secret; =20 extern mempool_t *cifs_sm_req_poolp; extern mempool_t *cifs_req_poolp; -extern mempool_t *cifs_mid_poolp; +extern mempool_t smb_message_pool; extern mempool_t cifs_io_request_pool; extern mempool_t cifs_io_subrequest_pool; =20 diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h index 8661ab105b4f..1126feb4ba5f 100644 --- a/fs/smb/client/cifsproto.h +++ b/fs/smb/client/cifsproto.h @@ -83,11 +83,11 @@ extern char *cifs_build_path_to_root(struct smb3_fs_con= text *ctx, int add_treename); extern char *build_wildcard_path_from_dentry(struct dentry *direntry); char *cifs_build_devname(char *nodename, const char *prepath); -extern void delete_mid(struct mid_q_entry *mid); +extern void delete_mid(struct smb_message *smb); void __release_mid(struct kref *refcount); -extern void cifs_wake_up_task(struct mid_q_entry *mid); +extern void cifs_wake_up_task(struct smb_message *smb); extern int cifs_handle_standard(struct TCP_Server_Info *server, - struct mid_q_entry *mid); + struct smb_message *smb); extern char *smb3_fs_context_fullpath(const struct smb3_fs_context *ctx, char dirsep); extern int smb3_parse_devname(const char *devname, struct smb3_fs_context = *ctx); @@ -97,8 +97,8 @@ extern bool cifs_match_ipaddr(struct sockaddr *srcaddr, s= truct sockaddr *rhs); extern int cifs_discard_remaining_data(struct TCP_Server_Info *server); extern int cifs_call_async(struct TCP_Server_Info *server, struct smb_rqst *rqst, - mid_receive_t *receive, mid_callback_t *callback, - mid_handle_t *handle, void *cbdata, const int flags, + mid_receive_t receive, mid_callback_t callback, + mid_handle_t handle, void *cbdata, const int flags, const struct cifs_credits *exist_credits); extern struct TCP_Server_Info *cifs_pick_channel(struct cifs_ses *ses); extern int cifs_send_recv(const unsigned int xid, struct cifs_ses *ses, @@ -116,15 +116,15 @@ extern int SendReceive(const unsigned int /* xid */ ,= struct cifs_ses *, int * /* bytes returned */ , const int); extern int SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses, char *in_buf, int flags); -int cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *= server); -extern struct mid_q_entry *cifs_setup_request(struct cifs_ses *, +int cifs_sync_mid_result(struct smb_message *smb, struct TCP_Server_Info *= server); +extern struct smb_message *cifs_setup_request(struct cifs_ses *, struct TCP_Server_Info *, struct smb_rqst *); -extern struct mid_q_entry *cifs_setup_async_request(struct TCP_Server_Info= *, +extern struct smb_message *cifs_setup_async_request(struct TCP_Server_Info= *, struct smb_rqst *); int __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst, struct smb_rqst *rqst); -extern int cifs_check_receive(struct mid_q_entry *mid, +extern int cifs_check_receive(struct smb_message *msg, struct TCP_Server_Info *server, bool log_error); int wait_for_free_request(struct TCP_Server_Info *server, const int flags, unsigned int *instance); @@ -134,13 +134,13 @@ extern int cifs_wait_mtu_credits(struct TCP_Server_In= fo *server, =20 static inline int send_cancel(struct TCP_Server_Info *server, struct smb_rqst *rqst, - struct mid_q_entry *mid) + struct smb_message *smb) { return server->ops->send_cancel ? - server->ops->send_cancel(server, rqst, mid) : 0; + server->ops->send_cancel(server, rqst, smb) : 0; } =20 -int wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *= midQ); +int wait_for_response(struct TCP_Server_Info *server, struct smb_message *= smb); extern int SendReceive2(const unsigned int /* xid */ , struct cifs_ses *, struct kvec *, int /* nvec to send */, int * /* type of buf returned */, const int flags, @@ -186,7 +186,7 @@ extern int decode_negTokenInit(unsigned char *security_= blob, int length, extern int cifs_convert_address(struct sockaddr *dst, const char *src, int= len); extern void cifs_set_port(struct sockaddr *addr, const unsigned short int = port); extern int map_smb_to_linux_error(char *buf, bool logErr); -extern int map_and_check_smb_error(struct mid_q_entry *mid, bool logErr); +extern int map_and_check_smb_error(struct smb_message *smb, bool logErr); extern void header_assemble(struct smb_hdr *, char /* command */ , const struct cifs_tcon *, int /* length of fixed section (word count) in two byte units */); @@ -269,7 +269,7 @@ extern unsigned int setup_special_mode_ACE(struct smb_a= ce *pace, __u64 nmode); extern unsigned int setup_special_user_owner_ACE(struct smb_ace *pace); =20 -extern void dequeue_mid(struct mid_q_entry *mid, bool malformed); +extern void dequeue_mid(struct smb_message *smb, bool malformed); extern int cifs_read_from_socket(struct TCP_Server_Info *server, char *buf, unsigned int to_read); extern ssize_t cifs_discard_from_socket(struct TCP_Server_Info *server, @@ -613,7 +613,7 @@ extern struct cifs_ses * cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *c= tx); =20 int cifs_async_readv(struct cifs_io_subrequest *rdata); -int cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry = *mid); +int cifs_readv_receive(struct TCP_Server_Info *server, struct smb_message = *smb); =20 void cifs_async_writev(struct cifs_io_subrequest *wdata); int cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, @@ -762,9 +762,9 @@ static inline bool dfs_src_pathname_equal(const char *s= 1, const char *s2) return true; } =20 -static inline void release_mid(struct mid_q_entry *mid) +static inline void release_mid(struct smb_message *smb) { - kref_put(&mid->refcount, __release_mid); + kref_put(&smb->refcount, __release_mid); } =20 static inline void cifs_free_open_info(struct cifs_open_info_data *data) diff --git a/fs/smb/client/cifssmb.c b/fs/smb/client/cifssmb.c index 75142f49d65d..879fa0ad6e44 100644 --- a/fs/smb/client/cifssmb.c +++ b/fs/smb/client/cifssmb.c @@ -577,12 +577,12 @@ CIFSSMBTDis(const unsigned int xid, struct cifs_tcon = *tcon) * FIXME: maybe we should consider checking that the reply matches request? */ static void -cifs_echo_callback(struct mid_q_entry *mid) +cifs_echo_callback(struct smb_message *smb) { - struct TCP_Server_Info *server =3D mid->callback_data; + struct TCP_Server_Info *server =3D smb->callback_data; struct cifs_credits credits =3D { .value =3D 1, .instance =3D 0 }; =20 - release_mid(mid); + release_mid(smb); add_credits(server, &credits, CIFS_ECHO_OP); } =20 @@ -1296,9 +1296,9 @@ CIFS_open(const unsigned int xid, struct cifs_open_pa= rms *oparms, int *oplock, } =20 static void -cifs_readv_callback(struct mid_q_entry *mid) +cifs_readv_callback(struct smb_message *smb) { - struct cifs_io_subrequest *rdata =3D mid->callback_data; + struct cifs_io_subrequest *rdata =3D smb->callback_data; struct netfs_inode *ictx =3D netfs_inode(rdata->rreq->inode); struct cifs_tcon *tcon =3D tlink_tcon(rdata->req->cfile->tlink); struct TCP_Server_Info *server =3D tcon->ses->server; @@ -1313,10 +1313,10 @@ cifs_readv_callback(struct mid_q_entry *mid) }; =20 cifs_dbg(FYI, "%s: mid=3D%llu state=3D%d result=3D%d bytes=3D%zu\n", - __func__, mid->mid, mid->mid_state, rdata->result, + __func__, smb->mid, smb->mid_state, rdata->result, rdata->subreq.len); =20 - switch (mid->mid_state) { + switch (smb->mid_state) { case MID_RESPONSE_RECEIVED: /* result already set, check signature */ if (server->sign) { @@ -1324,7 +1324,7 @@ cifs_readv_callback(struct mid_q_entry *mid) =20 iov_iter_truncate(&rqst.rq_iter, rdata->got_bytes); rc =3D cifs_verify_signature(&rqst, server, - mid->sequence_number); + smb->sequence_number); if (rc) cifs_dbg(VFS, "SMB signature verification returned error =3D %d\n", rc); @@ -1379,7 +1379,7 @@ cifs_readv_callback(struct mid_q_entry *mid) rdata->subreq.transferred +=3D rdata->got_bytes; trace_netfs_sreq(&rdata->subreq, netfs_sreq_trace_io_progress); netfs_read_subreq_terminated(&rdata->subreq); - release_mid(mid); + release_mid(smb); add_credits(server, &credits, 0); } =20 @@ -1682,12 +1682,12 @@ CIFSSMBWrite(const unsigned int xid, struct cifs_io= _parms *io_parms, * workqueue completion task. */ static void -cifs_writev_callback(struct mid_q_entry *mid) +cifs_writev_callback(struct smb_message *smb) { - struct cifs_io_subrequest *wdata =3D mid->callback_data; + struct cifs_io_subrequest *wdata =3D smb->callback_data; struct TCP_Server_Info *server =3D wdata->server; struct cifs_tcon *tcon =3D tlink_tcon(wdata->req->cfile->tlink); - WRITE_RSP *smb =3D (WRITE_RSP *)mid->resp_buf; + WRITE_RSP *rsp =3D (WRITE_RSP *)smb->resp_buf; struct cifs_credits credits =3D { .value =3D 1, .instance =3D 0, @@ -1697,15 +1697,15 @@ cifs_writev_callback(struct mid_q_entry *mid) ssize_t result; size_t written; =20 - switch (mid->mid_state) { + switch (smb->mid_state) { case MID_RESPONSE_RECEIVED: - result =3D cifs_check_receive(mid, tcon->ses->server, 0); + result =3D cifs_check_receive(smb, tcon->ses->server, 0); if (result !=3D 0) break; =20 - written =3D le16_to_cpu(smb->CountHigh); + written =3D le16_to_cpu(rsp->CountHigh); written <<=3D 16; - written +=3D le16_to_cpu(smb->Count); + written +=3D le16_to_cpu(rsp->Count); /* * Mask off high 16 bits when bytes written as returned * by the server is greater than bytes requested by the @@ -1749,7 +1749,7 @@ cifs_writev_callback(struct mid_q_entry *mid) 0, cifs_trace_rw_credits_write_response_clear); wdata->credits.value =3D 0; cifs_write_subrequest_terminated(wdata, result); - release_mid(mid); + release_mid(smb); trace_smb3_rw_credits(credits.rreq_debug_id, credits.rreq_debug_index, 0, server->credits, server->in_flight, credits.value, cifs_trace_rw_credits_write_response_add); @@ -1761,7 +1761,7 @@ void cifs_async_writev(struct cifs_io_subrequest *wdata) { int rc =3D -EACCES; - WRITE_REQ *smb =3D NULL; + WRITE_REQ *req =3D NULL; int wct; struct cifs_tcon *tcon =3D tlink_tcon(wdata->req->cfile->tlink); struct kvec iov[2]; @@ -1778,30 +1778,30 @@ cifs_async_writev(struct cifs_io_subrequest *wdata) } } =20 - rc =3D small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **)&smb); + rc =3D small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **)&req); if (rc) goto async_writev_out; =20 - smb->hdr.Pid =3D cpu_to_le16((__u16)wdata->req->pid); - smb->hdr.PidHigh =3D cpu_to_le16((__u16)(wdata->req->pid >> 16)); + req->hdr.Pid =3D cpu_to_le16((__u16)wdata->req->pid); + req->hdr.PidHigh =3D cpu_to_le16((__u16)(wdata->req->pid >> 16)); =20 - smb->AndXCommand =3D 0xFF; /* none */ - smb->Fid =3D wdata->req->cfile->fid.netfid; - smb->OffsetLow =3D cpu_to_le32(wdata->subreq.start & 0xFFFFFFFF); + req->AndXCommand =3D 0xFF; /* none */ + req->Fid =3D wdata->req->cfile->fid.netfid; + req->OffsetLow =3D cpu_to_le32(wdata->subreq.start & 0xFFFFFFFF); if (wct =3D=3D 14) - smb->OffsetHigh =3D cpu_to_le32(wdata->subreq.start >> 32); - smb->Reserved =3D 0xFFFFFFFF; - smb->WriteMode =3D 0; - smb->Remaining =3D 0; + req->OffsetHigh =3D cpu_to_le32(wdata->subreq.start >> 32); + req->Reserved =3D 0xFFFFFFFF; + req->WriteMode =3D 0; + req->Remaining =3D 0; =20 - smb->DataOffset =3D + req->DataOffset =3D cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4); =20 /* 4 for RFC1001 length + 1 for BCC */ iov[0].iov_len =3D 4; - iov[0].iov_base =3D smb; - iov[1].iov_len =3D get_rfc1002_length(smb) + 1; - iov[1].iov_base =3D (char *)smb + 4; + iov[0].iov_base =3D req; + iov[1].iov_len =3D get_rfc1002_length(req) + 1; + iov[1].iov_base =3D (char *)req + 4; =20 rqst.rq_iov =3D iov; rqst.rq_nvec =3D 2; @@ -1810,18 +1810,18 @@ cifs_async_writev(struct cifs_io_subrequest *wdata) cifs_dbg(FYI, "async write at %llu %zu bytes\n", wdata->subreq.start, wdata->subreq.len); =20 - smb->DataLengthLow =3D cpu_to_le16(wdata->subreq.len & 0xFFFF); - smb->DataLengthHigh =3D cpu_to_le16(wdata->subreq.len >> 16); + req->DataLengthLow =3D cpu_to_le16(wdata->subreq.len & 0xFFFF); + req->DataLengthHigh =3D cpu_to_le16(wdata->subreq.len >> 16); =20 if (wct =3D=3D 14) { - inc_rfc1001_len(&smb->hdr, wdata->subreq.len + 1); - put_bcc(wdata->subreq.len + 1, &smb->hdr); + inc_rfc1001_len(&req->hdr, wdata->subreq.len + 1); + put_bcc(wdata->subreq.len + 1, &req->hdr); } else { /* wct =3D=3D 12 */ - struct smb_com_writex_req *smbw =3D - (struct smb_com_writex_req *)smb; - inc_rfc1001_len(&smbw->hdr, wdata->subreq.len + 5); - put_bcc(wdata->subreq.len + 5, &smbw->hdr); + struct smb_com_writex_req *reqw =3D + (struct smb_com_writex_req *)req; + inc_rfc1001_len(&reqw->hdr, wdata->subreq.len + 5); + put_bcc(wdata->subreq.len + 5, &reqw->hdr); iov[1].iov_len +=3D 4; /* pad bigger by four bytes */ } =20 @@ -1832,7 +1832,7 @@ cifs_async_writev(struct cifs_io_subrequest *wdata) cifs_stats_inc(&tcon->stats.cifs_stats.num_writes); =20 async_writev_out: - cifs_small_buf_release(smb); + cifs_small_buf_release(req); out: if (rc) { add_credits_and_wake_if(wdata->server, &wdata->credits, 0); diff --git a/fs/smb/client/cifstransport.c b/fs/smb/client/cifstransport.c index 241e0b427357..20709ae52d26 100644 --- a/fs/smb/client/cifstransport.c +++ b/fs/smb/client/cifstransport.c @@ -33,40 +33,40 @@ /* Max number of iovectors we can use off the stack when sending requests.= */ #define CIFS_MAX_IOV_SIZE 8 =20 -static struct mid_q_entry * +static struct smb_message * alloc_mid(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server) { - struct mid_q_entry *temp; + struct smb_message *smb; =20 if (server =3D=3D NULL) { cifs_dbg(VFS, "%s: null TCP session\n", __func__); return NULL; } =20 - temp =3D mempool_alloc(cifs_mid_poolp, GFP_NOFS); - memset(temp, 0, sizeof(struct mid_q_entry)); - kref_init(&temp->refcount); - temp->mid =3D get_mid(smb_buffer); - temp->pid =3D current->pid; - temp->command =3D cpu_to_le16(smb_buffer->Command); + smb =3D mempool_alloc(&smb_message_pool, GFP_NOFS); + memset(smb, 0, sizeof(struct smb_message)); + kref_init(&smb->refcount); + smb->mid =3D get_mid(smb_buffer); + smb->pid =3D current->pid; + smb->command =3D cpu_to_le16(smb_buffer->Command); cifs_dbg(FYI, "For smb_command %d\n", smb_buffer->Command); /* easier to use jiffies */ /* when mid allocated can be before when sent */ - temp->when_alloc =3D jiffies; - temp->server =3D server; + smb->when_alloc =3D jiffies; + smb->server =3D server; =20 /* * The default is for the mid to be synchronous, so the * default callback just wakes up the current task. */ get_task_struct(current); - temp->creator =3D current; - temp->callback =3D cifs_wake_up_task; - temp->callback_data =3D current; + smb->creator =3D current; + smb->callback =3D cifs_wake_up_task; + smb->callback_data =3D current; =20 atomic_inc(&mid_count); - temp->mid_state =3D MID_REQUEST_ALLOCATED; - return temp; + smb->mid_state =3D MID_REQUEST_ALLOCATED; + return smb; } =20 int @@ -86,7 +86,7 @@ smb_send(struct TCP_Server_Info *server, struct smb_hdr *= smb_buffer, } =20 static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf, - struct mid_q_entry **ppmidQ) + struct smb_message **ppmidQ) { spin_lock(&ses->ses_lock); if (ses->ses_status =3D=3D SES_NEW) { @@ -117,12 +117,12 @@ static int allocate_mid(struct cifs_ses *ses, struct = smb_hdr *in_buf, return 0; } =20 -struct mid_q_entry * +struct smb_message * cifs_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *= rqst) { int rc; struct smb_hdr *hdr =3D (struct smb_hdr *)rqst->rq_iov[0].iov_base; - struct mid_q_entry *mid; + struct smb_message *smb; =20 if (rqst->rq_iov[0].iov_len !=3D 4 || rqst->rq_iov[0].iov_base + 4 !=3D rqst->rq_iov[1].iov_base) @@ -132,17 +132,17 @@ cifs_setup_async_request(struct TCP_Server_Info *serv= er, struct smb_rqst *rqst) if (server->sign) hdr->Flags2 |=3D SMBFLG2_SECURITY_SIGNATURE; =20 - mid =3D alloc_mid(hdr, server); - if (mid =3D=3D NULL) + smb =3D alloc_mid(hdr, server); + if (smb =3D=3D NULL) return ERR_PTR(-ENOMEM); =20 - rc =3D cifs_sign_rqst(rqst, server, &mid->sequence_number); + rc =3D cifs_sign_rqst(rqst, server, &smb->sequence_number); if (rc) { - release_mid(mid); + release_mid(smb); return ERR_PTR(rc); } =20 - return mid; + return smb; } =20 /* @@ -173,12 +173,12 @@ SendReceiveNoRsp(const unsigned int xid, struct cifs_= ses *ses, } =20 int -cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, +cifs_check_receive(struct smb_message *smb, struct TCP_Server_Info *server, bool log_error) { - unsigned int len =3D get_rfc1002_length(mid->resp_buf) + 4; + unsigned int len =3D get_rfc1002_length(smb->resp_buf) + 4; =20 - dump_smb(mid->resp_buf, min_t(u32, 92, len)); + dump_smb(smb->resp_buf, min_t(u32, 92, len)); =20 /* convert the length into a more usable form */ if (server->sign) { @@ -187,43 +187,43 @@ cifs_check_receive(struct mid_q_entry *mid, struct TC= P_Server_Info *server, struct smb_rqst rqst =3D { .rq_iov =3D iov, .rq_nvec =3D 2 }; =20 - iov[0].iov_base =3D mid->resp_buf; + iov[0].iov_base =3D smb->resp_buf; iov[0].iov_len =3D 4; - iov[1].iov_base =3D (char *)mid->resp_buf + 4; + iov[1].iov_base =3D (char *)smb->resp_buf + 4; iov[1].iov_len =3D len - 4; /* FIXME: add code to kill session */ rc =3D cifs_verify_signature(&rqst, server, - mid->sequence_number); + smb->sequence_number); if (rc) cifs_server_dbg(VFS, "SMB signature verification returned error =3D %d\= n", rc); } =20 /* BB special case reconnect tid and uid here? */ - return map_and_check_smb_error(mid, log_error); + return map_and_check_smb_error(smb, log_error); } =20 -struct mid_q_entry * +struct smb_message * cifs_setup_request(struct cifs_ses *ses, struct TCP_Server_Info *ignored, struct smb_rqst *rqst) { int rc; struct smb_hdr *hdr =3D (struct smb_hdr *)rqst->rq_iov[0].iov_base; - struct mid_q_entry *mid; + struct smb_message *smb; =20 if (rqst->rq_iov[0].iov_len !=3D 4 || rqst->rq_iov[0].iov_base + 4 !=3D rqst->rq_iov[1].iov_base) return ERR_PTR(-EIO); =20 - rc =3D allocate_mid(ses, hdr, &mid); + rc =3D allocate_mid(ses, hdr, &smb); if (rc) return ERR_PTR(rc); - rc =3D cifs_sign_rqst(rqst, ses->server, &mid->sequence_number); + rc =3D cifs_sign_rqst(rqst, ses->server, &smb->sequence_number); if (rc) { - delete_mid(mid); + delete_mid(smb); return ERR_PTR(rc); } - return mid; + return smb; } =20 int @@ -271,7 +271,7 @@ SendReceive(const unsigned int xid, struct cifs_ses *se= s, int *pbytes_returned, const int flags) { int rc =3D 0; - struct mid_q_entry *midQ; + struct smb_message *smb; unsigned int len =3D be32_to_cpu(in_buf->smb_buf_length); struct kvec iov =3D { .iov_base =3D in_buf, .iov_len =3D len }; struct smb_rqst rqst =3D { .rq_iov =3D &iov, .rq_nvec =3D 1 }; @@ -315,7 +315,7 @@ SendReceive(const unsigned int xid, struct cifs_ses *se= s, =20 cifs_server_lock(server); =20 - rc =3D allocate_mid(ses, in_buf, &midQ); + rc =3D allocate_mid(ses, in_buf, &smb); if (rc) { cifs_server_unlock(server); /* Update # of requests on wire to server */ @@ -323,16 +323,16 @@ SendReceive(const unsigned int xid, struct cifs_ses *= ses, return rc; } =20 - rc =3D cifs_sign_smb(in_buf, server, &midQ->sequence_number); + rc =3D cifs_sign_smb(in_buf, server, &smb->sequence_number); if (rc) { cifs_server_unlock(server); goto out; } =20 - midQ->mid_state =3D MID_REQUEST_SUBMITTED; + smb->mid_state =3D MID_REQUEST_SUBMITTED; =20 rc =3D smb_send(server, in_buf, len); - cifs_save_when_sent(midQ); + cifs_save_when_sent(smb); =20 if (rc < 0) server->sequence_number -=3D 2; @@ -342,14 +342,14 @@ SendReceive(const unsigned int xid, struct cifs_ses *= ses, if (rc < 0) goto out; =20 - rc =3D wait_for_response(server, midQ); + rc =3D wait_for_response(server, smb); if (rc !=3D 0) { - send_cancel(server, &rqst, midQ); + send_cancel(server, &rqst, smb); spin_lock(&server->mid_lock); - if (midQ->mid_state =3D=3D MID_REQUEST_SUBMITTED || - midQ->mid_state =3D=3D MID_RESPONSE_RECEIVED) { + if (smb->mid_state =3D=3D MID_REQUEST_SUBMITTED || + smb->mid_state =3D=3D MID_RESPONSE_RECEIVED) { /* no longer considered to be "in-flight" */ - midQ->callback =3D release_mid; + smb->callback =3D release_mid; spin_unlock(&server->mid_lock); add_credits(server, &credits, 0); return rc; @@ -357,24 +357,24 @@ SendReceive(const unsigned int xid, struct cifs_ses *= ses, spin_unlock(&server->mid_lock); } =20 - rc =3D cifs_sync_mid_result(midQ, server); + rc =3D cifs_sync_mid_result(smb, server); if (rc !=3D 0) { add_credits(server, &credits, 0); return rc; } =20 - if (!midQ->resp_buf || !out_buf || - midQ->mid_state !=3D MID_RESPONSE_READY) { + if (!smb->resp_buf || !out_buf || + smb->mid_state !=3D MID_RESPONSE_READY) { rc =3D -EIO; cifs_server_dbg(VFS, "Bad MID state?\n"); goto out; } =20 - *pbytes_returned =3D get_rfc1002_length(midQ->resp_buf); - memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4); - rc =3D cifs_check_receive(midQ, server, 0); + *pbytes_returned =3D get_rfc1002_length(smb->resp_buf); + memcpy(out_buf, smb->resp_buf, *pbytes_returned + 4); + rc =3D cifs_check_receive(smb, server, 0); out: - delete_mid(midQ); + delete_mid(smb); add_credits(server, &credits, 0); =20 return rc; @@ -412,7 +412,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct = cifs_tcon *tcon, { int rc =3D 0; int rstart =3D 0; - struct mid_q_entry *midQ; + struct smb_message *smb; struct cifs_ses *ses; unsigned int len =3D be32_to_cpu(in_buf->smb_buf_length); struct kvec iov =3D { .iov_base =3D in_buf, .iov_len =3D len }; @@ -459,22 +459,22 @@ SendReceiveBlockingLock(const unsigned int xid, struc= t cifs_tcon *tcon, =20 cifs_server_lock(server); =20 - rc =3D allocate_mid(ses, in_buf, &midQ); + rc =3D allocate_mid(ses, in_buf, &smb); if (rc) { cifs_server_unlock(server); return rc; } =20 - rc =3D cifs_sign_smb(in_buf, server, &midQ->sequence_number); + rc =3D cifs_sign_smb(in_buf, server, &smb->sequence_number); if (rc) { - delete_mid(midQ); + delete_mid(smb); cifs_server_unlock(server); return rc; } =20 - midQ->mid_state =3D MID_REQUEST_SUBMITTED; + smb->mid_state =3D MID_REQUEST_SUBMITTED; rc =3D smb_send(server, in_buf, len); - cifs_save_when_sent(midQ); + cifs_save_when_sent(smb); =20 if (rc < 0) server->sequence_number -=3D 2; @@ -482,22 +482,22 @@ SendReceiveBlockingLock(const unsigned int xid, struc= t cifs_tcon *tcon, cifs_server_unlock(server); =20 if (rc < 0) { - delete_mid(midQ); + delete_mid(smb); return rc; } =20 /* Wait for a reply - allow signals to interrupt. */ rc =3D wait_event_interruptible(server->response_q, - (!(midQ->mid_state =3D=3D MID_REQUEST_SUBMITTED || - midQ->mid_state =3D=3D MID_RESPONSE_RECEIVED)) || + (!(smb->mid_state =3D=3D MID_REQUEST_SUBMITTED || + smb->mid_state =3D=3D MID_RESPONSE_RECEIVED)) || ((server->tcpStatus !=3D CifsGood) && (server->tcpStatus !=3D CifsNew))); =20 /* Were we interrupted by a signal ? */ spin_lock(&server->srv_lock); if ((rc =3D=3D -ERESTARTSYS) && - (midQ->mid_state =3D=3D MID_REQUEST_SUBMITTED || - midQ->mid_state =3D=3D MID_RESPONSE_RECEIVED) && + (smb->mid_state =3D=3D MID_REQUEST_SUBMITTED || + smb->mid_state =3D=3D MID_RESPONSE_RECEIVED) && ((server->tcpStatus =3D=3D CifsGood) || (server->tcpStatus =3D=3D CifsNew))) { spin_unlock(&server->srv_lock); @@ -505,9 +505,9 @@ SendReceiveBlockingLock(const unsigned int xid, struct = cifs_tcon *tcon, if (in_buf->Command =3D=3D SMB_COM_TRANSACTION2) { /* POSIX lock. We send a NT_CANCEL SMB to cause the blocking lock to return. */ - rc =3D send_cancel(server, &rqst, midQ); + rc =3D send_cancel(server, &rqst, smb); if (rc) { - delete_mid(midQ); + delete_mid(smb); return rc; } } else { @@ -519,19 +519,19 @@ SendReceiveBlockingLock(const unsigned int xid, struc= t cifs_tcon *tcon, /* If we get -ENOLCK back the lock may have already been removed. Don't exit in this case. */ if (rc && rc !=3D -ENOLCK) { - delete_mid(midQ); + delete_mid(smb); return rc; } } =20 - rc =3D wait_for_response(server, midQ); + rc =3D wait_for_response(server, smb); if (rc) { - send_cancel(server, &rqst, midQ); + send_cancel(server, &rqst, smb); spin_lock(&server->mid_lock); - if (midQ->mid_state =3D=3D MID_REQUEST_SUBMITTED || - midQ->mid_state =3D=3D MID_RESPONSE_RECEIVED) { + if (smb->mid_state =3D=3D MID_REQUEST_SUBMITTED || + smb->mid_state =3D=3D MID_RESPONSE_RECEIVED) { /* no longer considered to be "in-flight" */ - midQ->callback =3D release_mid; + smb->callback =3D release_mid; spin_unlock(&server->mid_lock); return rc; } @@ -544,22 +544,22 @@ SendReceiveBlockingLock(const unsigned int xid, struc= t cifs_tcon *tcon, } spin_unlock(&server->srv_lock); =20 - rc =3D cifs_sync_mid_result(midQ, server); + rc =3D cifs_sync_mid_result(smb, server); if (rc !=3D 0) return rc; =20 /* rcvd frame is ok */ - if (out_buf =3D=3D NULL || midQ->mid_state !=3D MID_RESPONSE_READY) { + if (out_buf =3D=3D NULL || smb->mid_state !=3D MID_RESPONSE_READY) { rc =3D -EIO; cifs_tcon_dbg(VFS, "Bad MID state?\n"); goto out; } =20 - *pbytes_returned =3D get_rfc1002_length(midQ->resp_buf); - memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4); - rc =3D cifs_check_receive(midQ, server, 0); + *pbytes_returned =3D get_rfc1002_length(smb->resp_buf); + memcpy(out_buf, smb->resp_buf, *pbytes_returned + 4); + rc =3D cifs_check_receive(smb, server, 0); out: - delete_mid(midQ); + delete_mid(smb); if (rstart && rc =3D=3D -EACCES) return -ERESTARTSYS; return rc; diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c index 205f547ca49e..9abaca4c8eba 100644 --- a/fs/smb/client/connect.c +++ b/fs/smb/client/connect.c @@ -293,7 +293,7 @@ cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server= _Info *server, static void cifs_abort_connection(struct TCP_Server_Info *server) { - struct mid_q_entry *mid, *nmid; + struct smb_message *smb, *nsmb; struct list_head retry_list; =20 server->maxBuf =3D 0; @@ -322,21 +322,21 @@ cifs_abort_connection(struct TCP_Server_Info *server) INIT_LIST_HEAD(&retry_list); cifs_dbg(FYI, "%s: moving mids to private list\n", __func__); spin_lock(&server->mid_lock); - list_for_each_entry_safe(mid, nmid, &server->pending_mid_q, qhead) { - kref_get(&mid->refcount); - if (mid->mid_state =3D=3D MID_REQUEST_SUBMITTED) - mid->mid_state =3D MID_RETRY_NEEDED; - list_move(&mid->qhead, &retry_list); - mid->mid_flags |=3D MID_DELETED; + list_for_each_entry_safe(smb, nsmb, &server->pending_mid_q, qhead) { + kref_get(&smb->refcount); + if (smb->mid_state =3D=3D MID_REQUEST_SUBMITTED) + smb->mid_state =3D MID_RETRY_NEEDED; + list_move(&smb->qhead, &retry_list); + smb->mid_flags |=3D MID_DELETED; } spin_unlock(&server->mid_lock); cifs_server_unlock(server); =20 cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__); - list_for_each_entry_safe(mid, nmid, &retry_list, qhead) { - list_del_init(&mid->qhead); - mid->callback(mid); - release_mid(mid); + list_for_each_entry_safe(smb, nsmb, &retry_list, qhead) { + list_del_init(&smb->qhead); + smb->callback(smb); + release_mid(smb); } =20 if (cifs_rdma_enabled(server)) { @@ -872,7 +872,7 @@ is_smb_response(struct TCP_Server_Info *server, unsigne= d char type) !server->with_rfc1001 && server->rfc1001_sessinit !=3D 0) { int rc, mid_rc; - struct mid_q_entry *mid, *nmid; + struct smb_message *smb, *nsmb; LIST_HEAD(dispose_list); =20 cifs_dbg(FYI, "RFC 1002 negative session response during SMB Negotiate,= retrying with NetBIOS session\n"); @@ -885,10 +885,10 @@ is_smb_response(struct TCP_Server_Info *server, unsig= ned char type) * corresponding to SMB1/SMB2 Negotiate packet. */ spin_lock(&server->mid_lock); - list_for_each_entry_safe(mid, nmid, &server->pending_mid_q, qhead) { - kref_get(&mid->refcount); - list_move(&mid->qhead, &dispose_list); - mid->mid_flags |=3D MID_DELETED; + list_for_each_entry_safe(smb, nsmb, &server->pending_mid_q, qhead) { + kref_get(&smb->refcount); + list_move(&smb->qhead, &dispose_list); + smb->mid_flags |=3D MID_DELETED; } spin_unlock(&server->mid_lock); =20 @@ -915,12 +915,12 @@ is_smb_response(struct TCP_Server_Info *server, unsig= ned char type) * callback. Use MID_RC state which indicates that the * return code should be read from mid_rc member. */ - list_for_each_entry_safe(mid, nmid, &dispose_list, qhead) { - list_del_init(&mid->qhead); - mid->mid_rc =3D mid_rc; - mid->mid_state =3D MID_RC; - mid->callback(mid); - release_mid(mid); + list_for_each_entry_safe(smb, nsmb, &dispose_list, qhead) { + list_del_init(&smb->qhead); + smb->mid_rc =3D mid_rc; + smb->mid_state =3D MID_RC; + smb->callback(smb); + release_mid(smb); } =20 /* @@ -952,27 +952,27 @@ is_smb_response(struct TCP_Server_Info *server, unsig= ned char type) } =20 void -dequeue_mid(struct mid_q_entry *mid, bool malformed) +dequeue_mid(struct smb_message *smb, bool malformed) { #ifdef CONFIG_CIFS_STATS2 - mid->when_received =3D jiffies; + smb->when_received =3D jiffies; #endif - spin_lock(&mid->server->mid_lock); + spin_lock(&smb->server->mid_lock); if (!malformed) - mid->mid_state =3D MID_RESPONSE_RECEIVED; + smb->mid_state =3D MID_RESPONSE_RECEIVED; else - mid->mid_state =3D MID_RESPONSE_MALFORMED; + smb->mid_state =3D MID_RESPONSE_MALFORMED; /* * Trying to handle/dequeue a mid after the send_recv() * function has finished processing it is a bug. */ - if (mid->mid_flags & MID_DELETED) { - spin_unlock(&mid->server->mid_lock); + if (smb->mid_flags & MID_DELETED) { + spin_unlock(&smb->server->mid_lock); pr_warn_once("trying to dequeue a deleted mid\n"); } else { - list_del_init(&mid->qhead); - mid->mid_flags |=3D MID_DELETED; - spin_unlock(&mid->server->mid_lock); + list_del_init(&smb->qhead); + smb->mid_flags |=3D MID_DELETED; + spin_unlock(&smb->server->mid_lock); } } =20 @@ -991,24 +991,24 @@ smb2_get_credits_from_hdr(char *buffer, struct TCP_Se= rver_Info *server) } =20 static void -handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server, +handle_mid(struct smb_message *smb, struct TCP_Server_Info *server, char *buf, int malformed) { if (server->ops->check_trans2 && - server->ops->check_trans2(mid, server, buf, malformed)) + server->ops->check_trans2(smb, server, buf, malformed)) return; - mid->credits_received =3D smb2_get_credits_from_hdr(buf, server); - mid->resp_buf =3D buf; - mid->large_buf =3D server->large_buf; + smb->credits_received =3D smb2_get_credits_from_hdr(buf, server); + smb->resp_buf =3D buf; + smb->large_buf =3D server->large_buf; /* Was previous buf put in mpx struct for multi-rsp? */ - if (!mid->multiRsp) { + if (!smb->multiRsp) { /* smb buffer will be freed by user thread */ if (server->large_buf) server->bigbuf =3D NULL; else server->smallbuf =3D NULL; } - dequeue_mid(mid, malformed); + dequeue_mid(smb, malformed); } =20 int @@ -1097,28 +1097,28 @@ clean_demultiplex_info(struct TCP_Server_Info *serv= er) } =20 if (!list_empty(&server->pending_mid_q)) { - struct mid_q_entry *mid_entry; + struct smb_message *smb; struct list_head *tmp, *tmp2; LIST_HEAD(dispose_list); =20 spin_lock(&server->mid_lock); list_for_each_safe(tmp, tmp2, &server->pending_mid_q) { - mid_entry =3D list_entry(tmp, struct mid_q_entry, qhead); - cifs_dbg(FYI, "Clearing mid %llu\n", mid_entry->mid); - kref_get(&mid_entry->refcount); - mid_entry->mid_state =3D MID_SHUTDOWN; - list_move(&mid_entry->qhead, &dispose_list); - mid_entry->mid_flags |=3D MID_DELETED; + smb =3D list_entry(tmp, struct smb_message, qhead); + cifs_dbg(FYI, "Clearing mid %llu\n", smb->mid); + kref_get(&smb->refcount); + smb->mid_state =3D MID_SHUTDOWN; + list_move(&smb->qhead, &dispose_list); + smb->mid_flags |=3D MID_DELETED; } spin_unlock(&server->mid_lock); =20 /* now walk dispose list and issue callbacks */ list_for_each_safe(tmp, tmp2, &dispose_list) { - mid_entry =3D list_entry(tmp, struct mid_q_entry, qhead); - cifs_dbg(FYI, "Callback mid %llu\n", mid_entry->mid); - list_del_init(&mid_entry->qhead); - mid_entry->callback(mid_entry); - release_mid(mid_entry); + smb =3D list_entry(tmp, struct smb_message, qhead); + cifs_dbg(FYI, "Callback mid %llu\n", smb->mid); + list_del_init(&smb->qhead); + smb->callback(smb); + release_mid(smb); } /* 1/8th of sec is more than enough time for them to exit */ msleep(125); @@ -1152,7 +1152,7 @@ clean_demultiplex_info(struct TCP_Server_Info *server) } =20 static int -standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid) +standard_receive3(struct TCP_Server_Info *server, struct smb_message *smb) { int length; char *buf =3D server->smallbuf; @@ -1183,11 +1183,11 @@ standard_receive3(struct TCP_Server_Info *server, s= truct mid_q_entry *mid) =20 dump_smb(buf, server->total_read); =20 - return cifs_handle_standard(server, mid); + return cifs_handle_standard(server, smb); } =20 int -cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *m= id) +cifs_handle_standard(struct TCP_Server_Info *server, struct smb_message *s= mb) { char *buf =3D server->large_buf ? server->bigbuf : server->smallbuf; int rc; @@ -1215,10 +1215,10 @@ cifs_handle_standard(struct TCP_Server_Info *server= , struct mid_q_entry *mid) server->ops->is_status_pending(buf, server)) return -1; =20 - if (!mid) + if (!smb) return rc; =20 - handle_mid(mid, server, buf, rc); + handle_mid(smb, server, buf, rc); return 0; } =20 @@ -1255,13 +1255,13 @@ smb2_add_credits_from_hdr(char *buffer, struct TCP_= Server_Info *server) static int cifs_demultiplex_thread(void *p) { - int i, num_mids, length; + int i, num_smbs, length; struct TCP_Server_Info *server =3D p; unsigned int pdu_length; unsigned int next_offset; char *buf =3D NULL; struct task_struct *task_to_wake =3D NULL; - struct mid_q_entry *mids[MAX_COMPOUND]; + struct smb_message *smbs[MAX_COMPOUND]; char *bufs[MAX_COMPOUND]; unsigned int noreclaim_flag, num_io_timeout =3D 0; bool pending_reconnect =3D false; @@ -1336,32 +1336,32 @@ cifs_demultiplex_thread(void *p) server->pdu_size =3D next_offset; } =20 - memset(mids, 0, sizeof(mids)); + memset(smbs, 0, sizeof(smbs)); memset(bufs, 0, sizeof(bufs)); - num_mids =3D 0; + num_smbs =3D 0; =20 if (server->ops->is_transform_hdr && server->ops->receive_transform && server->ops->is_transform_hdr(buf)) { length =3D server->ops->receive_transform(server, - mids, + smbs, bufs, - &num_mids); + &num_smbs); } else { - mids[0] =3D server->ops->find_mid(server, buf); + smbs[0] =3D server->ops->find_mid(server, buf); bufs[0] =3D buf; - num_mids =3D 1; + num_smbs =3D 1; =20 - if (!mids[0] || !mids[0]->receive) - length =3D standard_receive3(server, mids[0]); + if (!smbs[0] || !smbs[0]->receive) + length =3D standard_receive3(server, smbs[0]); else - length =3D mids[0]->receive(server, mids[0]); + length =3D smbs[0]->receive(server, smbs[0]); } =20 if (length < 0) { - for (i =3D 0; i < num_mids; i++) - if (mids[i]) - release_mid(mids[i]); + for (i =3D 0; i < num_smbs; i++) + if (smbs[i]) + release_mid(smbs[i]); continue; } =20 @@ -1380,9 +1380,9 @@ cifs_demultiplex_thread(void *p) =20 server->lstrp =3D jiffies; =20 - for (i =3D 0; i < num_mids; i++) { - if (mids[i] !=3D NULL) { - mids[i]->resp_buf_size =3D server->pdu_size; + for (i =3D 0; i < num_smbs; i++) { + if (smbs[i] !=3D NULL) { + smbs[i]->resp_buf_size =3D server->pdu_size; =20 if (bufs[i] !=3D NULL) { if (server->ops->is_network_name_deleted && @@ -1393,10 +1393,10 @@ cifs_demultiplex_thread(void *p) } } =20 - if (!mids[i]->multiRsp || mids[i]->multiEnd) - mids[i]->callback(mids[i]); + if (!smbs[i]->multiRsp || smbs[i]->multiEnd) + smbs[i]->callback(smbs[i]); =20 - release_mid(mids[i]); + release_mid(smbs[i]); } else if (server->ops->is_oplock_break && server->ops->is_oplock_break(bufs[i], server)) { diff --git a/fs/smb/client/netmisc.c b/fs/smb/client/netmisc.c index 9ec20601cee2..b34d2b91cf5a 100644 --- a/fs/smb/client/netmisc.c +++ b/fs/smb/client/netmisc.c @@ -889,22 +889,22 @@ map_smb_to_linux_error(char *buf, bool logErr) } =20 int -map_and_check_smb_error(struct mid_q_entry *mid, bool logErr) +map_and_check_smb_error(struct smb_message *smb, bool logErr) { int rc; - struct smb_hdr *smb =3D (struct smb_hdr *)mid->resp_buf; + struct smb_hdr *rhdr =3D (struct smb_hdr *)smb->resp_buf; =20 - rc =3D map_smb_to_linux_error((char *)smb, logErr); - if (rc =3D=3D -EACCES && !(smb->Flags2 & SMBFLG2_ERR_STATUS)) { + rc =3D map_smb_to_linux_error((char *)rhdr, logErr); + if (rc =3D=3D -EACCES && !(rhdr->Flags2 & SMBFLG2_ERR_STATUS)) { /* possible ERRBaduid */ - __u8 class =3D smb->Status.DosError.ErrorClass; - __u16 code =3D le16_to_cpu(smb->Status.DosError.Error); + __u8 class =3D rhdr->Status.DosError.ErrorClass; + __u16 code =3D le16_to_cpu(rhdr->Status.DosError.Error); =20 /* switch can be used to handle different errors */ if (class =3D=3D ERRSRV && code =3D=3D ERRbaduid) { cifs_dbg(FYI, "Server returned 0x%x, reconnecting session...\n", code); - cifs_signal_cifsd_for_reconnect(mid->server, false); + cifs_signal_cifsd_for_reconnect(smb->server, false); } } =20 diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c index b27a182629ec..ba301c94d4ff 100644 --- a/fs/smb/client/smb1ops.c +++ b/fs/smb/client/smb1ops.c @@ -29,7 +29,7 @@ */ static int send_nt_cancel(struct TCP_Server_Info *server, struct smb_rqst *rqst, - struct mid_q_entry *mid) + struct smb_message *smb) { int rc =3D 0; struct smb_hdr *in_buf =3D (struct smb_hdr *)rqst->rq_iov[0].iov_base; @@ -41,7 +41,7 @@ send_nt_cancel(struct TCP_Server_Info *server, struct smb= _rqst *rqst, put_bcc(0, in_buf); =20 cifs_server_lock(server); - rc =3D cifs_sign_smb(in_buf, server, &mid->sequence_number); + rc =3D cifs_sign_smb(in_buf, server, &smb->sequence_number); if (rc) { cifs_server_unlock(server); return rc; @@ -88,20 +88,20 @@ cifs_read_data_length(char *buf, bool in_remaining) le16_to_cpu(rsp->DataLength); } =20 -static struct mid_q_entry * +static struct smb_message * cifs_find_mid(struct TCP_Server_Info *server, char *buffer) { struct smb_hdr *buf =3D (struct smb_hdr *)buffer; - struct mid_q_entry *mid; + struct smb_message *smb; =20 spin_lock(&server->mid_lock); - list_for_each_entry(mid, &server->pending_mid_q, qhead) { - if (compare_mid(mid->mid, buf) && - mid->mid_state =3D=3D MID_REQUEST_SUBMITTED && - le16_to_cpu(mid->command) =3D=3D buf->Command) { - kref_get(&mid->refcount); + list_for_each_entry(smb, &server->pending_mid_q, qhead) { + if (compare_mid(smb->mid, buf) && + smb->mid_state =3D=3D MID_REQUEST_SUBMITTED && + le16_to_cpu(smb->command) =3D=3D buf->Command) { + kref_get(&smb->refcount); spin_unlock(&server->mid_lock); - return mid; + return smb; } } spin_unlock(&server->mid_lock); @@ -135,7 +135,7 @@ cifs_get_credits_field(struct TCP_Server_Info *server, = const int optype) } =20 static unsigned int -cifs_get_credits(struct mid_q_entry *mid) +cifs_get_credits(struct smb_message *smb) { return 1; } @@ -189,7 +189,7 @@ cifs_get_next_mid(struct TCP_Server_Info *server) * did not time out). */ while (cur_mid !=3D last_mid) { - struct mid_q_entry *mid_entry; + struct smb_message *smb; unsigned int num_mids; =20 collision =3D false; @@ -197,10 +197,10 @@ cifs_get_next_mid(struct TCP_Server_Info *server) cur_mid++; =20 num_mids =3D 0; - list_for_each_entry(mid_entry, &server->pending_mid_q, qhead) { + list_for_each_entry(smb, &server->pending_mid_q, qhead) { ++num_mids; - if (mid_entry->mid =3D=3D cur_mid && - mid_entry->mid_state =3D=3D MID_REQUEST_SUBMITTED) { + if (smb->mid =3D=3D cur_mid && + smb->mid_state =3D=3D MID_REQUEST_SUBMITTED) { /* This mid is in use, try a different one */ collision =3D true; break; @@ -385,22 +385,22 @@ cifs_downgrade_oplock(struct TCP_Server_Info *server, } =20 static bool -cifs_check_trans2(struct mid_q_entry *mid, struct TCP_Server_Info *server, +cifs_check_trans2(struct smb_message *smb, struct TCP_Server_Info *server, char *buf, int malformed) { if (malformed) return false; if (check2ndT2(buf) <=3D 0) return false; - mid->multiRsp =3D true; - if (mid->resp_buf) { + smb->multiRsp =3D true; + if (smb->resp_buf) { /* merge response - fix up 1st*/ - malformed =3D coalesce_t2(buf, mid->resp_buf); + malformed =3D coalesce_t2(buf, smb->resp_buf); if (malformed > 0) return true; /* All parts received or packet is malformed. */ - mid->multiEnd =3D true; - dequeue_mid(mid, malformed); + smb->multiEnd =3D true; + dequeue_mid(smb, malformed); return true; } if (!server->large_buf) { @@ -408,8 +408,8 @@ cifs_check_trans2(struct mid_q_entry *mid, struct TCP_S= erver_Info *server, cifs_dbg(VFS, "1st trans2 resp needs bigbuf\n"); } else { /* Have first buffer */ - mid->resp_buf =3D buf; - mid->large_buf =3D true; + smb->resp_buf =3D buf; + smb->large_buf =3D true; server->bigbuf =3D NULL; } return true; diff --git a/fs/smb/client/smb2misc.c b/fs/smb/client/smb2misc.c index 93ce9fc7b4a4..f1b0546c7858 100644 --- a/fs/smb/client/smb2misc.c +++ b/fs/smb/client/smb2misc.c @@ -839,14 +839,14 @@ smb2_handle_cancelled_close(struct cifs_tcon *tcon, _= _u64 persistent_fid, } =20 int -smb2_handle_cancelled_mid(struct mid_q_entry *mid, struct TCP_Server_Info = *server) +smb2_handle_cancelled_mid(struct smb_message *smb, struct TCP_Server_Info = *server) { - struct smb2_hdr *hdr =3D mid->resp_buf; - struct smb2_create_rsp *rsp =3D mid->resp_buf; + struct smb2_hdr *hdr =3D smb->resp_buf; + struct smb2_create_rsp *rsp =3D smb->resp_buf; struct cifs_tcon *tcon; int rc; =20 - if ((mid->optype & CIFS_CP_CREATE_CLOSE_OP) || hdr->Command !=3D SMB2_CRE= ATE || + if ((smb->optype & CIFS_CP_CREATE_CLOSE_OP) || hdr->Command !=3D SMB2_CRE= ATE || hdr->Status !=3D STATUS_SUCCESS) return 0; =20 diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c index 1468c16ea9b8..a7ba4a77721e 100644 --- a/fs/smb/client/smb2ops.c +++ b/fs/smb/client/smb2ops.c @@ -226,9 +226,9 @@ smb2_get_credits_field(struct TCP_Server_Info *server, = const int optype) } =20 static unsigned int -smb2_get_credits(struct mid_q_entry *mid) +smb2_get_credits(struct smb_message *smb) { - return mid->credits_received; + return smb->credits_received; } =20 static int @@ -389,10 +389,10 @@ smb2_revert_current_mid(struct TCP_Server_Info *serve= r, const unsigned int val) spin_unlock(&server->mid_lock); } =20 -static struct mid_q_entry * +static struct smb_message * __smb2_find_mid(struct TCP_Server_Info *server, char *buf, bool dequeue) { - struct mid_q_entry *mid; + struct smb_message *smb; struct smb2_hdr *shdr =3D (struct smb2_hdr *)buf; __u64 wire_mid =3D le64_to_cpu(shdr->MessageId); =20 @@ -402,30 +402,30 @@ __smb2_find_mid(struct TCP_Server_Info *server, char = *buf, bool dequeue) } =20 spin_lock(&server->mid_lock); - list_for_each_entry(mid, &server->pending_mid_q, qhead) { - if ((mid->mid =3D=3D wire_mid) && - (mid->mid_state =3D=3D MID_REQUEST_SUBMITTED) && - (mid->command =3D=3D shdr->Command)) { - kref_get(&mid->refcount); + list_for_each_entry(smb, &server->pending_mid_q, qhead) { + if ((smb->mid =3D=3D wire_mid) && + (smb->mid_state =3D=3D MID_REQUEST_SUBMITTED) && + (smb->command =3D=3D shdr->Command)) { + kref_get(&smb->refcount); if (dequeue) { - list_del_init(&mid->qhead); - mid->mid_flags |=3D MID_DELETED; + list_del_init(&smb->qhead); + smb->mid_flags |=3D MID_DELETED; } spin_unlock(&server->mid_lock); - return mid; + return smb; } } spin_unlock(&server->mid_lock); return NULL; } =20 -static struct mid_q_entry * +static struct smb_message * smb2_find_mid(struct TCP_Server_Info *server, char *buf) { return __smb2_find_mid(server, buf, false); } =20 -static struct mid_q_entry * +static struct smb_message * smb2_find_dequeue_mid(struct TCP_Server_Info *server, char *buf) { return __smb2_find_mid(server, buf, true); @@ -4611,7 +4611,7 @@ cifs_copy_folioq_to_iter(struct folio_queue *folioq, = size_t data_size, } =20 static int -handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid, +handle_read_data(struct TCP_Server_Info *server, struct smb_message *smb, char *buf, unsigned int buf_len, struct folio_queue *buffer, unsigned int buffer_len, bool is_offloaded) { @@ -4620,7 +4620,7 @@ handle_read_data(struct TCP_Server_Info *server, stru= ct mid_q_entry *mid, unsigned int cur_off; unsigned int cur_page_idx; unsigned int pad_len; - struct cifs_io_subrequest *rdata =3D mid->callback_data; + struct cifs_io_subrequest *rdata =3D smb->callback_data; struct smb2_hdr *shdr =3D (struct smb2_hdr *)buf; int length; bool use_rdma_mr =3D false; @@ -4658,9 +4658,9 @@ handle_read_data(struct TCP_Server_Info *server, stru= ct mid_q_entry *mid, __func__, rdata->result); /* normal error on read response */ if (is_offloaded) - mid->mid_state =3D MID_RESPONSE_RECEIVED; + smb->mid_state =3D MID_RESPONSE_RECEIVED; else - dequeue_mid(mid, false); + dequeue_mid(smb, false); return 0; } =20 @@ -4685,9 +4685,9 @@ handle_read_data(struct TCP_Server_Info *server, stru= ct mid_q_entry *mid, __func__, data_offset); rdata->result =3D -EIO; if (is_offloaded) - mid->mid_state =3D MID_RESPONSE_MALFORMED; + smb->mid_state =3D MID_RESPONSE_MALFORMED; else - dequeue_mid(mid, rdata->result); + dequeue_mid(smb, rdata->result); return 0; } =20 @@ -4704,9 +4704,9 @@ handle_read_data(struct TCP_Server_Info *server, stru= ct mid_q_entry *mid, __func__, data_offset); rdata->result =3D -EIO; if (is_offloaded) - mid->mid_state =3D MID_RESPONSE_MALFORMED; + smb->mid_state =3D MID_RESPONSE_MALFORMED; else - dequeue_mid(mid, rdata->result); + dequeue_mid(smb, rdata->result); return 0; } =20 @@ -4714,9 +4714,9 @@ handle_read_data(struct TCP_Server_Info *server, stru= ct mid_q_entry *mid, /* data_len is corrupt -- discard frame */ rdata->result =3D -EIO; if (is_offloaded) - mid->mid_state =3D MID_RESPONSE_MALFORMED; + smb->mid_state =3D MID_RESPONSE_MALFORMED; else - dequeue_mid(mid, rdata->result); + dequeue_mid(smb, rdata->result); return 0; } =20 @@ -4725,9 +4725,9 @@ handle_read_data(struct TCP_Server_Info *server, stru= ct mid_q_entry *mid, cur_off, &rdata->subreq.io_iter); if (rdata->result !=3D 0) { if (is_offloaded) - mid->mid_state =3D MID_RESPONSE_MALFORMED; + smb->mid_state =3D MID_RESPONSE_MALFORMED; else - dequeue_mid(mid, rdata->result); + dequeue_mid(smb, rdata->result); return 0; } rdata->got_bytes =3D buffer_len; @@ -4744,16 +4744,16 @@ handle_read_data(struct TCP_Server_Info *server, st= ruct mid_q_entry *mid, WARN_ONCE(1, "buf can not contain only a part of read data"); rdata->result =3D -EIO; if (is_offloaded) - mid->mid_state =3D MID_RESPONSE_MALFORMED; + smb->mid_state =3D MID_RESPONSE_MALFORMED; else - dequeue_mid(mid, rdata->result); + dequeue_mid(smb, rdata->result); return 0; } =20 if (is_offloaded) - mid->mid_state =3D MID_RESPONSE_RECEIVED; + smb->mid_state =3D MID_RESPONSE_RECEIVED; else - dequeue_mid(mid, false); + dequeue_mid(smb, false); return 0; } =20 @@ -4771,7 +4771,7 @@ static void smb2_decrypt_offload(struct work_struct *= work) struct smb2_decrypt_work *dw =3D container_of(work, struct smb2_decrypt_work, decrypt); int rc; - struct mid_q_entry *mid; + struct smb_message *smb; struct iov_iter iter; =20 iov_iter_folio_queue(&iter, ITER_DEST, dw->buffer, 0, 0, dw->len); @@ -4783,43 +4783,43 @@ static void smb2_decrypt_offload(struct work_struct= *work) } =20 dw->server->lstrp =3D jiffies; - mid =3D smb2_find_dequeue_mid(dw->server, dw->buf); - if (mid =3D=3D NULL) + smb =3D smb2_find_dequeue_mid(dw->server, dw->buf); + if (smb =3D=3D NULL) cifs_dbg(FYI, "mid not found\n"); else { - mid->decrypted =3D true; - rc =3D handle_read_data(dw->server, mid, dw->buf, + smb->decrypted =3D true; + rc =3D handle_read_data(dw->server, smb, dw->buf, dw->server->vals->read_rsp_size, dw->buffer, dw->len, true); if (rc >=3D 0) { #ifdef CONFIG_CIFS_STATS2 - mid->when_received =3D jiffies; + smb->when_received =3D jiffies; #endif if (dw->server->ops->is_network_name_deleted) dw->server->ops->is_network_name_deleted(dw->buf, dw->server); =20 - mid->callback(mid); + smb->callback(smb); } else { spin_lock(&dw->server->srv_lock); if (dw->server->tcpStatus =3D=3D CifsNeedReconnect) { spin_lock(&dw->server->mid_lock); - mid->mid_state =3D MID_RETRY_NEEDED; + smb->mid_state =3D MID_RETRY_NEEDED; spin_unlock(&dw->server->mid_lock); spin_unlock(&dw->server->srv_lock); - mid->callback(mid); + smb->callback(smb); } else { spin_lock(&dw->server->mid_lock); - mid->mid_state =3D MID_REQUEST_SUBMITTED; - mid->mid_flags &=3D ~(MID_DELETED); - list_add_tail(&mid->qhead, + smb->mid_state =3D MID_REQUEST_SUBMITTED; + smb->mid_flags &=3D ~(MID_DELETED); + list_add_tail(&smb->qhead, &dw->server->pending_mid_q); spin_unlock(&dw->server->mid_lock); spin_unlock(&dw->server->srv_lock); } } - release_mid(mid); + release_mid(smb); } =20 free_pages: @@ -4830,7 +4830,7 @@ static void smb2_decrypt_offload(struct work_struct *= work) =20 =20 static int -receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry = **mid, +receive_encrypted_read(struct TCP_Server_Info *server, struct smb_message = **smb, int *num_mids) { char *buf =3D server->smallbuf; @@ -4906,13 +4906,13 @@ receive_encrypted_read(struct TCP_Server_Info *serv= er, struct mid_q_entry **mid, if (rc) goto free_pages; =20 - *mid =3D smb2_find_mid(server, buf); - if (*mid =3D=3D NULL) { + *smb =3D smb2_find_mid(server, buf); + if (*smb =3D=3D NULL) { cifs_dbg(FYI, "mid not found\n"); } else { cifs_dbg(FYI, "mid found\n"); - (*mid)->decrypted =3D true; - rc =3D handle_read_data(server, *mid, buf, + (*smb)->decrypted =3D true; + rc =3D handle_read_data(server, *smb, buf, server->vals->read_rsp_size, dw->buffer, dw->len, false); if (rc >=3D 0) { @@ -4935,7 +4935,7 @@ receive_encrypted_read(struct TCP_Server_Info *server= , struct mid_q_entry **mid, =20 static int receive_encrypted_standard(struct TCP_Server_Info *server, - struct mid_q_entry **mids, char **bufs, + struct smb_message **mids, char **bufs, int *num_mids) { int ret, length; @@ -4944,7 +4944,7 @@ receive_encrypted_standard(struct TCP_Server_Info *se= rver, unsigned int pdu_length =3D server->pdu_size; unsigned int buf_size; unsigned int next_cmd; - struct mid_q_entry *mid_entry; + struct smb_message *smb; int next_is_large; char *next_buffer =3D NULL; =20 @@ -4987,13 +4987,13 @@ receive_encrypted_standard(struct TCP_Server_Info *= server, memcpy(next_buffer, buf + next_cmd, pdu_length - next_cmd); } =20 - mid_entry =3D smb2_find_mid(server, buf); - if (mid_entry =3D=3D NULL) + smb =3D smb2_find_mid(server, buf); + if (smb =3D=3D NULL) cifs_dbg(FYI, "mid not found\n"); else { cifs_dbg(FYI, "mid found\n"); - mid_entry->decrypted =3D true; - mid_entry->resp_buf_size =3D server->pdu_size; + smb->decrypted =3D true; + smb->resp_buf_size =3D server->pdu_size; } =20 if (*num_mids >=3D MAX_COMPOUND) { @@ -5001,12 +5001,12 @@ receive_encrypted_standard(struct TCP_Server_Info *= server, return -1; } bufs[*num_mids] =3D buf; - mids[(*num_mids)++] =3D mid_entry; + mids[(*num_mids)++] =3D smb; =20 - if (mid_entry && mid_entry->handle) - ret =3D mid_entry->handle(server, mid_entry); + if (smb && smb->handle) + ret =3D smb->handle(server, smb); else - ret =3D cifs_handle_standard(server, mid_entry); + ret =3D cifs_handle_standard(server, smb); =20 if (ret =3D=3D 0 && next_cmd) { pdu_length -=3D next_cmd; @@ -5034,7 +5034,7 @@ receive_encrypted_standard(struct TCP_Server_Info *se= rver, =20 static int smb3_receive_transform(struct TCP_Server_Info *server, - struct mid_q_entry **mids, char **bufs, int *num_mids) + struct smb_message **mids, char **bufs, int *num_mids) { char *buf =3D server->smallbuf; unsigned int pdu_length =3D server->pdu_size; @@ -5064,11 +5064,11 @@ smb3_receive_transform(struct TCP_Server_Info *serv= er, } =20 int -smb3_handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *= mid) +smb3_handle_read_data(struct TCP_Server_Info *server, struct smb_message *= smb) { char *buf =3D server->large_buf ? server->bigbuf : server->smallbuf; =20 - return handle_read_data(server, mid, buf, server->pdu_size, + return handle_read_data(server, smb, buf, server->pdu_size, NULL, 0, false); } =20 diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c index 96df4aa7a7af..645d67d04a8d 100644 --- a/fs/smb/client/smb2pdu.c +++ b/fs/smb/client/smb2pdu.c @@ -4089,19 +4089,19 @@ SMB2_change_notify(const unsigned int xid, struct c= ifs_tcon *tcon, * FIXME: maybe we should consider checking that the reply matches request? */ static void -smb2_echo_callback(struct mid_q_entry *mid) +smb2_echo_callback(struct smb_message *smb) { - struct TCP_Server_Info *server =3D mid->callback_data; - struct smb2_echo_rsp *rsp =3D (struct smb2_echo_rsp *)mid->resp_buf; + struct TCP_Server_Info *server =3D smb->callback_data; + struct smb2_echo_rsp *rsp =3D (struct smb2_echo_rsp *)smb->resp_buf; struct cifs_credits credits =3D { .value =3D 0, .instance =3D 0 }; =20 - if (mid->mid_state =3D=3D MID_RESPONSE_RECEIVED - || mid->mid_state =3D=3D MID_RESPONSE_MALFORMED) { + if (smb->mid_state =3D=3D MID_RESPONSE_RECEIVED + || smb->mid_state =3D=3D MID_RESPONSE_MALFORMED) { credits.value =3D le16_to_cpu(rsp->hdr.CreditRequest); credits.instance =3D server->reconnect_instance; } =20 - release_mid(mid); + release_mid(smb); add_credits(server, &credits, CIFS_ECHO_OP); } =20 @@ -4516,14 +4516,13 @@ smb2_new_read_req(void **buf, unsigned int *total_l= en, } =20 static void -smb2_readv_callback(struct mid_q_entry *mid) +smb2_readv_callback(struct smb_message *smb) { - struct cifs_io_subrequest *rdata =3D mid->callback_data; + struct cifs_io_subrequest *rdata =3D smb->callback_data; struct netfs_inode *ictx =3D netfs_inode(rdata->rreq->inode); struct cifs_tcon *tcon =3D tlink_tcon(rdata->req->cfile->tlink); struct TCP_Server_Info *server =3D rdata->server; - struct smb2_hdr *shdr =3D - (struct smb2_hdr *)rdata->iov[0].iov_base; + struct smb2_hdr *shdr =3D (struct smb2_hdr *)rdata->iov[0].iov_base; struct cifs_credits credits =3D { .value =3D 0, .instance =3D 0, @@ -4538,20 +4537,20 @@ smb2_readv_callback(struct mid_q_entry *mid) rqst.rq_iter =3D rdata->subreq.io_iter; } =20 - WARN_ONCE(rdata->server !=3D mid->server, + WARN_ONCE(rdata->server !=3D smb->server, "rdata server %p !=3D mid server %p", - rdata->server, mid->server); + rdata->server, smb->server); =20 cifs_dbg(FYI, "%s: mid=3D%llu state=3D%d result=3D%d bytes=3D%zu/%zu\n", - __func__, mid->mid, mid->mid_state, rdata->result, + __func__, smb->mid, smb->mid_state, rdata->result, rdata->got_bytes, rdata->subreq.len - rdata->subreq.transferred); =20 - switch (mid->mid_state) { + switch (smb->mid_state) { case MID_RESPONSE_RECEIVED: credits.value =3D le16_to_cpu(shdr->CreditRequest); credits.instance =3D server->reconnect_instance; /* result already set, check signature */ - if (server->sign && !mid->decrypted) { + if (server->sign && !smb->decrypted) { int rc; =20 iov_iter_truncate(&rqst.rq_iter, rdata->got_bytes); @@ -4641,7 +4640,7 @@ smb2_readv_callback(struct mid_q_entry *mid) rdata->subreq.transferred +=3D rdata->got_bytes; trace_netfs_sreq(&rdata->subreq, netfs_sreq_trace_io_progress); netfs_read_subreq_terminated(&rdata->subreq); - release_mid(mid); + release_mid(smb); trace_smb3_rw_credits(rreq_debug_id, subreq_debug_index, 0, server->credits, server->in_flight, credits.value, cifs_trace_rw_credits_read_response_add); @@ -4818,12 +4817,12 @@ SMB2_read(const unsigned int xid, struct cifs_io_pa= rms *io_parms, * workqueue completion task. */ static void -smb2_writev_callback(struct mid_q_entry *mid) +smb2_writev_callback(struct smb_message *smb) { - struct cifs_io_subrequest *wdata =3D mid->callback_data; + struct cifs_io_subrequest *wdata =3D smb->callback_data; struct cifs_tcon *tcon =3D tlink_tcon(wdata->req->cfile->tlink); struct TCP_Server_Info *server =3D wdata->server; - struct smb2_write_rsp *rsp =3D (struct smb2_write_rsp *)mid->resp_buf; + struct smb2_write_rsp *rsp =3D (struct smb2_write_rsp *)smb->resp_buf; struct cifs_credits credits =3D { .value =3D 0, .instance =3D 0, @@ -4835,16 +4834,16 @@ smb2_writev_callback(struct mid_q_entry *mid) ssize_t result =3D 0; size_t written; =20 - WARN_ONCE(wdata->server !=3D mid->server, + WARN_ONCE(wdata->server !=3D smb->server, "wdata server %p !=3D mid server %p", - wdata->server, mid->server); + wdata->server, smb->server); =20 - switch (mid->mid_state) { + switch (smb->mid_state) { case MID_RESPONSE_RECEIVED: trace_netfs_sreq(&wdata->subreq, netfs_sreq_trace_io_progress); credits.value =3D le16_to_cpu(rsp->hdr.CreditRequest); credits.instance =3D server->reconnect_instance; - result =3D smb2_check_receive(mid, server, 0); + result =3D smb2_check_receive(smb, server, 0); if (result !=3D 0) { trace_netfs_sreq(&wdata->subreq, netfs_sreq_trace_io_bad); break; @@ -4927,7 +4926,7 @@ smb2_writev_callback(struct mid_q_entry *mid) 0, cifs_trace_rw_credits_write_response_clear); wdata->credits.value =3D 0; cifs_write_subrequest_terminated(wdata, result ?: written); - release_mid(mid); + release_mid(smb); trace_smb3_rw_credits(rreq_debug_id, subreq_debug_index, 0, server->credits, server->in_flight, credits.value, cifs_trace_rw_credits_write_response_add); diff --git a/fs/smb/client/smb2proto.h b/fs/smb/client/smb2proto.h index 035aa1624053..6f1ce0399334 100644 --- a/fs/smb/client/smb2proto.h +++ b/fs/smb/client/smb2proto.h @@ -30,12 +30,12 @@ extern __le16 *cifs_convert_path_to_utf16(const char *f= rom, struct cifs_sb_info *cifs_sb); =20 extern int smb2_verify_signature(struct smb_rqst *, struct TCP_Server_Info= *); -extern int smb2_check_receive(struct mid_q_entry *mid, +extern int smb2_check_receive(struct smb_message *smb, struct TCP_Server_Info *server, bool log_error); -extern struct mid_q_entry *smb2_setup_request(struct cifs_ses *ses, +extern struct smb_message *smb2_setup_request(struct cifs_ses *ses, struct TCP_Server_Info *, struct smb_rqst *rqst); -extern struct mid_q_entry *smb2_setup_async_request( +extern struct smb_message *smb2_setup_async_request( struct TCP_Server_Info *server, struct smb_rqst *rqst); extern struct cifs_tcon *smb2_find_smb_tcon(struct TCP_Server_Info *server, __u64 ses_id, __u32 tid); @@ -50,7 +50,7 @@ extern __le32 smb2_get_lease_state(struct cifsInodeInfo *= cinode); extern bool smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv); extern int smb3_handle_read_data(struct TCP_Server_Info *server, - struct mid_q_entry *mid); + struct smb_message *smb); extern int smb2_query_reparse_tag(const unsigned int xid, struct cifs_tcon= *tcon, struct cifs_sb_info *cifs_sb, const char *path, __u32 *reparse_tag); @@ -257,7 +257,7 @@ extern int SMB2_oplock_break(const unsigned int xid, st= ruct cifs_tcon *tcon, extern int smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u64 persistent_fid, __u64 volatile_fid); -extern int smb2_handle_cancelled_mid(struct mid_q_entry *mid, struct TCP_S= erver_Info *server); +extern int smb2_handle_cancelled_mid(struct smb_message *smb, struct TCP_S= erver_Info *server); void smb2_cancelled_close_fid(struct work_struct *work); extern int SMB311_posix_qfs_info(const unsigned int xid, struct cifs_tcon = *tcon, u64 persistent_file_id, u64 volatile_file_id, diff --git a/fs/smb/client/smb2transport.c b/fs/smb/client/smb2transport.c index 475b36c27f65..5348bfd5fad0 100644 --- a/fs/smb/client/smb2transport.c +++ b/fs/smb/client/smb2transport.c @@ -756,11 +756,11 @@ smb2_seq_num_into_buf(struct TCP_Server_Info *server, get_next_mid(server); } =20 -static struct mid_q_entry * +static struct smb_message * smb2_mid_entry_alloc(const struct smb2_hdr *shdr, struct TCP_Server_Info *server) { - struct mid_q_entry *temp; + struct smb_message *smb; unsigned int credits =3D le16_to_cpu(shdr->CreditCharge); =20 if (server =3D=3D NULL) { @@ -768,36 +768,36 @@ smb2_mid_entry_alloc(const struct smb2_hdr *shdr, return NULL; } =20 - temp =3D mempool_alloc(cifs_mid_poolp, GFP_NOFS); - memset(temp, 0, sizeof(struct mid_q_entry)); - kref_init(&temp->refcount); - temp->mid =3D le64_to_cpu(shdr->MessageId); - temp->credits =3D credits > 0 ? credits : 1; - temp->pid =3D current->pid; - temp->command =3D shdr->Command; /* Always LE */ - temp->when_alloc =3D jiffies; - temp->server =3D server; + smb =3D mempool_alloc(&smb_message_pool, GFP_NOFS); + memset(smb, 0, sizeof(*smb)); + kref_init(&smb->refcount); + smb->mid =3D le64_to_cpu(shdr->MessageId); + smb->credits =3D credits > 0 ? credits : 1; + smb->pid =3D current->pid; + smb->command =3D shdr->Command; /* Always LE */ + smb->when_alloc =3D jiffies; + smb->server =3D server; =20 /* * The default is for the mid to be synchronous, so the * default callback just wakes up the current task. */ get_task_struct(current); - temp->creator =3D current; - temp->callback =3D cifs_wake_up_task; - temp->callback_data =3D current; + smb->creator =3D current; + smb->callback =3D cifs_wake_up_task; + smb->callback_data =3D current; =20 atomic_inc(&mid_count); - temp->mid_state =3D MID_REQUEST_ALLOCATED; + smb->mid_state =3D MID_REQUEST_ALLOCATED; trace_smb3_cmd_enter(le32_to_cpu(shdr->Id.SyncId.TreeId), le64_to_cpu(shdr->SessionId), - le16_to_cpu(shdr->Command), temp->mid); - return temp; + le16_to_cpu(shdr->Command), smb->mid); + return smb; } =20 static int smb2_get_mid_entry(struct cifs_ses *ses, struct TCP_Server_Info *server, - struct smb2_hdr *shdr, struct mid_q_entry **mid) + struct smb2_hdr *shdr, struct smb_message **smb) { spin_lock(&server->srv_lock); if (server->tcpStatus =3D=3D CifsExiting) { @@ -837,18 +837,18 @@ smb2_get_mid_entry(struct cifs_ses *ses, struct TCP_S= erver_Info *server, } spin_unlock(&ses->ses_lock); =20 - *mid =3D smb2_mid_entry_alloc(shdr, server); - if (*mid =3D=3D NULL) + *smb =3D smb2_mid_entry_alloc(shdr, server); + if (*smb =3D=3D NULL) return -ENOMEM; spin_lock(&server->mid_lock); - list_add_tail(&(*mid)->qhead, &server->pending_mid_q); + list_add_tail(&(*smb)->qhead, &server->pending_mid_q); spin_unlock(&server->mid_lock); =20 return 0; } =20 int -smb2_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, +smb2_check_receive(struct smb_message *mid, struct TCP_Server_Info *server, bool log_error) { unsigned int len =3D mid->resp_buf_size; @@ -873,14 +873,14 @@ smb2_check_receive(struct mid_q_entry *mid, struct TC= P_Server_Info *server, return map_smb2_to_linux_error(mid->resp_buf, log_error); } =20 -struct mid_q_entry * +struct smb_message * smb2_setup_request(struct cifs_ses *ses, struct TCP_Server_Info *server, struct smb_rqst *rqst) { int rc; struct smb2_hdr *shdr =3D (struct smb2_hdr *)rqst->rq_iov[0].iov_base; - struct mid_q_entry *mid; + struct smb_message *mid; =20 smb2_seq_num_into_buf(server, shdr); =20 @@ -900,13 +900,13 @@ smb2_setup_request(struct cifs_ses *ses, struct TCP_S= erver_Info *server, return mid; } =20 -struct mid_q_entry * +struct smb_message * smb2_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *= rqst) { int rc; struct smb2_hdr *shdr =3D (struct smb2_hdr *)rqst->rq_iov[0].iov_base; - struct mid_q_entry *mid; + struct smb_message *smb; =20 spin_lock(&server->srv_lock); if (server->tcpStatus =3D=3D CifsNeedNegotiate && @@ -918,8 +918,8 @@ smb2_setup_async_request(struct TCP_Server_Info *server= , struct smb_rqst *rqst) =20 smb2_seq_num_into_buf(server, shdr); =20 - mid =3D smb2_mid_entry_alloc(shdr, server); - if (mid =3D=3D NULL) { + smb =3D smb2_mid_entry_alloc(shdr, server); + if (smb =3D=3D NULL) { revert_current_mid_from_hdr(server, shdr); return ERR_PTR(-ENOMEM); } @@ -927,11 +927,11 @@ smb2_setup_async_request(struct TCP_Server_Info *serv= er, struct smb_rqst *rqst) rc =3D smb2_sign_rqst(rqst, server); if (rc) { revert_current_mid_from_hdr(server, shdr); - release_mid(mid); + release_mid(smb); return ERR_PTR(rc); } =20 - return mid; + return smb; } =20 int diff --git a/fs/smb/client/transport.c b/fs/smb/client/transport.c index 68c73e22c3c9..a105e0ddf81a 100644 --- a/fs/smb/client/transport.c +++ b/fs/smb/client/transport.c @@ -31,42 +31,42 @@ #include "compress.h" =20 void -cifs_wake_up_task(struct mid_q_entry *mid) +cifs_wake_up_task(struct smb_message *smb) { - if (mid->mid_state =3D=3D MID_RESPONSE_RECEIVED) - mid->mid_state =3D MID_RESPONSE_READY; - wake_up_process(mid->callback_data); + if (smb->mid_state =3D=3D MID_RESPONSE_RECEIVED) + smb->mid_state =3D MID_RESPONSE_READY; + wake_up_process(smb->callback_data); } =20 void __release_mid(struct kref *refcount) { - struct mid_q_entry *midEntry =3D - container_of(refcount, struct mid_q_entry, refcount); + struct smb_message *smb =3D + container_of(refcount, struct smb_message, refcount); #ifdef CONFIG_CIFS_STATS2 - __le16 command =3D midEntry->server->vals->lock_cmd; - __u16 smb_cmd =3D le16_to_cpu(midEntry->command); + __le16 command =3D smb->server->vals->lock_cmd; + __u16 smb_cmd =3D le16_to_cpu(smb->command); unsigned long now; unsigned long roundtrip_time; #endif - struct TCP_Server_Info *server =3D midEntry->server; + struct TCP_Server_Info *server =3D smb->server; =20 - if (midEntry->resp_buf && (midEntry->mid_flags & MID_WAIT_CANCELLED) && - (midEntry->mid_state =3D=3D MID_RESPONSE_RECEIVED || - midEntry->mid_state =3D=3D MID_RESPONSE_READY) && + if (smb->resp_buf && (smb->mid_flags & MID_WAIT_CANCELLED) && + (smb->mid_state =3D=3D MID_RESPONSE_RECEIVED || + smb->mid_state =3D=3D MID_RESPONSE_READY) && server->ops->handle_cancelled_mid) - server->ops->handle_cancelled_mid(midEntry, server); + server->ops->handle_cancelled_mid(smb, server); =20 - midEntry->mid_state =3D MID_FREE; + smb->mid_state =3D MID_FREE; atomic_dec(&mid_count); - if (midEntry->large_buf) - cifs_buf_release(midEntry->resp_buf); + if (smb->large_buf) + cifs_buf_release(smb->resp_buf); else - cifs_small_buf_release(midEntry->resp_buf); + cifs_small_buf_release(smb->resp_buf); #ifdef CONFIG_CIFS_STATS2 now =3D jiffies; - if (now < midEntry->when_alloc) + if (now < smb->when_alloc) cifs_server_dbg(VFS, "Invalid mid allocation time\n"); - roundtrip_time =3D now - midEntry->when_alloc; + roundtrip_time =3D now - smb->when_alloc; =20 if (smb_cmd < NUMBER_OF_SMB2_COMMANDS) { if (atomic_read(&server->num_cmds[smb_cmd]) =3D=3D 0) { @@ -92,8 +92,8 @@ void __release_mid(struct kref *refcount) * checks */ if ((slow_rsp_threshold !=3D 0) && - time_after(now, midEntry->when_alloc + (slow_rsp_threshold * HZ)) && - (midEntry->command !=3D command)) { + time_after(now, smb->when_alloc + (slow_rsp_threshold * HZ)) && + (smb->command !=3D command)) { /* * smb2slowcmd[NUMBER_OF_SMB2_COMMANDS] counts by command * NB: le16_to_cpu returns unsigned so can not be negative below @@ -101,34 +101,35 @@ void __release_mid(struct kref *refcount) if (smb_cmd < NUMBER_OF_SMB2_COMMANDS) cifs_stats_inc(&server->smb2slowcmd[smb_cmd]); =20 - trace_smb3_slow_rsp(smb_cmd, midEntry->mid, midEntry->pid, - midEntry->when_sent, midEntry->when_received); + trace_smb3_slow_rsp(smb_cmd, smb->mid, smb->pid, + smb->when_sent, smb->when_received); if (cifsFYI & CIFS_TIMER) { pr_debug("slow rsp: cmd %d mid %llu", - midEntry->command, midEntry->mid); + smb->command, smb->mid); cifs_info("A: 0x%lx S: 0x%lx R: 0x%lx\n", - now - midEntry->when_alloc, - now - midEntry->when_sent, - now - midEntry->when_received); + now - smb->when_alloc, + now - smb->when_sent, + now - smb->when_received); } } #endif - put_task_struct(midEntry->creator); + put_task_struct(smb->creator); =20 - mempool_free(midEntry, cifs_mid_poolp); + mempool_free(smb, &smb_message_pool); } =20 void -delete_mid(struct mid_q_entry *mid) +delete_mid(struct smb_message *smb) { - spin_lock(&mid->server->mid_lock); - if (!(mid->mid_flags & MID_DELETED)) { - list_del_init(&mid->qhead); - mid->mid_flags |=3D MID_DELETED; + spin_lock(&smb->server->mid_lock); + + if (!(smb->mid_flags & MID_DELETED)) { + list_del_init(&smb->qhead); + smb->mid_flags |=3D MID_DELETED; } - spin_unlock(&mid->server->mid_lock); + spin_unlock(&smb->server->mid_lock); =20 - release_mid(mid); + release_mid(smb); } =20 /* @@ -633,13 +634,13 @@ cifs_wait_mtu_credits(struct TCP_Server_Info *server,= size_t size, return 0; } =20 -int wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *= midQ) +int wait_for_response(struct TCP_Server_Info *server, struct smb_message *= smb) { int error; =20 error =3D wait_event_state(server->response_q, - midQ->mid_state !=3D MID_REQUEST_SUBMITTED && - midQ->mid_state !=3D MID_RESPONSE_RECEIVED, + smb->mid_state !=3D MID_REQUEST_SUBMITTED && + smb->mid_state !=3D MID_RESPONSE_RECEIVED, (TASK_KILLABLE|TASK_FREEZABLE_UNSAFE)); if (error < 0) return -ERESTARTSYS; @@ -653,12 +654,12 @@ int wait_for_response(struct TCP_Server_Info *server,= struct mid_q_entry *midQ) */ int cifs_call_async(struct TCP_Server_Info *server, struct smb_rqst *rqst, - mid_receive_t *receive, mid_callback_t *callback, - mid_handle_t *handle, void *cbdata, const int flags, + mid_receive_t receive, mid_callback_t callback, + mid_handle_t handle, void *cbdata, const int flags, const struct cifs_credits *exist_credits) { int rc; - struct mid_q_entry *mid; + struct smb_message *smb; struct cifs_credits credits =3D { .value =3D 0, .instance =3D 0 }; unsigned int instance; int optype; @@ -687,35 +688,35 @@ cifs_call_async(struct TCP_Server_Info *server, struc= t smb_rqst *rqst, return -EAGAIN; } =20 - mid =3D server->ops->setup_async_request(server, rqst); - if (IS_ERR(mid)) { + smb =3D server->ops->setup_async_request(server, rqst); + if (IS_ERR(smb)) { cifs_server_unlock(server); add_credits_and_wake_if(server, &credits, optype); - return PTR_ERR(mid); + return PTR_ERR(smb); } =20 - mid->receive =3D receive; - mid->callback =3D callback; - mid->callback_data =3D cbdata; - mid->handle =3D handle; - mid->mid_state =3D MID_REQUEST_SUBMITTED; + smb->receive =3D receive; + smb->callback =3D callback; + smb->callback_data =3D cbdata; + smb->handle =3D handle; + smb->mid_state =3D MID_REQUEST_SUBMITTED; =20 /* put it on the pending_mid_q */ spin_lock(&server->mid_lock); - list_add_tail(&mid->qhead, &server->pending_mid_q); + list_add_tail(&smb->qhead, &server->pending_mid_q); spin_unlock(&server->mid_lock); =20 /* * Need to store the time in mid before calling I/O. For call_async, * I/O response may come back and free the mid entry on another thread. */ - cifs_save_when_sent(mid); + cifs_save_when_sent(smb); rc =3D smb_send_rqst(server, 1, rqst, flags); =20 if (rc < 0) { - revert_current_mid(server, mid->credits); + revert_current_mid(server, smb->credits); server->sequence_number -=3D 2; - delete_mid(mid); + delete_mid(smb); } =20 cifs_server_unlock(server); @@ -727,15 +728,15 @@ cifs_call_async(struct TCP_Server_Info *server, struc= t smb_rqst *rqst, return rc; } =20 -int cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *= server) +int cifs_sync_mid_result(struct smb_message *smb, struct TCP_Server_Info *= server) { int rc =3D 0; =20 cifs_dbg(FYI, "%s: cmd=3D%d mid=3D%llu state=3D%d\n", - __func__, le16_to_cpu(mid->command), mid->mid, mid->mid_state); + __func__, le16_to_cpu(smb->command), smb->mid, smb->mid_state); =20 spin_lock(&server->mid_lock); - switch (mid->mid_state) { + switch (smb->mid_state) { case MID_RESPONSE_READY: spin_unlock(&server->mid_lock); return rc; @@ -749,53 +750,53 @@ int cifs_sync_mid_result(struct mid_q_entry *mid, str= uct TCP_Server_Info *server rc =3D -EHOSTDOWN; break; case MID_RC: - rc =3D mid->mid_rc; + rc =3D smb->mid_rc; break; default: - if (!(mid->mid_flags & MID_DELETED)) { - list_del_init(&mid->qhead); - mid->mid_flags |=3D MID_DELETED; + if (!(smb->mid_flags & MID_DELETED)) { + list_del_init(&smb->qhead); + smb->mid_flags |=3D MID_DELETED; } spin_unlock(&server->mid_lock); cifs_server_dbg(VFS, "%s: invalid mid state mid=3D%llu state=3D%d\n", - __func__, mid->mid, mid->mid_state); + __func__, smb->mid, smb->mid_state); rc =3D -EIO; goto sync_mid_done; } spin_unlock(&server->mid_lock); =20 sync_mid_done: - release_mid(mid); + release_mid(smb); return rc; } =20 static void -cifs_compound_callback(struct mid_q_entry *mid) +cifs_compound_callback(struct smb_message *smb) { - struct TCP_Server_Info *server =3D mid->server; + struct TCP_Server_Info *server =3D smb->server; struct cifs_credits credits =3D { - .value =3D server->ops->get_credits(mid), + .value =3D server->ops->get_credits(smb), .instance =3D server->reconnect_instance, }; =20 - add_credits(server, &credits, mid->optype); + add_credits(server, &credits, smb->optype); =20 - if (mid->mid_state =3D=3D MID_RESPONSE_RECEIVED) - mid->mid_state =3D MID_RESPONSE_READY; + if (smb->mid_state =3D=3D MID_RESPONSE_RECEIVED) + smb->mid_state =3D MID_RESPONSE_READY; } =20 static void -cifs_compound_last_callback(struct mid_q_entry *mid) +cifs_compound_last_callback(struct smb_message *smb) { - cifs_compound_callback(mid); - cifs_wake_up_task(mid); + cifs_compound_callback(smb); + cifs_wake_up_task(smb); } =20 static void -cifs_cancelled_callback(struct mid_q_entry *mid) +cifs_cancelled_callback(struct smb_message *smb) { - cifs_compound_callback(mid); - release_mid(mid); + cifs_compound_callback(smb); + release_mid(smb); } =20 /* @@ -859,7 +860,7 @@ compound_send_recv(const unsigned int xid, struct cifs_= ses *ses, int *resp_buf_type, struct kvec *resp_iov) { int i, j, optype, rc =3D 0; - struct mid_q_entry *midQ[MAX_COMPOUND]; + struct smb_message *smb[MAX_COMPOUND]; bool cancelled_mid[MAX_COMPOUND] =3D {false}; struct cifs_credits credits[MAX_COMPOUND] =3D { { .value =3D 0, .instance =3D 0 } @@ -925,35 +926,35 @@ compound_send_recv(const unsigned int xid, struct cif= s_ses *ses, } =20 for (i =3D 0; i < num_rqst; i++) { - midQ[i] =3D server->ops->setup_request(ses, server, &rqst[i]); - if (IS_ERR(midQ[i])) { + smb[i] =3D server->ops->setup_request(ses, server, &rqst[i]); + if (IS_ERR(smb[i])) { revert_current_mid(server, i); for (j =3D 0; j < i; j++) - delete_mid(midQ[j]); + delete_mid(smb[j]); cifs_server_unlock(server); =20 /* Update # of requests on wire to server */ for (j =3D 0; j < num_rqst; j++) add_credits(server, &credits[j], optype); - return PTR_ERR(midQ[i]); + return PTR_ERR(smb[i]); } =20 - midQ[i]->mid_state =3D MID_REQUEST_SUBMITTED; - midQ[i]->optype =3D optype; + smb[i]->mid_state =3D MID_REQUEST_SUBMITTED; + smb[i]->optype =3D optype; /* * Invoke callback for every part of the compound chain * to calculate credits properly. Wake up this thread only when * the last element is received. */ if (i < num_rqst - 1) - midQ[i]->callback =3D cifs_compound_callback; + smb[i]->callback =3D cifs_compound_callback; else - midQ[i]->callback =3D cifs_compound_last_callback; + smb[i]->callback =3D cifs_compound_last_callback; } rc =3D smb_send_rqst(server, num_rqst, rqst, flags); =20 for (i =3D 0; i < num_rqst; i++) - cifs_save_when_sent(midQ[i]); + cifs_save_when_sent(smb[i]); =20 if (rc < 0) { revert_current_mid(server, num_rqst); @@ -996,20 +997,20 @@ compound_send_recv(const unsigned int xid, struct cif= s_ses *ses, spin_unlock(&ses->ses_lock); =20 for (i =3D 0; i < num_rqst; i++) { - rc =3D wait_for_response(server, midQ[i]); + rc =3D wait_for_response(server, smb[i]); if (rc !=3D 0) break; } if (rc !=3D 0) { for (; i < num_rqst; i++) { cifs_server_dbg(FYI, "Cancelling wait for mid %llu cmd: %d\n", - midQ[i]->mid, le16_to_cpu(midQ[i]->command)); - send_cancel(server, &rqst[i], midQ[i]); + smb[i]->mid, le16_to_cpu(smb[i]->command)); + send_cancel(server, &rqst[i], smb[i]); spin_lock(&server->mid_lock); - midQ[i]->mid_flags |=3D MID_WAIT_CANCELLED; - if (midQ[i]->mid_state =3D=3D MID_REQUEST_SUBMITTED || - midQ[i]->mid_state =3D=3D MID_RESPONSE_RECEIVED) { - midQ[i]->callback =3D cifs_cancelled_callback; + smb[i]->mid_flags |=3D MID_WAIT_CANCELLED; + if (smb[i]->mid_state =3D=3D MID_REQUEST_SUBMITTED || + smb[i]->mid_state =3D=3D MID_RESPONSE_RECEIVED) { + smb[i]->callback =3D cifs_cancelled_callback; cancelled_mid[i] =3D true; credits[i].value =3D 0; } @@ -1021,36 +1022,36 @@ compound_send_recv(const unsigned int xid, struct c= ifs_ses *ses, if (rc < 0) goto out; =20 - rc =3D cifs_sync_mid_result(midQ[i], server); + rc =3D cifs_sync_mid_result(smb[i], server); if (rc !=3D 0) { /* mark this mid as cancelled to not free it below */ cancelled_mid[i] =3D true; goto out; } =20 - if (!midQ[i]->resp_buf || - midQ[i]->mid_state !=3D MID_RESPONSE_READY) { + if (!smb[i]->resp_buf || + smb[i]->mid_state !=3D MID_RESPONSE_READY) { rc =3D -EIO; cifs_dbg(FYI, "Bad MID state?\n"); goto out; } =20 - buf =3D (char *)midQ[i]->resp_buf; + buf =3D (char *)smb[i]->resp_buf; resp_iov[i].iov_base =3D buf; - resp_iov[i].iov_len =3D midQ[i]->resp_buf_size + + resp_iov[i].iov_len =3D smb[i]->resp_buf_size + HEADER_PREAMBLE_SIZE(server); =20 - if (midQ[i]->large_buf) + if (smb[i]->large_buf) resp_buf_type[i] =3D CIFS_LARGE_BUFFER; else resp_buf_type[i] =3D CIFS_SMALL_BUFFER; =20 - rc =3D server->ops->check_receive(midQ[i], server, + rc =3D server->ops->check_receive(smb[i], server, flags & CIFS_LOG_ERROR); =20 /* mark it so buf will not be freed by delete_mid */ if ((flags & CIFS_NO_RSP_BUF) =3D=3D 0) - midQ[i]->resp_buf =3D NULL; + smb[i]->resp_buf =3D NULL; =20 } =20 @@ -1080,7 +1081,7 @@ compound_send_recv(const unsigned int xid, struct cif= s_ses *ses, */ for (i =3D 0; i < num_rqst; i++) { if (!cancelled_mid[i]) - delete_mid(midQ[i]); + delete_mid(smb[i]); } =20 return rc; @@ -1123,38 +1124,38 @@ cifs_discard_remaining_data(struct TCP_Server_Info = *server) } =20 static int -__cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *m= id, +__cifs_readv_discard(struct TCP_Server_Info *server, struct smb_message *s= mb, bool malformed) { int length; =20 length =3D cifs_discard_remaining_data(server); - dequeue_mid(mid, malformed); - mid->resp_buf =3D server->smallbuf; + dequeue_mid(smb, malformed); + smb->resp_buf =3D server->smallbuf; server->smallbuf =3D NULL; return length; } =20 static int -cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid) +cifs_readv_discard(struct TCP_Server_Info *server, struct smb_message *smb) { - struct cifs_io_subrequest *rdata =3D mid->callback_data; + struct cifs_io_subrequest *rdata =3D smb->callback_data; =20 - return __cifs_readv_discard(server, mid, rdata->result); + return __cifs_readv_discard(server, smb, rdata->result); } =20 int -cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) +cifs_readv_receive(struct TCP_Server_Info *server, struct smb_message *smb) { int length, len; unsigned int data_offset, data_len; - struct cifs_io_subrequest *rdata =3D mid->callback_data; + struct cifs_io_subrequest *rdata =3D smb->callback_data; char *buf =3D server->smallbuf; unsigned int buflen =3D server->pdu_size + HEADER_PREAMBLE_SIZE(server); bool use_rdma_mr =3D false; =20 cifs_dbg(FYI, "%s: mid=3D%llu offset=3D%llu bytes=3D%zu\n", - __func__, mid->mid, rdata->subreq.start, rdata->subreq.len); + __func__, smb->mid, rdata->subreq.start, rdata->subreq.len); =20 /* * read the rest of READ_RSP header (sans Data array), or whatever we @@ -1199,7 +1200,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, st= ruct mid_q_entry *mid) cifs_dbg(FYI, "%s: server returned error %d\n", __func__, rdata->result); /* normal error on read response */ - return __cifs_readv_discard(server, mid, false); + return __cifs_readv_discard(server, smb, false); } =20 /* Is there enough to get to the rest of the READ_RSP header? */ @@ -1208,7 +1209,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, st= ruct mid_q_entry *mid) __func__, server->total_read, server->vals->read_rsp_size); rdata->result =3D -EIO; - return cifs_readv_discard(server, mid); + return cifs_readv_discard(server, smb); } =20 data_offset =3D server->ops->read_data_offset(buf) + @@ -1227,7 +1228,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, st= ruct mid_q_entry *mid) cifs_dbg(FYI, "%s: data offset (%u) beyond end of smallbuf\n", __func__, data_offset); rdata->result =3D -EIO; - return cifs_readv_discard(server, mid); + return cifs_readv_discard(server, smb); } =20 cifs_dbg(FYI, "%s: total_read=3D%u data_offset=3D%u\n", @@ -1251,7 +1252,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, st= ruct mid_q_entry *mid) if (!use_rdma_mr && (data_offset + data_len > buflen)) { /* data_len is corrupt -- discard frame */ rdata->result =3D -EIO; - return cifs_readv_discard(server, mid); + return cifs_readv_discard(server, smb); } =20 #ifdef CONFIG_CIFS_SMB_DIRECT @@ -1270,10 +1271,10 @@ cifs_readv_receive(struct TCP_Server_Info *server, = struct mid_q_entry *mid) =20 /* discard anything left over */ if (server->total_read < buflen) - return cifs_readv_discard(server, mid); + return cifs_readv_discard(server, smb); =20 - dequeue_mid(mid, false); - mid->resp_buf =3D server->smallbuf; + dequeue_mid(smb, false); + smb->resp_buf =3D server->smallbuf; server->smallbuf =3D NULL; return length; } From nobody Thu Dec 18 03:20:29 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 89A2F2BE7BE for ; Wed, 6 Aug 2025 20:38:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512684; cv=none; b=hh+hxwHb943HhmyEhAaTIs7s+8QzlFQNagrmeV1xtY15UO72Ulj6RceuxoXkJcoYaaeVOHTQNaLF6Qf0OJ0Wr+vcojF9l2sxufDP6wj7IS45Wn6vDvlhJP+0xJldQJVtwiDNmQusmFTxowNtoc58AmZBS50pNsPBYWS0EBdtiP4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512684; c=relaxed/simple; bh=HlJtVDS0CF+uKYV5ZU3bq02nbBAOUiTNb80hlbh7iCM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=FZ3j8q+VwbAlrKpxGWDZbVRWvuX4WDMHv62b03Qp/q4jIbgKAapcdEEl5e6sQhGsy2W+0ScXRmDfvEH78KUkgP/RariWxIIqTObrfOuN/6JKrIVx6GxckqYsks+UKnkduMY2Q+SmmlwM6urZf1gWDWkuCLP5s/iZPnCgNEjKzok= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=FSw2Ahuo; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="FSw2Ahuo" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1754512679; h=from:from:reply-to:subject:subject: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=GvmKYWxdl2Sd25IFOAPHPXp2nwfzUjCOfR+tUgjELuI=; b=FSw2AhuoNUFZnHIDJttuiAeXOLRBFAA+WO5lCu+w6esKpg8bLsJYhEqM0Kuyy/q3UuJL7P +yRwFfMTwdglncjsPcZHohpAeNyEP3dq+8KEFjfVjNnFrWKxlpOpkRZrC6vSiCjvgMq0gk mqYs+XAEJGNLKX9xwX/tj14+ZEUsF8c= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-682-P9A-xUo3NDaKZHvKCtkLJw-1; Wed, 06 Aug 2025 16:37:55 -0400 X-MC-Unique: P9A-xUo3NDaKZHvKCtkLJw-1 X-Mimecast-MFC-AGG-ID: P9A-xUo3NDaKZHvKCtkLJw_1754512674 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 48CD719560B4; Wed, 6 Aug 2025 20:37:54 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.17]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id ABABF180035C; Wed, 6 Aug 2025 20:37:50 +0000 (UTC) From: David Howells To: Steve French Cc: David Howells , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Wang Zhaolong , Stefan Metzmacher , Mina Almasry , linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org, netfs@lists.linux.dev, linux-fsdevel@vger.kernel.org Subject: [RFC PATCH 08/31] cifs: Keep the CPU-endian command ID around Date: Wed, 6 Aug 2025 21:36:29 +0100 Message-ID: <20250806203705.2560493-9-dhowells@redhat.com> In-Reply-To: <20250806203705.2560493-1-dhowells@redhat.com> References: <20250806203705.2560493-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Content-Type: text/plain; charset="utf-8" Because the command IDs are small integers in a sequence, the C compiler can generate better code if they're cpu-endian. Signed-off-by: David Howells cc: Steve French cc: Paulo Alcantara cc: Shyam Prasad N cc: Tom Talpey cc: linux-cifs@vger.kernel.org cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/smb/client/cifs_debug.c | 2 +- fs/smb/client/cifsglob.h | 4 +- fs/smb/client/cifstransport.c | 4 +- fs/smb/client/compress.c | 4 +- fs/smb/client/smb1ops.c | 3 +- fs/smb/client/smb2misc.c | 30 +++++----- fs/smb/client/smb2ops.c | 19 ++++--- fs/smb/client/smb2pdu.c | 103 ++++++++++++++++++---------------- fs/smb/client/smb2transport.c | 20 +++---- fs/smb/client/transport.c | 12 ++-- fs/smb/common/smb2pdu.h | 68 +++++++++------------- fs/smb/server/oplock.c | 4 +- fs/smb/server/smb2misc.c | 40 ++++++------- fs/smb/server/smb2ops.c | 8 +-- fs/smb/server/smb2pdu.c | 14 ++--- 15 files changed, 162 insertions(+), 173 deletions(-) diff --git a/fs/smb/client/cifs_debug.c b/fs/smb/client/cifs_debug.c index 163e8954b940..cba30f339d6b 100644 --- a/fs/smb/client/cifs_debug.c +++ b/fs/smb/client/cifs_debug.c @@ -627,7 +627,7 @@ static int cifs_debug_data_proc_show(struct seq_file *m= , void *v) list_for_each_entry(smb, &chan_server->pending_mid_q, qhead) { seq_printf(m, "\n\t\tState: %d com: %d pid: %d cbdata: %p mid %llu", smb->mid_state, - le16_to_cpu(smb->command), + smb->command_id, smb->pid, smb->callback_data, smb->mid); diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index 5d523099e298..60350213a02b 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h @@ -647,7 +647,7 @@ struct smb_version_values { size_t header_size; size_t max_header_size; size_t read_rsp_size; - __le16 lock_cmd; + enum smb2_command lock_cmd; unsigned int cap_unix; unsigned int cap_nt_find; unsigned int cap_large_files; @@ -1728,8 +1728,8 @@ struct smb_message { int mid_state; /* wish this were enum but can not pass to wait_event */ int mid_rc; /* rc for MID_RC */ unsigned int mid_flags; - __le16 command; /* smb command code */ unsigned int optype; /* operation type */ + enum smb2_command command_id; /* smb command code */ bool large_buf:1; /* if valid response, is pointer to large buf */ bool multiRsp:1; /* multiple trans2 responses for one request */ bool multiEnd:1; /* both received */ diff --git a/fs/smb/client/cifstransport.c b/fs/smb/client/cifstransport.c index 20709ae52d26..a3400a757968 100644 --- a/fs/smb/client/cifstransport.c +++ b/fs/smb/client/cifstransport.c @@ -48,8 +48,8 @@ alloc_mid(const struct smb_hdr *smb_buffer, struct TCP_Se= rver_Info *server) kref_init(&smb->refcount); smb->mid =3D get_mid(smb_buffer); smb->pid =3D current->pid; - smb->command =3D cpu_to_le16(smb_buffer->Command); - cifs_dbg(FYI, "For smb_command %d\n", smb_buffer->Command); + smb->command_id =3D le16_to_cpu(smb_buffer->Command); + cifs_dbg(FYI, "For smb_command %d\n", smb->command_id); /* easier to use jiffies */ /* when mid allocated can be before when sent */ smb->when_alloc =3D jiffies; diff --git a/fs/smb/client/compress.c b/fs/smb/client/compress.c index 766b4de13da7..f52710425151 100644 --- a/fs/smb/client/compress.c +++ b/fs/smb/client/compress.c @@ -303,7 +303,7 @@ bool should_compress(const struct cifs_tcon *tcon, cons= t struct smb_rqst *rq) if (!(tcon->share_flags & SMB2_SHAREFLAG_COMPRESS_DATA)) return false; =20 - if (shdr->Command =3D=3D SMB2_WRITE) { + if (le16_to_cpu(shdr->Command) =3D=3D SMB2_WRITE_HE) { const struct smb2_write_req *wreq =3D rq->rq_iov->iov_base; =20 if (le32_to_cpu(wreq->Length) < SMB_COMPRESS_MIN_LEN) @@ -312,7 +312,7 @@ bool should_compress(const struct cifs_tcon *tcon, cons= t struct smb_rqst *rq) return is_compressible(&rq->rq_iter); } =20 - return (shdr->Command =3D=3D SMB2_READ); + return le16_to_cpu(shdr->Command) =3D=3D SMB2_READ_HE; } =20 int smb_compress(struct TCP_Server_Info *server, struct smb_rqst *rq, comp= ress_send_fn send_fn) diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c index ba301c94d4ff..dc2daba936e2 100644 --- a/fs/smb/client/smb1ops.c +++ b/fs/smb/client/smb1ops.c @@ -93,12 +93,13 @@ cifs_find_mid(struct TCP_Server_Info *server, char *buf= fer) { struct smb_hdr *buf =3D (struct smb_hdr *)buffer; struct smb_message *smb; + enum smb2_command command =3D le16_to_cpu(buf->Command); =20 spin_lock(&server->mid_lock); list_for_each_entry(smb, &server->pending_mid_q, qhead) { if (compare_mid(smb->mid, buf) && smb->mid_state =3D=3D MID_REQUEST_SUBMITTED && - le16_to_cpu(smb->command) =3D=3D buf->Command) { + smb->command_id =3D=3D command) { kref_get(&smb->refcount); spin_unlock(&server->mid_lock); return smb; diff --git a/fs/smb/client/smb2misc.c b/fs/smb/client/smb2misc.c index f1b0546c7858..f6280e3d4e55 100644 --- a/fs/smb/client/smb2misc.c +++ b/fs/smb/client/smb2misc.c @@ -33,7 +33,7 @@ check_smb2_hdr(struct smb2_hdr *shdr, __u64 mid) return 0; else { /* only one valid case where server sends us request */ - if (shdr->Command =3D=3D SMB2_OPLOCK_BREAK) + if (le16_to_cpu(shdr->Command) =3D=3D SMB2_OPLOCK_BREAK_HE) return 0; else cifs_dbg(VFS, "Received Request not response\n"); @@ -138,9 +138,9 @@ smb2_check_message(char *buf, unsigned int len, struct = TCP_Server_Info *server) struct TCP_Server_Info *pserver; struct smb2_hdr *shdr =3D (struct smb2_hdr *)buf; struct smb2_pdu *pdu =3D (struct smb2_pdu *)shdr; + enum smb2_command command; int hdr_size =3D sizeof(struct smb2_hdr); int pdu_size =3D sizeof(struct smb2_pdu); - int command; __u32 calc_len; /* calculated length */ __u64 mid; =20 @@ -330,49 +330,49 @@ smb2_get_data_area_len(int *off, int *len, struct smb= 2_hdr *shdr) * of the data buffer offset and data buffer length for the particular * command. */ - switch (shdr->Command) { - case SMB2_NEGOTIATE: + switch (le16_to_cpu(shdr->Command)) { + case SMB2_NEGOTIATE_HE: *off =3D le16_to_cpu( ((struct smb2_negotiate_rsp *)shdr)->SecurityBufferOffset); *len =3D le16_to_cpu( ((struct smb2_negotiate_rsp *)shdr)->SecurityBufferLength); break; - case SMB2_SESSION_SETUP: + case SMB2_SESSION_SETUP_HE: *off =3D le16_to_cpu( ((struct smb2_sess_setup_rsp *)shdr)->SecurityBufferOffset); *len =3D le16_to_cpu( ((struct smb2_sess_setup_rsp *)shdr)->SecurityBufferLength); break; - case SMB2_CREATE: + case SMB2_CREATE_HE: *off =3D le32_to_cpu( ((struct smb2_create_rsp *)shdr)->CreateContextsOffset); *len =3D le32_to_cpu( ((struct smb2_create_rsp *)shdr)->CreateContextsLength); break; - case SMB2_QUERY_INFO: + case SMB2_QUERY_INFO_HE: *off =3D le16_to_cpu( ((struct smb2_query_info_rsp *)shdr)->OutputBufferOffset); *len =3D le32_to_cpu( ((struct smb2_query_info_rsp *)shdr)->OutputBufferLength); break; - case SMB2_READ: + case SMB2_READ_HE: /* TODO: is this a bug ? */ *off =3D ((struct smb2_read_rsp *)shdr)->DataOffset; *len =3D le32_to_cpu(((struct smb2_read_rsp *)shdr)->DataLength); break; - case SMB2_QUERY_DIRECTORY: + case SMB2_QUERY_DIRECTORY_HE: *off =3D le16_to_cpu( ((struct smb2_query_directory_rsp *)shdr)->OutputBufferOffset); *len =3D le32_to_cpu( ((struct smb2_query_directory_rsp *)shdr)->OutputBufferLength); break; - case SMB2_IOCTL: + case SMB2_IOCTL_HE: *off =3D le32_to_cpu( ((struct smb2_ioctl_rsp *)shdr)->OutputOffset); *len =3D le32_to_cpu( ((struct smb2_ioctl_rsp *)shdr)->OutputCount); break; - case SMB2_CHANGE_NOTIFY: + case SMB2_CHANGE_NOTIFY_HE: *off =3D le16_to_cpu( ((struct smb2_change_notify_rsp *)shdr)->OutputBufferOffset); *len =3D le32_to_cpu( @@ -680,7 +680,7 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Ser= ver_Info *server) =20 cifs_dbg(FYI, "Checking for oplock break\n"); =20 - if (rsp->hdr.Command !=3D SMB2_OPLOCK_BREAK) + if (rsp->hdr.Command !=3D cpu_to_le32(SMB2_OPLOCK_BREAK_HE)) return false; =20 if (rsp->StructureSize !=3D @@ -846,7 +846,7 @@ smb2_handle_cancelled_mid(struct smb_message *smb, stru= ct TCP_Server_Info *serve struct cifs_tcon *tcon; int rc; =20 - if ((smb->optype & CIFS_CP_CREATE_CLOSE_OP) || hdr->Command !=3D SMB2_CRE= ATE || + if ((smb->optype & CIFS_CP_CREATE_CLOSE_OP) || smb->command_id !=3D SMB2_= CREATE_HE || hdr->Status !=3D STATUS_SUCCESS) return 0; =20 @@ -887,7 +887,7 @@ smb311_update_preauth_hash(struct cifs_ses *ses, struct= TCP_Server_Info *server, =20 hdr =3D (struct smb2_hdr *)iov[0].iov_base; /* neg prot are always taken */ - if (hdr->Command =3D=3D SMB2_NEGOTIATE) + if (le16_to_cpu(hdr->Command) =3D=3D SMB2_NEGOTIATE_HE) goto ok; =20 /* @@ -898,7 +898,7 @@ smb311_update_preauth_hash(struct cifs_ses *ses, struct= TCP_Server_Info *server, if (server->dialect !=3D SMB311_PROT_ID) return 0; =20 - if (hdr->Command !=3D SMB2_SESSION_SETUP) + if (le16_to_cpu(hdr->Command) !=3D SMB2_SESSION_SETUP_HE) return 0; =20 /* skip last sess setup response */ diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c index a7ba4a77721e..0116bf348a76 100644 --- a/fs/smb/client/smb2ops.c +++ b/fs/smb/client/smb2ops.c @@ -394,6 +394,7 @@ __smb2_find_mid(struct TCP_Server_Info *server, char *b= uf, bool dequeue) { struct smb_message *smb; struct smb2_hdr *shdr =3D (struct smb2_hdr *)buf; + enum smb2_command command =3D le16_to_cpu(shdr->Command); __u64 wire_mid =3D le64_to_cpu(shdr->MessageId); =20 if (shdr->ProtocolId =3D=3D SMB2_TRANSFORM_PROTO_NUM) { @@ -405,7 +406,7 @@ __smb2_find_mid(struct TCP_Server_Info *server, char *b= uf, bool dequeue) list_for_each_entry(smb, &server->pending_mid_q, qhead) { if ((smb->mid =3D=3D wire_mid) && (smb->mid_state =3D=3D MID_REQUEST_SUBMITTED) && - (smb->command =3D=3D shdr->Command)) { + (smb->command_id =3D=3D command)) { kref_get(&smb->refcount); if (dequeue) { list_del_init(&smb->qhead); @@ -4625,7 +4626,7 @@ handle_read_data(struct TCP_Server_Info *server, stru= ct smb_message *smb, int length; bool use_rdma_mr =3D false; =20 - if (shdr->Command !=3D SMB2_READ) { + if (le16_to_cpu(shdr->Command) !=3D SMB2_READ_HE) { cifs_server_dbg(VFS, "only big read responses are supported\n"); return -EOPNOTSUPP; } @@ -5714,7 +5715,7 @@ struct smb_version_values smb20_values =3D { .header_preamble_size =3D 0, .max_header_size =3D MAX_SMB2_HDR_SIZE, .read_rsp_size =3D sizeof(struct smb2_read_rsp), - .lock_cmd =3D SMB2_LOCK, + .lock_cmd =3D SMB2_LOCK_HE, .cap_unix =3D 0, .cap_nt_find =3D SMB2_NT_FIND, .cap_large_files =3D SMB2_LARGE_FILES, @@ -5736,7 +5737,7 @@ struct smb_version_values smb21_values =3D { .header_preamble_size =3D 0, .max_header_size =3D MAX_SMB2_HDR_SIZE, .read_rsp_size =3D sizeof(struct smb2_read_rsp), - .lock_cmd =3D SMB2_LOCK, + .lock_cmd =3D SMB2_LOCK_HE, .cap_unix =3D 0, .cap_nt_find =3D SMB2_NT_FIND, .cap_large_files =3D SMB2_LARGE_FILES, @@ -5757,7 +5758,7 @@ struct smb_version_values smb3any_values =3D { .header_preamble_size =3D 0, .max_header_size =3D MAX_SMB2_HDR_SIZE, .read_rsp_size =3D sizeof(struct smb2_read_rsp), - .lock_cmd =3D SMB2_LOCK, + .lock_cmd =3D SMB2_LOCK_HE, .cap_unix =3D 0, .cap_nt_find =3D SMB2_NT_FIND, .cap_large_files =3D SMB2_LARGE_FILES, @@ -5778,7 +5779,7 @@ struct smb_version_values smbdefault_values =3D { .header_preamble_size =3D 0, .max_header_size =3D MAX_SMB2_HDR_SIZE, .read_rsp_size =3D sizeof(struct smb2_read_rsp), - .lock_cmd =3D SMB2_LOCK, + .lock_cmd =3D SMB2_LOCK_HE, .cap_unix =3D 0, .cap_nt_find =3D SMB2_NT_FIND, .cap_large_files =3D SMB2_LARGE_FILES, @@ -5799,7 +5800,7 @@ struct smb_version_values smb30_values =3D { .header_preamble_size =3D 0, .max_header_size =3D MAX_SMB2_HDR_SIZE, .read_rsp_size =3D sizeof(struct smb2_read_rsp), - .lock_cmd =3D SMB2_LOCK, + .lock_cmd =3D SMB2_LOCK_HE, .cap_unix =3D 0, .cap_nt_find =3D SMB2_NT_FIND, .cap_large_files =3D SMB2_LARGE_FILES, @@ -5820,7 +5821,7 @@ struct smb_version_values smb302_values =3D { .header_preamble_size =3D 0, .max_header_size =3D MAX_SMB2_HDR_SIZE, .read_rsp_size =3D sizeof(struct smb2_read_rsp), - .lock_cmd =3D SMB2_LOCK, + .lock_cmd =3D SMB2_LOCK_HE, .cap_unix =3D 0, .cap_nt_find =3D SMB2_NT_FIND, .cap_large_files =3D SMB2_LARGE_FILES, @@ -5841,7 +5842,7 @@ struct smb_version_values smb311_values =3D { .header_preamble_size =3D 0, .max_header_size =3D MAX_SMB2_HDR_SIZE, .read_rsp_size =3D sizeof(struct smb2_read_rsp), - .lock_cmd =3D SMB2_LOCK, + .lock_cmd =3D SMB2_LOCK_HE, .cap_unix =3D 0, .cap_nt_find =3D SMB2_NT_FIND, .cap_large_files =3D SMB2_LARGE_FILES, diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c index 645d67d04a8d..97a267ce2a62 100644 --- a/fs/smb/client/smb2pdu.c +++ b/fs/smb/client/smb2pdu.c @@ -92,7 +92,7 @@ int smb3_encryption_required(const struct cifs_tcon *tcon) } =20 static void -smb2_hdr_assemble(struct smb2_hdr *shdr, __le16 smb2_cmd, +smb2_hdr_assemble(struct smb2_hdr *shdr, enum smb2_command smb2_cmd, const struct cifs_tcon *tcon, struct TCP_Server_Info *server) { @@ -100,7 +100,7 @@ smb2_hdr_assemble(struct smb2_hdr *shdr, __le16 smb2_cm= d, =20 shdr->ProtocolId =3D SMB2_PROTO_NUMBER; shdr->StructureSize =3D cpu_to_le16(64); - shdr->Command =3D smb2_cmd; + shdr->Command =3D cpu_to_le16(smb2_cmd); =20 if (server) { /* After reconnect SMB3 must set ChannelSequence on subsequent reqs */ @@ -215,7 +215,7 @@ cifs_chan_skip_or_disable(struct cifs_ses *ses, } =20 static int -smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon, +smb2_reconnect(enum smb2_command smb2_command, struct cifs_tcon *tcon, struct TCP_Server_Info *server, bool from_reconnect) { struct cifs_ses *ses; @@ -230,7 +230,7 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *t= con, if (tcon =3D=3D NULL) return 0; =20 - if (smb2_command =3D=3D SMB2_TREE_CONNECT) + if (smb2_command =3D=3D SMB2_TREE_CONNECT_HE) return 0; =20 spin_lock(&tcon->tc_lock); @@ -238,7 +238,7 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *t= con, /* * only tree disconnect allowed when disconnecting ... */ - if (smb2_command !=3D SMB2_TREE_DISCONNECT) { + if (smb2_command !=3D SMB2_TREE_DISCONNECT_HE) { spin_unlock(&tcon->tc_lock); cifs_dbg(FYI, "can not send cmd %d while umounting\n", smb2_command); @@ -269,12 +269,14 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon = *tcon, /* * BB Should we keep oplock break and add flush to exceptions? */ - case SMB2_TREE_DISCONNECT: - case SMB2_CANCEL: - case SMB2_CLOSE: - case SMB2_OPLOCK_BREAK: + case SMB2_TREE_DISCONNECT_HE: + case SMB2_CANCEL_HE: + case SMB2_CLOSE_HE: + case SMB2_OPLOCK_BREAK_HE: spin_unlock(&server->srv_lock); return -EAGAIN; + default: + break; } } =20 @@ -462,7 +464,7 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *t= con, ses->flags &=3D ~CIFS_SES_FLAG_SCALE_CHANNELS; spin_unlock(&ses->ses_lock); =20 - if (smb2_command !=3D SMB2_INTERNAL_CMD) + if (smb2_command !=3D SMB2_INTERNAL_CMD_HE) mod_delayed_work(cifsiod_wq, &server->reconnect, 0); =20 atomic_inc(&tconInfoReconnectCount); @@ -476,29 +478,32 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon = *tcon, * case it and skip above? */ switch (smb2_command) { - case SMB2_FLUSH: - case SMB2_READ: - case SMB2_WRITE: - case SMB2_LOCK: - case SMB2_QUERY_DIRECTORY: - case SMB2_CHANGE_NOTIFY: - case SMB2_QUERY_INFO: - case SMB2_SET_INFO: - case SMB2_IOCTL: + case SMB2_FLUSH_HE: + case SMB2_READ_HE: + case SMB2_WRITE_HE: + case SMB2_LOCK_HE: + case SMB2_QUERY_DIRECTORY_HE: + case SMB2_CHANGE_NOTIFY_HE: + case SMB2_QUERY_INFO_HE: + case SMB2_SET_INFO_HE: + case SMB2_IOCTL_HE: rc =3D -EAGAIN; + break; + default: + break; } return rc; } =20 static void -fill_small_buf(__le16 smb2_command, struct cifs_tcon *tcon, +fill_small_buf(enum smb2_command smb2_command, struct cifs_tcon *tcon, struct TCP_Server_Info *server, void *buf, unsigned int *total_len) { struct smb2_pdu *spdu =3D buf; /* lookup word count ie StructureSize from table */ - __u16 parmsize =3D smb2_req_struct_sizes[le16_to_cpu(smb2_command)]; + __u16 parmsize =3D smb2_req_struct_sizes[smb2_command]; =20 /* * smaller than SMALL_BUFFER_SIZE but bigger than fixed area of @@ -517,14 +522,14 @@ fill_small_buf(__le16 smb2_command, struct cifs_tcon = *tcon, * SMB information in the SMB header. If the return code is zero, this * function must have filled in request_buf pointer. */ -static int __smb2_plain_req_init(__le16 smb2_command, struct cifs_tcon *tc= on, +static int __smb2_plain_req_init(enum smb2_command smb2_command, struct ci= fs_tcon *tcon, struct TCP_Server_Info *server, void **request_buf, unsigned int *total_len) { /* BB eventually switch this to SMB2 specific small buf size */ switch (smb2_command) { - case SMB2_SET_INFO: - case SMB2_QUERY_INFO: + case SMB2_SET_INFO_HE: + case SMB2_QUERY_INFO_HE: *request_buf =3D cifs_buf_get(); break; default: @@ -576,10 +581,10 @@ static int smb2_ioctl_req_init(u32 opcode, struct cif= s_tcon *tcon, if (opcode =3D=3D FSCTL_VALIDATE_NEGOTIATE_INFO || (opcode =3D=3D FSCTL_QUERY_NETWORK_INTERFACE_INFO && (tcon->ses->flags & CIFS_SES_FLAGS_PENDING_QUERY_INTERFACES))) - return __smb2_plain_req_init(SMB2_IOCTL, tcon, server, + return __smb2_plain_req_init(SMB2_IOCTL_HE, tcon, server, request_buf, total_len); =20 - return smb2_plain_req_init(SMB2_IOCTL, tcon, server, + return smb2_plain_req_init(SMB2_IOCTL_HE, tcon, server, request_buf, total_len); } =20 @@ -1064,7 +1069,7 @@ SMB2_negotiate(const unsigned int xid, return -EIO; } =20 - rc =3D smb2_plain_req_init(SMB2_NEGOTIATE, NULL, server, + rc =3D smb2_plain_req_init(SMB2_NEGOTIATE_HE, NULL, server, (void **) &req, &total_len); if (rc) return rc; @@ -1464,7 +1469,7 @@ SMB2_sess_alloc_buffer(struct SMB2_sess_data *sess_da= ta) unsigned int total_len; bool is_binding =3D false; =20 - rc =3D smb2_plain_req_init(SMB2_SESSION_SETUP, NULL, server, + rc =3D smb2_plain_req_init(SMB2_SESSION_SETUP_HE, NULL, server, (void **) &req, &total_len); if (rc) @@ -1979,7 +1984,7 @@ SMB2_logoff(const unsigned int xid, struct cifs_ses *= ses) } spin_unlock(&ses->chan_lock); =20 - rc =3D smb2_plain_req_init(SMB2_LOGOFF, NULL, ses->server, + rc =3D smb2_plain_req_init(SMB2_LOGOFF_HE, NULL, ses->server, (void **) &req, &total_len); if (rc) return rc; @@ -2064,7 +2069,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *se= s, const char *tree, /* SMB2 TREE_CONNECT request must be called with TreeId =3D=3D 0 */ tcon->tid =3D 0; atomic_set(&tcon->num_remote_opens, 0); - rc =3D smb2_plain_req_init(SMB2_TREE_CONNECT, tcon, server, + rc =3D smb2_plain_req_init(SMB2_TREE_CONNECT_HE, tcon, server, (void **) &req, &total_len); if (rc) { kfree(unc_path); @@ -2199,7 +2204,7 @@ SMB2_tdis(const unsigned int xid, struct cifs_tcon *t= con) =20 invalidate_all_cached_dirs(tcon); =20 - rc =3D smb2_plain_req_init(SMB2_TREE_DISCONNECT, tcon, server, + rc =3D smb2_plain_req_init(SMB2_TREE_DISCONNECT_HE, tcon, server, (void **) &req, &total_len); if (rc) @@ -2862,7 +2867,7 @@ int smb311_posix_mkdir(const unsigned int xid, struct= inode *inode, } =20 /* resource #2: request */ - rc =3D smb2_plain_req_init(SMB2_CREATE, tcon, server, + rc =3D smb2_plain_req_init(SMB2_CREATE_HE, tcon, server, (void **) &req, &total_len); if (rc) goto err_free_path; @@ -3016,7 +3021,7 @@ SMB2_open_init(struct cifs_tcon *tcon, struct TCP_Ser= ver_Info *server, __le16 *copy_path; int rc; =20 - rc =3D smb2_plain_req_init(SMB2_CREATE, tcon, server, + rc =3D smb2_plain_req_init(SMB2_CREATE_HE, tcon, server, (void **) &req, &total_len); if (rc) return rc; @@ -3571,7 +3576,7 @@ SMB2_close_init(struct cifs_tcon *tcon, struct TCP_Se= rver_Info *server, unsigned int total_len; int rc; =20 - rc =3D smb2_plain_req_init(SMB2_CLOSE, tcon, server, + rc =3D smb2_plain_req_init(SMB2_CLOSE_HE, tcon, server, (void **) &req, &total_len); if (rc) return rc; @@ -3765,7 +3770,7 @@ SMB2_query_info_init(struct cifs_tcon *tcon, struct T= CP_Server_Info *server, len > CIFSMaxBufSize)) return -EINVAL; =20 - rc =3D smb2_plain_req_init(SMB2_QUERY_INFO, tcon, server, + rc =3D smb2_plain_req_init(SMB2_QUERY_INFO_HE, tcon, server, (void **) &req, &total_len); if (rc) return rc; @@ -3966,7 +3971,7 @@ SMB2_notify_init(const unsigned int xid, struct smb_r= qst *rqst, unsigned int total_len; int rc; =20 - rc =3D smb2_plain_req_init(SMB2_CHANGE_NOTIFY, tcon, server, + rc =3D smb2_plain_req_init(SMB2_CHANGE_NOTIFY_HE, tcon, server, (void **) &req, &total_len); if (rc) return rc; @@ -4203,7 +4208,7 @@ void smb2_reconnect_server(struct work_struct *work) spin_unlock(&cifs_tcp_ses_lock); =20 list_for_each_entry_safe(tcon, tcon2, &tmp_list, rlist) { - rc =3D smb2_reconnect(SMB2_INTERNAL_CMD, tcon, server, true); + rc =3D smb2_reconnect(SMB2_INTERNAL_CMD_HE, tcon, server, true); if (!rc) { cifs_renegotiate_iosize(server, tcon); cifs_reopen_persistent_handles(tcon); @@ -4235,7 +4240,7 @@ void smb2_reconnect_server(struct work_struct *work) /* now reconnect sessions for necessary channels */ list_for_each_entry_safe(ses, ses2, &tmp_ses_list, rlist) { tcon->ses =3D ses; - rc =3D smb2_reconnect(SMB2_INTERNAL_CMD, tcon, server, true); + rc =3D smb2_reconnect(SMB2_INTERNAL_CMD_HE, tcon, server, true); if (rc) resched =3D true; list_del_init(&ses->rlist); @@ -4275,7 +4280,7 @@ SMB2_echo(struct TCP_Server_Info *server) } spin_unlock(&server->srv_lock); =20 - rc =3D smb2_plain_req_init(SMB2_ECHO, NULL, server, + rc =3D smb2_plain_req_init(SMB2_ECHO_HE, NULL, server, (void **)&req, &total_len); if (rc) return rc; @@ -4311,7 +4316,7 @@ SMB2_flush_init(const unsigned int xid, struct smb_rq= st *rqst, unsigned int total_len; int rc; =20 - rc =3D smb2_plain_req_init(SMB2_FLUSH, tcon, server, + rc =3D smb2_plain_req_init(SMB2_FLUSH_HE, tcon, server, (void **) &req, &total_len); if (rc) return rc; @@ -4432,7 +4437,7 @@ smb2_new_read_req(void **buf, unsigned int *total_len, struct smb2_hdr *shdr; struct TCP_Server_Info *server =3D io_parms->server; =20 - rc =3D smb2_plain_req_init(SMB2_READ, io_parms->tcon, server, + rc =3D smb2_plain_req_init(SMB2_READ_HE, io_parms->tcon, server, (void **) &req, total_len); if (rc) return rc; @@ -4964,7 +4969,7 @@ smb2_async_writev(struct cifs_io_subrequest *wdata) }; io_parms =3D &_io_parms; =20 - rc =3D smb2_plain_req_init(SMB2_WRITE, tcon, server, + rc =3D smb2_plain_req_init(SMB2_WRITE_HE, tcon, server, (void **) &req, &total_len); if (rc) goto out; @@ -5136,7 +5141,7 @@ SMB2_write(const unsigned int xid, struct cifs_io_par= ms *io_parms, if (n_vec < 1) return rc; =20 - rc =3D smb2_plain_req_init(SMB2_WRITE, io_parms->tcon, server, + rc =3D smb2_plain_req_init(SMB2_WRITE_HE, io_parms->tcon, server, (void **) &req, &total_len); if (rc) return rc; @@ -5369,7 +5374,7 @@ int SMB2_query_directory_init(const unsigned int xid, struct kvec *iov =3D rqst->rq_iov; int len, rc; =20 - rc =3D smb2_plain_req_init(SMB2_QUERY_DIRECTORY, tcon, server, + rc =3D smb2_plain_req_init(SMB2_QUERY_DIRECTORY_HE, tcon, server, (void **) &req, &total_len); if (rc) return rc; @@ -5603,7 +5608,7 @@ SMB2_set_info_init(struct cifs_tcon *tcon, struct TCP= _Server_Info *server, unsigned int i, total_len; int rc; =20 - rc =3D smb2_plain_req_init(SMB2_SET_INFO, tcon, server, + rc =3D smb2_plain_req_init(SMB2_SET_INFO_HE, tcon, server, (void **) &req, &total_len); if (rc) return rc; @@ -5777,7 +5782,7 @@ SMB2_oplock_break(const unsigned int xid, struct cifs= _tcon *tcon, server =3D cifs_pick_channel(ses); =20 cifs_dbg(FYI, "SMB2_oplock_break\n"); - rc =3D smb2_plain_req_init(SMB2_OPLOCK_BREAK, tcon, server, + rc =3D smb2_plain_req_init(SMB2_OPLOCK_BREAK_HE, tcon, server, (void **) &req, &total_len); if (rc) return rc; @@ -5863,7 +5868,7 @@ build_qfs_info_req(struct kvec *iov, struct cifs_tcon= *tcon, if ((tcon->ses =3D=3D NULL) || server =3D=3D NULL) return -EIO; =20 - rc =3D smb2_plain_req_init(SMB2_QUERY_INFO, tcon, server, + rc =3D smb2_plain_req_init(SMB2_QUERY_INFO_HE, tcon, server, (void **) &req, &total_len); if (rc) return rc; @@ -6076,7 +6081,7 @@ smb2_lockv(const unsigned int xid, struct cifs_tcon *= tcon, =20 cifs_dbg(FYI, "smb2_lockv num lock %d\n", num_lock); =20 - rc =3D smb2_plain_req_init(SMB2_LOCK, tcon, server, + rc =3D smb2_plain_req_init(SMB2_LOCK_HE, tcon, server, (void **) &req, &total_len); if (rc) return rc; @@ -6159,7 +6164,7 @@ SMB2_lease_break(const unsigned int xid, struct cifs_= tcon *tcon, struct TCP_Server_Info *server =3D cifs_pick_channel(tcon->ses); =20 cifs_dbg(FYI, "SMB2_lease_break\n"); - rc =3D smb2_plain_req_init(SMB2_OPLOCK_BREAK, tcon, server, + rc =3D smb2_plain_req_init(SMB2_OPLOCK_BREAK_HE, tcon, server, (void **) &req, &total_len); if (rc) return rc; diff --git a/fs/smb/client/smb2transport.c b/fs/smb/client/smb2transport.c index 5348bfd5fad0..806ced5d0783 100644 --- a/fs/smb/client/smb2transport.c +++ b/fs/smb/client/smb2transport.c @@ -671,7 +671,7 @@ smb2_sign_rqst(struct smb_rqst *rqst, struct TCP_Server= _Info *server) shdr =3D (struct smb2_hdr *)rqst->rq_iov[0].iov_base; ssr =3D (struct smb2_sess_setup_req *)shdr; =20 - is_binding =3D shdr->Command =3D=3D SMB2_SESSION_SETUP && + is_binding =3D le16_to_cpu(shdr->Command) =3D=3D SMB2_SESSION_SETUP_HE && (ssr->Flags & SMB2_SESSION_REQ_FLAG_BINDING); is_signed =3D shdr->Flags & SMB2_FLAGS_SIGNED; =20 @@ -702,9 +702,9 @@ smb2_verify_signature(struct smb_rqst *rqst, struct TCP= _Server_Info *server) struct smb2_hdr *shdr =3D (struct smb2_hdr *)rqst->rq_iov[0].iov_base; =20 - if ((shdr->Command =3D=3D SMB2_NEGOTIATE) || - (shdr->Command =3D=3D SMB2_SESSION_SETUP) || - (shdr->Command =3D=3D SMB2_OPLOCK_BREAK) || + if (le16_to_cpu(shdr->Command) =3D=3D SMB2_NEGOTIATE_HE || + le16_to_cpu(shdr->Command) =3D=3D SMB2_SESSION_SETUP_HE || + le16_to_cpu(shdr->Command) =3D=3D SMB2_OPLOCK_BREAK_HE || server->ignore_signature || (!server->session_estab)) return 0; @@ -774,7 +774,7 @@ smb2_mid_entry_alloc(const struct smb2_hdr *shdr, smb->mid =3D le64_to_cpu(shdr->MessageId); smb->credits =3D credits > 0 ? credits : 1; smb->pid =3D current->pid; - smb->command =3D shdr->Command; /* Always LE */ + smb->command_id =3D le16_to_cpu(shdr->Command); smb->when_alloc =3D jiffies; smb->server =3D server; =20 @@ -812,7 +812,7 @@ smb2_get_mid_entry(struct cifs_ses *ses, struct TCP_Ser= ver_Info *server, } =20 if (server->tcpStatus =3D=3D CifsNeedNegotiate && - shdr->Command !=3D SMB2_NEGOTIATE) { + le16_to_cpu(shdr->Command) !=3D SMB2_NEGOTIATE_HE) { spin_unlock(&server->srv_lock); return -EAGAIN; } @@ -820,8 +820,8 @@ smb2_get_mid_entry(struct cifs_ses *ses, struct TCP_Ser= ver_Info *server, =20 spin_lock(&ses->ses_lock); if (ses->ses_status =3D=3D SES_NEW) { - if ((shdr->Command !=3D SMB2_SESSION_SETUP) && - (shdr->Command !=3D SMB2_NEGOTIATE)) { + if (le16_to_cpu(shdr->Command) !=3D SMB2_SESSION_SETUP_HE && + le16_to_cpu(shdr->Command) !=3D SMB2_NEGOTIATE_HE) { spin_unlock(&ses->ses_lock); return -EAGAIN; } @@ -829,7 +829,7 @@ smb2_get_mid_entry(struct cifs_ses *ses, struct TCP_Ser= ver_Info *server, } =20 if (ses->ses_status =3D=3D SES_EXITING) { - if (shdr->Command !=3D SMB2_LOGOFF) { + if (le16_to_cpu(shdr->Command) !=3D SMB2_LOGOFF_HE) { spin_unlock(&ses->ses_lock); return -EAGAIN; } @@ -910,7 +910,7 @@ smb2_setup_async_request(struct TCP_Server_Info *server= , struct smb_rqst *rqst) =20 spin_lock(&server->srv_lock); if (server->tcpStatus =3D=3D CifsNeedNegotiate && - shdr->Command !=3D SMB2_NEGOTIATE) { + le16_to_cpu(shdr->Command) !=3D SMB2_NEGOTIATE_HE) { spin_unlock(&server->srv_lock); return ERR_PTR(-EAGAIN); } diff --git a/fs/smb/client/transport.c b/fs/smb/client/transport.c index a105e0ddf81a..d55b24d1aa77 100644 --- a/fs/smb/client/transport.c +++ b/fs/smb/client/transport.c @@ -43,8 +43,8 @@ void __release_mid(struct kref *refcount) struct smb_message *smb =3D container_of(refcount, struct smb_message, refcount); #ifdef CONFIG_CIFS_STATS2 - __le16 command =3D smb->server->vals->lock_cmd; - __u16 smb_cmd =3D le16_to_cpu(smb->command); + enum smb2_command command =3D smb->server->vals->lock_cmd; + enum smb2_command smb_cmd =3D smb->command_id; unsigned long now; unsigned long roundtrip_time; #endif @@ -93,7 +93,7 @@ void __release_mid(struct kref *refcount) */ if ((slow_rsp_threshold !=3D 0) && time_after(now, smb->when_alloc + (slow_rsp_threshold * HZ)) && - (smb->command !=3D command)) { + (smb->command_id !=3D command)) { /* * smb2slowcmd[NUMBER_OF_SMB2_COMMANDS] counts by command * NB: le16_to_cpu returns unsigned so can not be negative below @@ -105,7 +105,7 @@ void __release_mid(struct kref *refcount) smb->when_sent, smb->when_received); if (cifsFYI & CIFS_TIMER) { pr_debug("slow rsp: cmd %d mid %llu", - smb->command, smb->mid); + smb->command_id, smb->mid); cifs_info("A: 0x%lx S: 0x%lx R: 0x%lx\n", now - smb->when_alloc, now - smb->when_sent, @@ -733,7 +733,7 @@ int cifs_sync_mid_result(struct smb_message *smb, struc= t TCP_Server_Info *server int rc =3D 0; =20 cifs_dbg(FYI, "%s: cmd=3D%d mid=3D%llu state=3D%d\n", - __func__, le16_to_cpu(smb->command), smb->mid, smb->mid_state); + __func__, smb->command_id, smb->mid, smb->mid_state); =20 spin_lock(&server->mid_lock); switch (smb->mid_state) { @@ -1004,7 +1004,7 @@ compound_send_recv(const unsigned int xid, struct cif= s_ses *ses, if (rc !=3D 0) { for (; i < num_rqst; i++) { cifs_server_dbg(FYI, "Cancelling wait for mid %llu cmd: %d\n", - smb[i]->mid, le16_to_cpu(smb[i]->command)); + smb[i]->mid, smb[i]->command_id); send_cancel(server, &rqst[i], smb[i]); spin_lock(&server->mid_lock); smb[i]->mid_flags |=3D MID_WAIT_CANCELLED; diff --git a/fs/smb/common/smb2pdu.h b/fs/smb/common/smb2pdu.h index f79a5165a7cc..2f4b158518cd 100644 --- a/fs/smb/common/smb2pdu.h +++ b/fs/smb/common/smb2pdu.h @@ -15,49 +15,30 @@ */ =20 /* List of commands in host endian */ -#define SMB2_NEGOTIATE_HE 0x0000 -#define SMB2_SESSION_SETUP_HE 0x0001 -#define SMB2_LOGOFF_HE 0x0002 /* trivial request/resp */ -#define SMB2_TREE_CONNECT_HE 0x0003 -#define SMB2_TREE_DISCONNECT_HE 0x0004 /* trivial req/resp */ -#define SMB2_CREATE_HE 0x0005 -#define SMB2_CLOSE_HE 0x0006 -#define SMB2_FLUSH_HE 0x0007 /* trivial resp */ -#define SMB2_READ_HE 0x0008 -#define SMB2_WRITE_HE 0x0009 -#define SMB2_LOCK_HE 0x000A -#define SMB2_IOCTL_HE 0x000B -#define SMB2_CANCEL_HE 0x000C -#define SMB2_ECHO_HE 0x000D -#define SMB2_QUERY_DIRECTORY_HE 0x000E -#define SMB2_CHANGE_NOTIFY_HE 0x000F -#define SMB2_QUERY_INFO_HE 0x0010 -#define SMB2_SET_INFO_HE 0x0011 -#define SMB2_OPLOCK_BREAK_HE 0x0012 -#define SMB2_SERVER_TO_CLIENT_NOTIFICATION 0x0013 - -/* The same list in little endian */ -#define SMB2_NEGOTIATE cpu_to_le16(SMB2_NEGOTIATE_HE) -#define SMB2_SESSION_SETUP cpu_to_le16(SMB2_SESSION_SETUP_HE) -#define SMB2_LOGOFF cpu_to_le16(SMB2_LOGOFF_HE) -#define SMB2_TREE_CONNECT cpu_to_le16(SMB2_TREE_CONNECT_HE) -#define SMB2_TREE_DISCONNECT cpu_to_le16(SMB2_TREE_DISCONNECT_HE) -#define SMB2_CREATE cpu_to_le16(SMB2_CREATE_HE) -#define SMB2_CLOSE cpu_to_le16(SMB2_CLOSE_HE) -#define SMB2_FLUSH cpu_to_le16(SMB2_FLUSH_HE) -#define SMB2_READ cpu_to_le16(SMB2_READ_HE) -#define SMB2_WRITE cpu_to_le16(SMB2_WRITE_HE) -#define SMB2_LOCK cpu_to_le16(SMB2_LOCK_HE) -#define SMB2_IOCTL cpu_to_le16(SMB2_IOCTL_HE) -#define SMB2_CANCEL cpu_to_le16(SMB2_CANCEL_HE) -#define SMB2_ECHO cpu_to_le16(SMB2_ECHO_HE) -#define SMB2_QUERY_DIRECTORY cpu_to_le16(SMB2_QUERY_DIRECTORY_HE) -#define SMB2_CHANGE_NOTIFY cpu_to_le16(SMB2_CHANGE_NOTIFY_HE) -#define SMB2_QUERY_INFO cpu_to_le16(SMB2_QUERY_INFO_HE) -#define SMB2_SET_INFO cpu_to_le16(SMB2_SET_INFO_HE) -#define SMB2_OPLOCK_BREAK cpu_to_le16(SMB2_OPLOCK_BREAK_HE) - -#define SMB2_INTERNAL_CMD cpu_to_le16(0xFFFF) +enum smb2_command { + SMB2_NEGOTIATE_HE =3D 0x0000, + SMB2_SESSION_SETUP_HE =3D 0x0001, + SMB2_LOGOFF_HE =3D 0x0002, /* trivial request/resp */ + SMB2_TREE_CONNECT_HE =3D 0x0003, + SMB2_TREE_DISCONNECT_HE =3D 0x0004, /* trivial req/resp */ + SMB2_CREATE_HE =3D 0x0005, + SMB2_CLOSE_HE =3D 0x0006, + SMB2_FLUSH_HE =3D 0x0007, /* trivial resp */ + SMB2_READ_HE =3D 0x0008, + SMB2_WRITE_HE =3D 0x0009, + SMB2_LOCK_HE =3D 0x000A, + SMB2_IOCTL_HE =3D 0x000B, + SMB2_CANCEL_HE =3D 0x000C, + SMB2_ECHO_HE =3D 0x000D, + SMB2_QUERY_DIRECTORY_HE =3D 0x000E, + SMB2_CHANGE_NOTIFY_HE =3D 0x000F, + SMB2_QUERY_INFO_HE =3D 0x0010, + SMB2_SET_INFO_HE =3D 0x0011, + SMB2_OPLOCK_BREAK_HE =3D 0x0012, + SMB2_SERVER_TO_CLIENT_NOTIFICATION =3D 0x0013 +}; + +#define SMB2_INTERNAL_CMD_HE 0xFFFF =20 #define NUMBER_OF_SMB2_COMMANDS 0x0013 =20 @@ -182,6 +163,7 @@ struct smb3_hdr_req { struct smb2_pdu { struct smb2_hdr hdr; __le16 StructureSize2; /* size of wct area (varies, request specific) */ +#define SMB2_STRUCT_HAS_DYNAMIC_PART 0x01 } __packed; =20 #define SMB2_ERROR_STRUCTURE_SIZE2 9 diff --git a/fs/smb/server/oplock.c b/fs/smb/server/oplock.c index d7a8a580d013..dd3c046aeae3 100644 --- a/fs/smb/server/oplock.c +++ b/fs/smb/server/oplock.c @@ -642,7 +642,7 @@ static void __smb2_oplock_break_noti(struct work_struct= *wk) rsp_hdr->ProtocolId =3D SMB2_PROTO_NUMBER; rsp_hdr->StructureSize =3D SMB2_HEADER_STRUCTURE_SIZE; rsp_hdr->CreditRequest =3D cpu_to_le16(0); - rsp_hdr->Command =3D SMB2_OPLOCK_BREAK; + rsp_hdr->Command =3D cpu_to_le16(SMB2_OPLOCK_BREAK_HE); rsp_hdr->Flags =3D (SMB2_FLAGS_SERVER_TO_REDIR); rsp_hdr->NextCommand =3D 0; rsp_hdr->MessageId =3D cpu_to_le64(-1); @@ -749,7 +749,7 @@ static void __smb2_lease_break_noti(struct work_struct = *wk) rsp_hdr->ProtocolId =3D SMB2_PROTO_NUMBER; rsp_hdr->StructureSize =3D SMB2_HEADER_STRUCTURE_SIZE; rsp_hdr->CreditRequest =3D cpu_to_le16(0); - rsp_hdr->Command =3D SMB2_OPLOCK_BREAK; + rsp_hdr->Command =3D cpu_to_le16(SMB2_OPLOCK_BREAK_HE); rsp_hdr->Flags =3D (SMB2_FLAGS_SERVER_TO_REDIR); rsp_hdr->NextCommand =3D 0; rsp_hdr->MessageId =3D cpu_to_le64(-1); diff --git a/fs/smb/server/smb2misc.c b/fs/smb/server/smb2misc.c index ae501024665e..41323492f214 100644 --- a/fs/smb/server/smb2misc.c +++ b/fs/smb/server/smb2misc.c @@ -95,18 +95,18 @@ static int smb2_get_data_area_len(unsigned int *off, un= signed int *len, * of the data buffer offset and data buffer length for the particular * command. */ - switch (hdr->Command) { - case SMB2_SESSION_SETUP: + switch (le16_to_cpu(hdr->Command)) { + case SMB2_SESSION_SETUP_HE: *off =3D le16_to_cpu(((struct smb2_sess_setup_req *)hdr)->SecurityBuffer= Offset); *len =3D le16_to_cpu(((struct smb2_sess_setup_req *)hdr)->SecurityBuffer= Length); break; - case SMB2_TREE_CONNECT: + case SMB2_TREE_CONNECT_HE: *off =3D max_t(unsigned short int, le16_to_cpu(((struct smb2_tree_connect_req *)hdr)->PathOffset), offsetof(struct smb2_tree_connect_req, Buffer)); *len =3D le16_to_cpu(((struct smb2_tree_connect_req *)hdr)->PathLength); break; - case SMB2_CREATE: + case SMB2_CREATE_HE: { unsigned short int name_off =3D max_t(unsigned short int, @@ -131,23 +131,23 @@ static int smb2_get_data_area_len(unsigned int *off, = unsigned int *len, *len =3D name_len; break; } - case SMB2_QUERY_INFO: + case SMB2_QUERY_INFO_HE: *off =3D max_t(unsigned int, le16_to_cpu(((struct smb2_query_info_req *)hdr)->InputBufferOffset= ), offsetof(struct smb2_query_info_req, Buffer)); *len =3D le32_to_cpu(((struct smb2_query_info_req *)hdr)->InputBufferLen= gth); break; - case SMB2_SET_INFO: + case SMB2_SET_INFO_HE: *off =3D max_t(unsigned int, le16_to_cpu(((struct smb2_set_info_req *)hdr)->BufferOffset), offsetof(struct smb2_set_info_req, Buffer)); *len =3D le32_to_cpu(((struct smb2_set_info_req *)hdr)->BufferLength); break; - case SMB2_READ: + case SMB2_READ_HE: *off =3D le16_to_cpu(((struct smb2_read_req *)hdr)->ReadChannelInfoOffse= t); *len =3D le16_to_cpu(((struct smb2_read_req *)hdr)->ReadChannelInfoLengt= h); break; - case SMB2_WRITE: + case SMB2_WRITE_HE: if (((struct smb2_write_req *)hdr)->DataOffset || ((struct smb2_write_req *)hdr)->Length) { *off =3D max_t(unsigned short int, @@ -160,13 +160,13 @@ static int smb2_get_data_area_len(unsigned int *off, = unsigned int *len, *off =3D le16_to_cpu(((struct smb2_write_req *)hdr)->WriteChannelInfoOff= set); *len =3D le16_to_cpu(((struct smb2_write_req *)hdr)->WriteChannelInfoLen= gth); break; - case SMB2_QUERY_DIRECTORY: + case SMB2_QUERY_DIRECTORY_HE: *off =3D max_t(unsigned short int, le16_to_cpu(((struct smb2_query_directory_req *)hdr)->FileNameOffs= et), offsetof(struct smb2_query_directory_req, Buffer)); *len =3D le16_to_cpu(((struct smb2_query_directory_req *)hdr)->FileNameL= ength); break; - case SMB2_LOCK: + case SMB2_LOCK_HE: { unsigned short lock_count; =20 @@ -177,7 +177,7 @@ static int smb2_get_data_area_len(unsigned int *off, un= signed int *len, } break; } - case SMB2_IOCTL: + case SMB2_IOCTL_HE: *off =3D max_t(unsigned int, le32_to_cpu(((struct smb2_ioctl_req *)hdr)->InputOffset), offsetof(struct smb2_ioctl_req, Buffer)); @@ -226,7 +226,7 @@ static int smb2_calc_size(void *buf, unsigned int *len) * regardless of number of locks. Subtract single * smb2_lock_element for correct buffer size check. */ - if (hdr->Command =3D=3D SMB2_LOCK) + if (le16_to_cpu(hdr->Command) =3D=3D SMB2_LOCK_HE) *len -=3D sizeof(struct smb2_lock_element); =20 if (has_smb2_data_area[le16_to_cpu(hdr->Command)] =3D=3D false) @@ -306,27 +306,27 @@ static int smb2_validate_credit_charge(struct ksmbd_c= onn *conn, void *__hdr =3D hdr; int ret =3D 0; =20 - switch (hdr->Command) { - case SMB2_QUERY_INFO: + switch (le16_to_cpu(hdr->Command)) { + case SMB2_QUERY_INFO_HE: req_len =3D smb2_query_info_req_len(__hdr); break; - case SMB2_SET_INFO: + case SMB2_SET_INFO_HE: req_len =3D smb2_set_info_req_len(__hdr); break; - case SMB2_READ: + case SMB2_READ_HE: req_len =3D smb2_read_req_len(__hdr); break; - case SMB2_WRITE: + case SMB2_WRITE_HE: req_len =3D smb2_write_req_len(__hdr); break; - case SMB2_QUERY_DIRECTORY: + case SMB2_QUERY_DIRECTORY_HE: req_len =3D smb2_query_dir_req_len(__hdr); break; - case SMB2_IOCTL: + case SMB2_IOCTL_HE: req_len =3D smb2_ioctl_req_len(__hdr); expect_resp_len =3D smb2_ioctl_resp_len(__hdr); break; - case SMB2_CANCEL: + case SMB2_CANCEL_HE: return 0; default: req_len =3D 1; diff --git a/fs/smb/server/smb2ops.c b/fs/smb/server/smb2ops.c index 606aa3c5189a..c9302dd71e53 100644 --- a/fs/smb/server/smb2ops.c +++ b/fs/smb/server/smb2ops.c @@ -27,7 +27,7 @@ static struct smb_version_values smb21_server_values =3D { .header_size =3D sizeof(struct smb2_hdr), .max_header_size =3D MAX_SMB2_HDR_SIZE, .read_rsp_size =3D sizeof(struct smb2_read_rsp), - .lock_cmd =3D SMB2_LOCK, + .lock_cmd =3D SMB2_LOCK_HE, .cap_unix =3D 0, .cap_nt_find =3D SMB2_NT_FIND, .cap_large_files =3D SMB2_LARGE_FILES, @@ -53,7 +53,7 @@ static struct smb_version_values smb30_server_values =3D { .header_size =3D sizeof(struct smb2_hdr), .max_header_size =3D MAX_SMB2_HDR_SIZE, .read_rsp_size =3D sizeof(struct smb2_read_rsp), - .lock_cmd =3D SMB2_LOCK, + .lock_cmd =3D SMB2_LOCK_HE, .cap_unix =3D 0, .cap_nt_find =3D SMB2_NT_FIND, .cap_large_files =3D SMB2_LARGE_FILES, @@ -80,7 +80,7 @@ static struct smb_version_values smb302_server_values =3D= { .header_size =3D sizeof(struct smb2_hdr), .max_header_size =3D MAX_SMB2_HDR_SIZE, .read_rsp_size =3D sizeof(struct smb2_read_rsp), - .lock_cmd =3D SMB2_LOCK, + .lock_cmd =3D SMB2_LOCK_HE, .cap_unix =3D 0, .cap_nt_find =3D SMB2_NT_FIND, .cap_large_files =3D SMB2_LARGE_FILES, @@ -107,7 +107,7 @@ static struct smb_version_values smb311_server_values = =3D { .header_size =3D sizeof(struct smb2_hdr), .max_header_size =3D MAX_SMB2_HDR_SIZE, .read_rsp_size =3D sizeof(struct smb2_read_rsp), - .lock_cmd =3D SMB2_LOCK, + .lock_cmd =3D SMB2_LOCK_HE, .cap_unix =3D 0, .cap_nt_find =3D SMB2_NT_FIND, .cap_large_files =3D SMB2_LARGE_FILES, diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c index fafa86273f12..74749c60d9f6 100644 --- a/fs/smb/server/smb2pdu.c +++ b/fs/smb/server/smb2pdu.c @@ -181,7 +181,7 @@ bool is_smb2_neg_cmd(struct ksmbd_work *work) if (hdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR) return false; =20 - if (hdr->Command !=3D SMB2_NEGOTIATE) + if (le16_to_cpu(hdr->Command) !=3D SMB2_NEGOTIATE_HE) return false; =20 return true; @@ -262,7 +262,7 @@ int init_smb2_neg_rsp(struct ksmbd_work *work) rsp_hdr->ProtocolId =3D SMB2_PROTO_NUMBER; rsp_hdr->StructureSize =3D SMB2_HEADER_STRUCTURE_SIZE; rsp_hdr->CreditRequest =3D cpu_to_le16(2); - rsp_hdr->Command =3D SMB2_NEGOTIATE; + rsp_hdr->Command =3D cpu_to_le16(SMB2_NEGOTIATE_HE); rsp_hdr->Flags =3D (SMB2_FLAGS_SERVER_TO_REDIR); rsp_hdr->NextCommand =3D 0; rsp_hdr->MessageId =3D 0; @@ -349,7 +349,7 @@ int smb2_set_rsp_credits(struct ksmbd_work *work) * TODO: Need to adjuct CreditRequest value according to * current cpu load */ - if (hdr->Command =3D=3D SMB2_NEGOTIATE) + if (le16_to_cpu(hdr->Command) =3D=3D SMB2_NEGOTIATE_HE) aux_max =3D 1; else aux_max =3D conn->vals->max_credits - conn->total_credits; @@ -389,7 +389,7 @@ static void init_chained_smb2_rsp(struct ksmbd_work *wo= rk) /* Storing the current local FID which may be needed by subsequent * command in the compound request */ - if (req->Command =3D=3D SMB2_CREATE && rsp->Status =3D=3D STATUS_SUCCESS)= { + if (req->Command =3D=3D cpu_to_le16(SMB2_CREATE_HE) && rsp->Status =3D=3D= STATUS_SUCCESS) { work->compound_fid =3D ((struct smb2_create_rsp *)rsp)->VolatileFileId; work->compound_pfid =3D ((struct smb2_create_rsp *)rsp)->PersistentFileI= d; work->compound_sid =3D le64_to_cpu(rsp->SessionId); @@ -572,7 +572,7 @@ int smb2_check_user_session(struct ksmbd_work *work) { struct smb2_hdr *req_hdr =3D ksmbd_req_buf_next(work); struct ksmbd_conn *conn =3D work->conn; - unsigned int cmd =3D le16_to_cpu(req_hdr->Command); + enum smb2_command cmd =3D le16_to_cpu(req_hdr->Command); unsigned long long sess_id; =20 /* @@ -8887,7 +8887,7 @@ void smb2_set_sign_rsp(struct ksmbd_work *work) hdr->Flags |=3D SMB2_FLAGS_SIGNED; memset(hdr->Signature, 0, SMB2_SIGNATURE_SIZE); =20 - if (hdr->Command =3D=3D SMB2_READ) { + if (hdr->Command =3D=3D cpu_to_le16(SMB2_READ_HE)) { iov =3D &work->iov[work->iov_idx - 1]; n_vec++; } else { @@ -8993,7 +8993,7 @@ void smb3_set_sign_rsp(struct ksmbd_work *work) hdr->Flags |=3D SMB2_FLAGS_SIGNED; memset(hdr->Signature, 0, SMB2_SIGNATURE_SIZE); =20 - if (hdr->Command =3D=3D SMB2_READ) { + if (hdr->Command =3D=3D cpu_to_le16(SMB2_READ_HE)) { iov =3D &work->iov[work->iov_idx - 1]; n_vec++; } else { From nobody Thu Dec 18 03:20:29 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7B15C21FF49 for ; Wed, 6 Aug 2025 20:38:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512692; cv=none; b=pQYbcjOIQPTeh5ZOu+Hg1Z6KhS8tfxLPS9e+YQQOra7ptqeXs0HvwowW9WfkszsGoQFSOQbm44+Ws0y+prK0y43QGalhOySMXgb5AJby5SUP6q3GD3uOcRO4hXbDp+ZKV+S3rN+3CqHtEg0vu/3529jS6uojDMN11bPnPHE4aps= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512692; c=relaxed/simple; bh=dlpYImrdr5ig5f0eGfjCGwi/zkNFspEhX8SFybOIW6M=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Qf7ziNeWrlys9Rv4PjgsxYSAH/mQezHjZ0NT2p34A6f9TA1zBiWJRybXApKOOda5gsZJFYZH8nqxg9BxOHjXvbP0lqbvdzgB4mFbItsAX4W1GMA7wKjyXrOUZmEOkfSSh5xqi/uO0FlJXtt77koLDzXlS+51d5haVABVPSQRmy8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=MgCQl8P1; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="MgCQl8P1" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1754512686; h=from:from:reply-to:subject:subject: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=EniwsJc+bUFAtIahAbpGM/bZVSnuaGlzZlTbBHFQ4zw=; b=MgCQl8P195fXgftTtU8h4itAJjPUOBZzFLZiCBMq8dQIb3ESlsVijuy/+bEDVUiLLCufCv Q6lbGEpsJl5DBBqaNYJmxBvibSUIXvVFAX32bFOeCrm3nWa+lmPdkJUhkEt3/dDBQtV3Km 98tOtSkeoOO2IdMRAVH81x3Fa63rIdE= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-210-Yr9TL-XPNROBob1EU7WrJw-1; Wed, 06 Aug 2025 16:38:01 -0400 X-MC-Unique: Yr9TL-XPNROBob1EU7WrJw-1 X-Mimecast-MFC-AGG-ID: Yr9TL-XPNROBob1EU7WrJw_1754512679 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 1044418004D4; Wed, 6 Aug 2025 20:37:59 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.17]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 97D52180028E; Wed, 6 Aug 2025 20:37:55 +0000 (UTC) From: David Howells To: Steve French Cc: David Howells , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Wang Zhaolong , Stefan Metzmacher , Mina Almasry , linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org, netfs@lists.linux.dev, linux-fsdevel@vger.kernel.org Subject: [RFC PATCH 09/31] cifs: Rename SMB2_xxxx_HE to SMB2_xxxx Date: Wed, 6 Aug 2025 21:36:30 +0100 Message-ID: <20250806203705.2560493-10-dhowells@redhat.com> In-Reply-To: <20250806203705.2560493-1-dhowells@redhat.com> References: <20250806203705.2560493-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Content-Type: text/plain; charset="utf-8" Rename SMB2_xxxx_HE to SMB2_xxxx as the LE variants have been got rid of. Signed-off-by: David Howells cc: Steve French cc: Paulo Alcantara cc: Shyam Prasad N cc: Tom Talpey cc: linux-cifs@vger.kernel.org cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/smb/client/compress.c | 4 +- fs/smb/client/smb2misc.c | 43 ++++++----- fs/smb/client/smb2ops.c | 72 +++++++++--------- fs/smb/client/smb2pdu.c | 134 +++++++++++++++++----------------- fs/smb/client/smb2transport.c | 18 ++--- fs/smb/common/smb2pdu.h | 40 +++++----- fs/smb/server/connection.c | 2 +- fs/smb/server/oplock.c | 4 +- fs/smb/server/smb2misc.c | 44 +++++------ fs/smb/server/smb2ops.c | 46 ++++++------ fs/smb/server/smb2pdu.c | 42 +++++------ fs/smb/server/smb_common.c | 2 +- 12 files changed, 225 insertions(+), 226 deletions(-) diff --git a/fs/smb/client/compress.c b/fs/smb/client/compress.c index f52710425151..3caf4b89d8a5 100644 --- a/fs/smb/client/compress.c +++ b/fs/smb/client/compress.c @@ -303,7 +303,7 @@ bool should_compress(const struct cifs_tcon *tcon, cons= t struct smb_rqst *rq) if (!(tcon->share_flags & SMB2_SHAREFLAG_COMPRESS_DATA)) return false; =20 - if (le16_to_cpu(shdr->Command) =3D=3D SMB2_WRITE_HE) { + if (le16_to_cpu(shdr->Command) =3D=3D SMB2_WRITE) { const struct smb2_write_req *wreq =3D rq->rq_iov->iov_base; =20 if (le32_to_cpu(wreq->Length) < SMB_COMPRESS_MIN_LEN) @@ -312,7 +312,7 @@ bool should_compress(const struct cifs_tcon *tcon, cons= t struct smb_rqst *rq) return is_compressible(&rq->rq_iter); } =20 - return le16_to_cpu(shdr->Command) =3D=3D SMB2_READ_HE; + return le16_to_cpu(shdr->Command) =3D=3D SMB2_READ; } =20 int smb_compress(struct TCP_Server_Info *server, struct smb_rqst *rq, comp= ress_send_fn send_fn) diff --git a/fs/smb/client/smb2misc.c b/fs/smb/client/smb2misc.c index f6280e3d4e55..b8e3fe26d658 100644 --- a/fs/smb/client/smb2misc.c +++ b/fs/smb/client/smb2misc.c @@ -33,7 +33,7 @@ check_smb2_hdr(struct smb2_hdr *shdr, __u64 mid) return 0; else { /* only one valid case where server sends us request */ - if (le16_to_cpu(shdr->Command) =3D=3D SMB2_OPLOCK_BREAK_HE) + if (le16_to_cpu(shdr->Command) =3D=3D SMB2_OPLOCK_BREAK) return 0; else cifs_dbg(VFS, "Received Request not response\n"); @@ -209,13 +209,13 @@ smb2_check_message(char *buf, unsigned int len, struc= t TCP_Server_Info *server) } =20 if (smb2_rsp_struct_sizes[command] !=3D pdu->StructureSize2) { - if (command !=3D SMB2_OPLOCK_BREAK_HE && (shdr->Status =3D=3D 0 || + if (command !=3D SMB2_OPLOCK_BREAK && (shdr->Status =3D=3D 0 || pdu->StructureSize2 !=3D SMB2_ERROR_STRUCTURE_SIZE2_LE)) { /* error packets have 9 byte structure size */ cifs_dbg(VFS, "Invalid response size %u for command %d\n", le16_to_cpu(pdu->StructureSize2), command); return 1; - } else if (command =3D=3D SMB2_OPLOCK_BREAK_HE + } else if (command =3D=3D SMB2_OPLOCK_BREAK && (shdr->Status =3D=3D 0) && (le16_to_cpu(pdu->StructureSize2) !=3D 44) && (le16_to_cpu(pdu->StructureSize2) !=3D 36)) { @@ -230,19 +230,19 @@ smb2_check_message(char *buf, unsigned int len, struc= t TCP_Server_Info *server) =20 /* For SMB2_IOCTL, OutputOffset and OutputLength are optional, so might * be 0, and not a real miscalculation */ - if (command =3D=3D SMB2_IOCTL_HE && calc_len =3D=3D 0) + if (command =3D=3D SMB2_IOCTL && calc_len =3D=3D 0) return 0; =20 - if (command =3D=3D SMB2_NEGOTIATE_HE) + if (command =3D=3D SMB2_NEGOTIATE) calc_len +=3D get_neg_ctxt_len(shdr, len, calc_len); =20 if (len !=3D calc_len) { /* create failed on symlink */ - if (command =3D=3D SMB2_CREATE_HE && + if (command =3D=3D SMB2_CREATE && shdr->Status =3D=3D STATUS_STOPPED_ON_SYMLINK) return 0; /* Windows 7 server returns 24 bytes more */ - if (calc_len + 24 =3D=3D len && command =3D=3D SMB2_OPLOCK_BREAK_HE) + if (calc_len + 24 =3D=3D len && command =3D=3D SMB2_OPLOCK_BREAK) return 0; /* server can return one byte more due to implied bcc[0] */ if (calc_len =3D=3D len + 1) @@ -331,48 +331,48 @@ smb2_get_data_area_len(int *off, int *len, struct smb= 2_hdr *shdr) * command. */ switch (le16_to_cpu(shdr->Command)) { - case SMB2_NEGOTIATE_HE: + case SMB2_NEGOTIATE: *off =3D le16_to_cpu( ((struct smb2_negotiate_rsp *)shdr)->SecurityBufferOffset); *len =3D le16_to_cpu( ((struct smb2_negotiate_rsp *)shdr)->SecurityBufferLength); break; - case SMB2_SESSION_SETUP_HE: + case SMB2_SESSION_SETUP: *off =3D le16_to_cpu( ((struct smb2_sess_setup_rsp *)shdr)->SecurityBufferOffset); *len =3D le16_to_cpu( ((struct smb2_sess_setup_rsp *)shdr)->SecurityBufferLength); break; - case SMB2_CREATE_HE: + case SMB2_CREATE: *off =3D le32_to_cpu( ((struct smb2_create_rsp *)shdr)->CreateContextsOffset); *len =3D le32_to_cpu( ((struct smb2_create_rsp *)shdr)->CreateContextsLength); break; - case SMB2_QUERY_INFO_HE: + case SMB2_QUERY_INFO: *off =3D le16_to_cpu( ((struct smb2_query_info_rsp *)shdr)->OutputBufferOffset); *len =3D le32_to_cpu( ((struct smb2_query_info_rsp *)shdr)->OutputBufferLength); break; - case SMB2_READ_HE: + case SMB2_READ: /* TODO: is this a bug ? */ *off =3D ((struct smb2_read_rsp *)shdr)->DataOffset; *len =3D le32_to_cpu(((struct smb2_read_rsp *)shdr)->DataLength); break; - case SMB2_QUERY_DIRECTORY_HE: + case SMB2_QUERY_DIRECTORY: *off =3D le16_to_cpu( ((struct smb2_query_directory_rsp *)shdr)->OutputBufferOffset); *len =3D le32_to_cpu( ((struct smb2_query_directory_rsp *)shdr)->OutputBufferLength); break; - case SMB2_IOCTL_HE: + case SMB2_IOCTL: *off =3D le32_to_cpu( ((struct smb2_ioctl_rsp *)shdr)->OutputOffset); *len =3D le32_to_cpu( ((struct smb2_ioctl_rsp *)shdr)->OutputCount); break; - case SMB2_CHANGE_NOTIFY_HE: + case SMB2_CHANGE_NOTIFY: *off =3D le16_to_cpu( ((struct smb2_change_notify_rsp *)shdr)->OutputBufferOffset); *len =3D le32_to_cpu( @@ -680,11 +680,10 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_S= erver_Info *server) =20 cifs_dbg(FYI, "Checking for oplock break\n"); =20 - if (rsp->hdr.Command !=3D cpu_to_le32(SMB2_OPLOCK_BREAK_HE)) + if (rsp->hdr.Command !=3D cpu_to_le32(SMB2_OPLOCK_BREAK)) return false; =20 - if (rsp->StructureSize !=3D - smb2_rsp_struct_sizes[SMB2_OPLOCK_BREAK_HE]) { + if (rsp->StructureSize !=3D smb2_rsp_struct_sizes[SMB2_OPLOCK_BREAK]) { if (le16_to_cpu(rsp->StructureSize) =3D=3D 44) return smb2_is_valid_lease_break(buffer, server); else @@ -830,7 +829,7 @@ smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u= 64 persistent_fid, netfs_trace_tcon_ref_get_cancelled_close); spin_unlock(&cifs_tcp_ses_lock); =20 - rc =3D __smb2_handle_cancelled_cmd(tcon, SMB2_CLOSE_HE, 0, + rc =3D __smb2_handle_cancelled_cmd(tcon, SMB2_CLOSE, 0, persistent_fid, volatile_fid); if (rc) cifs_put_tcon(tcon, netfs_trace_tcon_ref_put_cancelled_close); @@ -846,7 +845,7 @@ smb2_handle_cancelled_mid(struct smb_message *smb, stru= ct TCP_Server_Info *serve struct cifs_tcon *tcon; int rc; =20 - if ((smb->optype & CIFS_CP_CREATE_CLOSE_OP) || smb->command_id !=3D SMB2_= CREATE_HE || + if ((smb->optype & CIFS_CP_CREATE_CLOSE_OP) || smb->command_id !=3D SMB2_= CREATE || hdr->Status !=3D STATUS_SUCCESS) return 0; =20 @@ -887,7 +886,7 @@ smb311_update_preauth_hash(struct cifs_ses *ses, struct= TCP_Server_Info *server, =20 hdr =3D (struct smb2_hdr *)iov[0].iov_base; /* neg prot are always taken */ - if (le16_to_cpu(hdr->Command) =3D=3D SMB2_NEGOTIATE_HE) + if (le16_to_cpu(hdr->Command) =3D=3D SMB2_NEGOTIATE) goto ok; =20 /* @@ -898,7 +897,7 @@ smb311_update_preauth_hash(struct cifs_ses *ses, struct= TCP_Server_Info *server, if (server->dialect !=3D SMB311_PROT_ID) return 0; =20 - if (le16_to_cpu(hdr->Command) !=3D SMB2_SESSION_SETUP_HE) + if (le16_to_cpu(hdr->Command) !=3D SMB2_SESSION_SETUP) return 0; =20 /* skip last sess setup response */ diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c index 0116bf348a76..36c506577b0e 100644 --- a/fs/smb/client/smb2ops.c +++ b/fs/smb/client/smb2ops.c @@ -1405,47 +1405,47 @@ smb2_print_stats(struct seq_file *m, struct cifs_tc= on *tcon) atomic_read(&tcon->num_local_opens), atomic_read(&tcon->num_remote_opens)); seq_printf(m, "\nTreeConnects: %d total %d failed", - atomic_read(&sent[SMB2_TREE_CONNECT_HE]), - atomic_read(&failed[SMB2_TREE_CONNECT_HE])); + atomic_read(&sent[SMB2_TREE_CONNECT]), + atomic_read(&failed[SMB2_TREE_CONNECT])); seq_printf(m, "\nTreeDisconnects: %d total %d failed", - atomic_read(&sent[SMB2_TREE_DISCONNECT_HE]), - atomic_read(&failed[SMB2_TREE_DISCONNECT_HE])); + atomic_read(&sent[SMB2_TREE_DISCONNECT]), + atomic_read(&failed[SMB2_TREE_DISCONNECT])); seq_printf(m, "\nCreates: %d total %d failed", - atomic_read(&sent[SMB2_CREATE_HE]), - atomic_read(&failed[SMB2_CREATE_HE])); + atomic_read(&sent[SMB2_CREATE]), + atomic_read(&failed[SMB2_CREATE])); seq_printf(m, "\nCloses: %d total %d failed", - atomic_read(&sent[SMB2_CLOSE_HE]), - atomic_read(&failed[SMB2_CLOSE_HE])); + atomic_read(&sent[SMB2_CLOSE]), + atomic_read(&failed[SMB2_CLOSE])); seq_printf(m, "\nFlushes: %d total %d failed", - atomic_read(&sent[SMB2_FLUSH_HE]), - atomic_read(&failed[SMB2_FLUSH_HE])); + atomic_read(&sent[SMB2_FLUSH]), + atomic_read(&failed[SMB2_FLUSH])); seq_printf(m, "\nReads: %d total %d failed", - atomic_read(&sent[SMB2_READ_HE]), - atomic_read(&failed[SMB2_READ_HE])); + atomic_read(&sent[SMB2_READ]), + atomic_read(&failed[SMB2_READ])); seq_printf(m, "\nWrites: %d total %d failed", - atomic_read(&sent[SMB2_WRITE_HE]), - atomic_read(&failed[SMB2_WRITE_HE])); + atomic_read(&sent[SMB2_WRITE]), + atomic_read(&failed[SMB2_WRITE])); seq_printf(m, "\nLocks: %d total %d failed", - atomic_read(&sent[SMB2_LOCK_HE]), - atomic_read(&failed[SMB2_LOCK_HE])); + atomic_read(&sent[SMB2_LOCK]), + atomic_read(&failed[SMB2_LOCK])); seq_printf(m, "\nIOCTLs: %d total %d failed", - atomic_read(&sent[SMB2_IOCTL_HE]), - atomic_read(&failed[SMB2_IOCTL_HE])); + atomic_read(&sent[SMB2_IOCTL]), + atomic_read(&failed[SMB2_IOCTL])); seq_printf(m, "\nQueryDirectories: %d total %d failed", - atomic_read(&sent[SMB2_QUERY_DIRECTORY_HE]), - atomic_read(&failed[SMB2_QUERY_DIRECTORY_HE])); + atomic_read(&sent[SMB2_QUERY_DIRECTORY]), + atomic_read(&failed[SMB2_QUERY_DIRECTORY])); seq_printf(m, "\nChangeNotifies: %d total %d failed", - atomic_read(&sent[SMB2_CHANGE_NOTIFY_HE]), - atomic_read(&failed[SMB2_CHANGE_NOTIFY_HE])); + atomic_read(&sent[SMB2_CHANGE_NOTIFY]), + atomic_read(&failed[SMB2_CHANGE_NOTIFY])); seq_printf(m, "\nQueryInfos: %d total %d failed", - atomic_read(&sent[SMB2_QUERY_INFO_HE]), - atomic_read(&failed[SMB2_QUERY_INFO_HE])); + atomic_read(&sent[SMB2_QUERY_INFO]), + atomic_read(&failed[SMB2_QUERY_INFO])); seq_printf(m, "\nSetInfos: %d total %d failed", - atomic_read(&sent[SMB2_SET_INFO_HE]), - atomic_read(&failed[SMB2_SET_INFO_HE])); + atomic_read(&sent[SMB2_SET_INFO]), + atomic_read(&failed[SMB2_SET_INFO])); seq_printf(m, "\nOplockBreaks: %d sent %d failed", - atomic_read(&sent[SMB2_OPLOCK_BREAK_HE]), - atomic_read(&failed[SMB2_OPLOCK_BREAK_HE])); + atomic_read(&sent[SMB2_OPLOCK_BREAK]), + atomic_read(&failed[SMB2_OPLOCK_BREAK])); } =20 static void @@ -4626,7 +4626,7 @@ handle_read_data(struct TCP_Server_Info *server, stru= ct smb_message *smb, int length; bool use_rdma_mr =3D false; =20 - if (le16_to_cpu(shdr->Command) !=3D SMB2_READ_HE) { + if (le16_to_cpu(shdr->Command) !=3D SMB2_READ) { cifs_server_dbg(VFS, "only big read responses are supported\n"); return -EOPNOTSUPP; } @@ -5715,7 +5715,7 @@ struct smb_version_values smb20_values =3D { .header_preamble_size =3D 0, .max_header_size =3D MAX_SMB2_HDR_SIZE, .read_rsp_size =3D sizeof(struct smb2_read_rsp), - .lock_cmd =3D SMB2_LOCK_HE, + .lock_cmd =3D SMB2_LOCK, .cap_unix =3D 0, .cap_nt_find =3D SMB2_NT_FIND, .cap_large_files =3D SMB2_LARGE_FILES, @@ -5737,7 +5737,7 @@ struct smb_version_values smb21_values =3D { .header_preamble_size =3D 0, .max_header_size =3D MAX_SMB2_HDR_SIZE, .read_rsp_size =3D sizeof(struct smb2_read_rsp), - .lock_cmd =3D SMB2_LOCK_HE, + .lock_cmd =3D SMB2_LOCK, .cap_unix =3D 0, .cap_nt_find =3D SMB2_NT_FIND, .cap_large_files =3D SMB2_LARGE_FILES, @@ -5758,7 +5758,7 @@ struct smb_version_values smb3any_values =3D { .header_preamble_size =3D 0, .max_header_size =3D MAX_SMB2_HDR_SIZE, .read_rsp_size =3D sizeof(struct smb2_read_rsp), - .lock_cmd =3D SMB2_LOCK_HE, + .lock_cmd =3D SMB2_LOCK, .cap_unix =3D 0, .cap_nt_find =3D SMB2_NT_FIND, .cap_large_files =3D SMB2_LARGE_FILES, @@ -5779,7 +5779,7 @@ struct smb_version_values smbdefault_values =3D { .header_preamble_size =3D 0, .max_header_size =3D MAX_SMB2_HDR_SIZE, .read_rsp_size =3D sizeof(struct smb2_read_rsp), - .lock_cmd =3D SMB2_LOCK_HE, + .lock_cmd =3D SMB2_LOCK, .cap_unix =3D 0, .cap_nt_find =3D SMB2_NT_FIND, .cap_large_files =3D SMB2_LARGE_FILES, @@ -5800,7 +5800,7 @@ struct smb_version_values smb30_values =3D { .header_preamble_size =3D 0, .max_header_size =3D MAX_SMB2_HDR_SIZE, .read_rsp_size =3D sizeof(struct smb2_read_rsp), - .lock_cmd =3D SMB2_LOCK_HE, + .lock_cmd =3D SMB2_LOCK, .cap_unix =3D 0, .cap_nt_find =3D SMB2_NT_FIND, .cap_large_files =3D SMB2_LARGE_FILES, @@ -5821,7 +5821,7 @@ struct smb_version_values smb302_values =3D { .header_preamble_size =3D 0, .max_header_size =3D MAX_SMB2_HDR_SIZE, .read_rsp_size =3D sizeof(struct smb2_read_rsp), - .lock_cmd =3D SMB2_LOCK_HE, + .lock_cmd =3D SMB2_LOCK, .cap_unix =3D 0, .cap_nt_find =3D SMB2_NT_FIND, .cap_large_files =3D SMB2_LARGE_FILES, @@ -5842,7 +5842,7 @@ struct smb_version_values smb311_values =3D { .header_preamble_size =3D 0, .max_header_size =3D MAX_SMB2_HDR_SIZE, .read_rsp_size =3D sizeof(struct smb2_read_rsp), - .lock_cmd =3D SMB2_LOCK_HE, + .lock_cmd =3D SMB2_LOCK, .cap_unix =3D 0, .cap_nt_find =3D SMB2_NT_FIND, .cap_large_files =3D SMB2_LARGE_FILES, diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c index 97a267ce2a62..8554a4aa001d 100644 --- a/fs/smb/client/smb2pdu.c +++ b/fs/smb/client/smb2pdu.c @@ -230,7 +230,7 @@ smb2_reconnect(enum smb2_command smb2_command, struct c= ifs_tcon *tcon, if (tcon =3D=3D NULL) return 0; =20 - if (smb2_command =3D=3D SMB2_TREE_CONNECT_HE) + if (smb2_command =3D=3D SMB2_TREE_CONNECT) return 0; =20 spin_lock(&tcon->tc_lock); @@ -238,7 +238,7 @@ smb2_reconnect(enum smb2_command smb2_command, struct c= ifs_tcon *tcon, /* * only tree disconnect allowed when disconnecting ... */ - if (smb2_command !=3D SMB2_TREE_DISCONNECT_HE) { + if (smb2_command !=3D SMB2_TREE_DISCONNECT) { spin_unlock(&tcon->tc_lock); cifs_dbg(FYI, "can not send cmd %d while umounting\n", smb2_command); @@ -269,10 +269,10 @@ smb2_reconnect(enum smb2_command smb2_command, struct= cifs_tcon *tcon, /* * BB Should we keep oplock break and add flush to exceptions? */ - case SMB2_TREE_DISCONNECT_HE: - case SMB2_CANCEL_HE: - case SMB2_CLOSE_HE: - case SMB2_OPLOCK_BREAK_HE: + case SMB2_TREE_DISCONNECT: + case SMB2_CANCEL: + case SMB2_CLOSE: + case SMB2_OPLOCK_BREAK: spin_unlock(&server->srv_lock); return -EAGAIN; default: @@ -464,7 +464,7 @@ smb2_reconnect(enum smb2_command smb2_command, struct c= ifs_tcon *tcon, ses->flags &=3D ~CIFS_SES_FLAG_SCALE_CHANNELS; spin_unlock(&ses->ses_lock); =20 - if (smb2_command !=3D SMB2_INTERNAL_CMD_HE) + if (smb2_command !=3D SMB2_INTERNAL_CMD) mod_delayed_work(cifsiod_wq, &server->reconnect, 0); =20 atomic_inc(&tconInfoReconnectCount); @@ -478,15 +478,15 @@ smb2_reconnect(enum smb2_command smb2_command, struct= cifs_tcon *tcon, * case it and skip above? */ switch (smb2_command) { - case SMB2_FLUSH_HE: - case SMB2_READ_HE: - case SMB2_WRITE_HE: - case SMB2_LOCK_HE: - case SMB2_QUERY_DIRECTORY_HE: - case SMB2_CHANGE_NOTIFY_HE: - case SMB2_QUERY_INFO_HE: - case SMB2_SET_INFO_HE: - case SMB2_IOCTL_HE: + case SMB2_FLUSH: + case SMB2_READ: + case SMB2_WRITE: + case SMB2_LOCK: + case SMB2_QUERY_DIRECTORY: + case SMB2_CHANGE_NOTIFY: + case SMB2_QUERY_INFO: + case SMB2_SET_INFO: + case SMB2_IOCTL: rc =3D -EAGAIN; break; default: @@ -528,8 +528,8 @@ static int __smb2_plain_req_init(enum smb2_command smb2= _command, struct cifs_tco { /* BB eventually switch this to SMB2 specific small buf size */ switch (smb2_command) { - case SMB2_SET_INFO_HE: - case SMB2_QUERY_INFO_HE: + case SMB2_SET_INFO: + case SMB2_QUERY_INFO: *request_buf =3D cifs_buf_get(); break; default: @@ -581,10 +581,10 @@ static int smb2_ioctl_req_init(u32 opcode, struct cif= s_tcon *tcon, if (opcode =3D=3D FSCTL_VALIDATE_NEGOTIATE_INFO || (opcode =3D=3D FSCTL_QUERY_NETWORK_INTERFACE_INFO && (tcon->ses->flags & CIFS_SES_FLAGS_PENDING_QUERY_INTERFACES))) - return __smb2_plain_req_init(SMB2_IOCTL_HE, tcon, server, + return __smb2_plain_req_init(SMB2_IOCTL, tcon, server, request_buf, total_len); =20 - return smb2_plain_req_init(SMB2_IOCTL_HE, tcon, server, + return smb2_plain_req_init(SMB2_IOCTL, tcon, server, request_buf, total_len); } =20 @@ -1069,7 +1069,7 @@ SMB2_negotiate(const unsigned int xid, return -EIO; } =20 - rc =3D smb2_plain_req_init(SMB2_NEGOTIATE_HE, NULL, server, + rc =3D smb2_plain_req_init(SMB2_NEGOTIATE, NULL, server, (void **) &req, &total_len); if (rc) return rc; @@ -1469,7 +1469,7 @@ SMB2_sess_alloc_buffer(struct SMB2_sess_data *sess_da= ta) unsigned int total_len; bool is_binding =3D false; =20 - rc =3D smb2_plain_req_init(SMB2_SESSION_SETUP_HE, NULL, server, + rc =3D smb2_plain_req_init(SMB2_SESSION_SETUP, NULL, server, (void **) &req, &total_len); if (rc) @@ -1984,7 +1984,7 @@ SMB2_logoff(const unsigned int xid, struct cifs_ses *= ses) } spin_unlock(&ses->chan_lock); =20 - rc =3D smb2_plain_req_init(SMB2_LOGOFF_HE, NULL, ses->server, + rc =3D smb2_plain_req_init(SMB2_LOGOFF, NULL, ses->server, (void **) &req, &total_len); if (rc) return rc; @@ -2069,7 +2069,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *se= s, const char *tree, /* SMB2 TREE_CONNECT request must be called with TreeId =3D=3D 0 */ tcon->tid =3D 0; atomic_set(&tcon->num_remote_opens, 0); - rc =3D smb2_plain_req_init(SMB2_TREE_CONNECT_HE, tcon, server, + rc =3D smb2_plain_req_init(SMB2_TREE_CONNECT, tcon, server, (void **) &req, &total_len); if (rc) { kfree(unc_path); @@ -2119,7 +2119,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *se= s, const char *tree, rsp =3D (struct smb2_tree_connect_rsp *)rsp_iov.iov_base; trace_smb3_tcon(xid, tcon->tid, ses->Suid, tree, rc); if ((rc !=3D 0) || (rsp =3D=3D NULL)) { - cifs_stats_fail_inc(tcon, SMB2_TREE_CONNECT_HE); + cifs_stats_fail_inc(tcon, SMB2_TREE_CONNECT); tcon->need_reconnect =3D true; goto tcon_error_exit; } @@ -2204,7 +2204,7 @@ SMB2_tdis(const unsigned int xid, struct cifs_tcon *t= con) =20 invalidate_all_cached_dirs(tcon); =20 - rc =3D smb2_plain_req_init(SMB2_TREE_DISCONNECT_HE, tcon, server, + rc =3D smb2_plain_req_init(SMB2_TREE_DISCONNECT, tcon, server, (void **) &req, &total_len); if (rc) @@ -2226,7 +2226,7 @@ SMB2_tdis(const unsigned int xid, struct cifs_tcon *t= con) &rqst, &resp_buf_type, flags, &rsp_iov); cifs_small_buf_release(req); if (rc) { - cifs_stats_fail_inc(tcon, SMB2_TREE_DISCONNECT_HE); + cifs_stats_fail_inc(tcon, SMB2_TREE_DISCONNECT); trace_smb3_tdis_err(xid, tcon->tid, ses->Suid, rc); } trace_smb3_tdis_done(xid, tcon->tid, ses->Suid); @@ -2867,7 +2867,7 @@ int smb311_posix_mkdir(const unsigned int xid, struct= inode *inode, } =20 /* resource #2: request */ - rc =3D smb2_plain_req_init(SMB2_CREATE_HE, tcon, server, + rc =3D smb2_plain_req_init(SMB2_CREATE, tcon, server, (void **) &req, &total_len); if (rc) goto err_free_path; @@ -2965,7 +2965,7 @@ int smb311_posix_mkdir(const unsigned int xid, struct= inode *inode, rc =3D cifs_send_recv(xid, ses, server, &rqst, &resp_buftype, flags, &rsp_iov); if (rc) { - cifs_stats_fail_inc(tcon, SMB2_CREATE_HE); + cifs_stats_fail_inc(tcon, SMB2_CREATE); trace_smb3_posix_mkdir_err(xid, tcon->tid, ses->Suid, CREATE_NOT_FILE, FILE_WRITE_ATTRIBUTES, rc); @@ -3021,7 +3021,7 @@ SMB2_open_init(struct cifs_tcon *tcon, struct TCP_Ser= ver_Info *server, __le16 *copy_path; int rc; =20 - rc =3D smb2_plain_req_init(SMB2_CREATE_HE, tcon, server, + rc =3D smb2_plain_req_init(SMB2_CREATE, tcon, server, (void **) &req, &total_len); if (rc) return rc; @@ -3244,7 +3244,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_pa= rms *oparms, __le16 *path, rsp =3D (struct smb2_create_rsp *)rsp_iov.iov_base; =20 if (rc !=3D 0) { - cifs_stats_fail_inc(tcon, SMB2_CREATE_HE); + cifs_stats_fail_inc(tcon, SMB2_CREATE); if (err_iov && rsp) { *err_iov =3D rsp_iov; *buftype =3D resp_buftype; @@ -3473,17 +3473,17 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon= *tcon, u64 persistent_fid, ses->Suid, 0, opcode, rc); =20 if ((rc !=3D 0) && (rc !=3D -EINVAL) && (rc !=3D -E2BIG)) { - cifs_stats_fail_inc(tcon, SMB2_IOCTL_HE); + cifs_stats_fail_inc(tcon, SMB2_IOCTL); goto ioctl_exit; } else if (rc =3D=3D -EINVAL) { if ((opcode !=3D FSCTL_SRV_COPYCHUNK_WRITE) && (opcode !=3D FSCTL_SRV_COPYCHUNK)) { - cifs_stats_fail_inc(tcon, SMB2_IOCTL_HE); + cifs_stats_fail_inc(tcon, SMB2_IOCTL); goto ioctl_exit; } } else if (rc =3D=3D -E2BIG) { if (opcode !=3D FSCTL_QUERY_ALLOCATED_RANGES) { - cifs_stats_fail_inc(tcon, SMB2_IOCTL_HE); + cifs_stats_fail_inc(tcon, SMB2_IOCTL); goto ioctl_exit; } } @@ -3576,7 +3576,7 @@ SMB2_close_init(struct cifs_tcon *tcon, struct TCP_Se= rver_Info *server, unsigned int total_len; int rc; =20 - rc =3D smb2_plain_req_init(SMB2_CLOSE_HE, tcon, server, + rc =3D smb2_plain_req_init(SMB2_CLOSE, tcon, server, (void **) &req, &total_len); if (rc) return rc; @@ -3655,7 +3655,7 @@ __SMB2_close(const unsigned int xid, struct cifs_tcon= *tcon, rsp =3D (struct smb2_close_rsp *)rsp_iov.iov_base; =20 if (rc !=3D 0) { - cifs_stats_fail_inc(tcon, SMB2_CLOSE_HE); + cifs_stats_fail_inc(tcon, SMB2_CLOSE); trace_smb3_close_err(xid, persistent_fid, tcon->tid, ses->Suid, rc); goto close_exit; @@ -3770,7 +3770,7 @@ SMB2_query_info_init(struct cifs_tcon *tcon, struct T= CP_Server_Info *server, len > CIFSMaxBufSize)) return -EINVAL; =20 - rc =3D smb2_plain_req_init(SMB2_QUERY_INFO_HE, tcon, server, + rc =3D smb2_plain_req_init(SMB2_QUERY_INFO, tcon, server, (void **) &req, &total_len); if (rc) return rc; @@ -3860,7 +3860,7 @@ query_info(const unsigned int xid, struct cifs_tcon *= tcon, rsp =3D (struct smb2_query_info_rsp *)rsp_iov.iov_base; =20 if (rc) { - cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE); + cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO); trace_smb3_query_info_err(xid, persistent_fid, tcon->tid, ses->Suid, info_class, (__u32)info_type, rc); goto qinf_exit; @@ -3971,7 +3971,7 @@ SMB2_notify_init(const unsigned int xid, struct smb_r= qst *rqst, unsigned int total_len; int rc; =20 - rc =3D smb2_plain_req_init(SMB2_CHANGE_NOTIFY_HE, tcon, server, + rc =3D smb2_plain_req_init(SMB2_CHANGE_NOTIFY, tcon, server, (void **) &req, &total_len); if (rc) return rc; @@ -4046,7 +4046,7 @@ SMB2_change_notify(const unsigned int xid, struct cif= s_tcon *tcon, &rqst, &resp_buftype, flags, &rsp_iov); =20 if (rc !=3D 0) { - cifs_stats_fail_inc(tcon, SMB2_CHANGE_NOTIFY_HE); + cifs_stats_fail_inc(tcon, SMB2_CHANGE_NOTIFY); trace_smb3_notify_err(xid, persistent_fid, tcon->tid, ses->Suid, (u8)watch_tree, completion_filter, rc); } else { @@ -4208,7 +4208,7 @@ void smb2_reconnect_server(struct work_struct *work) spin_unlock(&cifs_tcp_ses_lock); =20 list_for_each_entry_safe(tcon, tcon2, &tmp_list, rlist) { - rc =3D smb2_reconnect(SMB2_INTERNAL_CMD_HE, tcon, server, true); + rc =3D smb2_reconnect(SMB2_INTERNAL_CMD, tcon, server, true); if (!rc) { cifs_renegotiate_iosize(server, tcon); cifs_reopen_persistent_handles(tcon); @@ -4240,7 +4240,7 @@ void smb2_reconnect_server(struct work_struct *work) /* now reconnect sessions for necessary channels */ list_for_each_entry_safe(ses, ses2, &tmp_ses_list, rlist) { tcon->ses =3D ses; - rc =3D smb2_reconnect(SMB2_INTERNAL_CMD_HE, tcon, server, true); + rc =3D smb2_reconnect(SMB2_INTERNAL_CMD, tcon, server, true); if (rc) resched =3D true; list_del_init(&ses->rlist); @@ -4280,7 +4280,7 @@ SMB2_echo(struct TCP_Server_Info *server) } spin_unlock(&server->srv_lock); =20 - rc =3D smb2_plain_req_init(SMB2_ECHO_HE, NULL, server, + rc =3D smb2_plain_req_init(SMB2_ECHO, NULL, server, (void **)&req, &total_len); if (rc) return rc; @@ -4316,7 +4316,7 @@ SMB2_flush_init(const unsigned int xid, struct smb_rq= st *rqst, unsigned int total_len; int rc; =20 - rc =3D smb2_plain_req_init(SMB2_FLUSH_HE, tcon, server, + rc =3D smb2_plain_req_init(SMB2_FLUSH, tcon, server, (void **) &req, &total_len); if (rc) return rc; @@ -4375,7 +4375,7 @@ SMB2_flush(const unsigned int xid, struct cifs_tcon *= tcon, u64 persistent_fid, &rqst, &resp_buftype, flags, &rsp_iov); =20 if (rc !=3D 0) { - cifs_stats_fail_inc(tcon, SMB2_FLUSH_HE); + cifs_stats_fail_inc(tcon, SMB2_FLUSH); trace_smb3_flush_err(xid, persistent_fid, tcon->tid, ses->Suid, rc); } else @@ -4437,7 +4437,7 @@ smb2_new_read_req(void **buf, unsigned int *total_len, struct smb2_hdr *shdr; struct TCP_Server_Info *server =3D io_parms->server; =20 - rc =3D smb2_plain_req_init(SMB2_READ_HE, io_parms->tcon, server, + rc =3D smb2_plain_req_init(SMB2_READ, io_parms->tcon, server, (void **) &req, total_len); if (rc) return rc; @@ -4606,7 +4606,7 @@ smb2_readv_callback(struct smb_message *smb) } #endif if (rdata->result && rdata->result !=3D -ENODATA) { - cifs_stats_fail_inc(tcon, SMB2_READ_HE); + cifs_stats_fail_inc(tcon, SMB2_READ); trace_smb3_read_err(rdata->rreq->debug_id, rdata->subreq.debug_index, rdata->xid, @@ -4720,7 +4720,7 @@ smb2_async_readv(struct cifs_io_subrequest *rdata) smb3_handle_read_data, rdata, flags, &rdata->credits); if (rc) { - cifs_stats_fail_inc(io_parms.tcon, SMB2_READ_HE); + cifs_stats_fail_inc(io_parms.tcon, SMB2_READ); trace_smb3_read_err(rdata->rreq->debug_id, subreq->debug_index, rdata->xid, io_parms.persistent_fid, @@ -4773,7 +4773,7 @@ SMB2_read(const unsigned int xid, struct cifs_io_parm= s *io_parms, =20 if (rc) { if (rc !=3D -ENODATA) { - cifs_stats_fail_inc(io_parms->tcon, SMB2_READ_HE); + cifs_stats_fail_inc(io_parms->tcon, SMB2_READ); cifs_dbg(VFS, "Send error in read =3D %d\n", rc); trace_smb3_read_err(0, 0, xid, req->PersistentFileId, @@ -4908,7 +4908,7 @@ smb2_writev_callback(struct smb_message *smb) } #endif if (result) { - cifs_stats_fail_inc(tcon, SMB2_WRITE_HE); + cifs_stats_fail_inc(tcon, SMB2_WRITE); trace_smb3_write_err(wdata->rreq->debug_id, wdata->subreq.debug_index, wdata->xid, @@ -4969,7 +4969,7 @@ smb2_async_writev(struct cifs_io_subrequest *wdata) }; io_parms =3D &_io_parms; =20 - rc =3D smb2_plain_req_init(SMB2_WRITE_HE, tcon, server, + rc =3D smb2_plain_req_init(SMB2_WRITE, tcon, server, (void **) &req, &total_len); if (rc) goto out; @@ -5089,7 +5089,7 @@ smb2_async_writev(struct cifs_io_subrequest *wdata) io_parms->offset, io_parms->length, rc); - cifs_stats_fail_inc(tcon, SMB2_WRITE_HE); + cifs_stats_fail_inc(tcon, SMB2_WRITE); } =20 async_writev_out: @@ -5141,7 +5141,7 @@ SMB2_write(const unsigned int xid, struct cifs_io_par= ms *io_parms, if (n_vec < 1) return rc; =20 - rc =3D smb2_plain_req_init(SMB2_WRITE_HE, io_parms->tcon, server, + rc =3D smb2_plain_req_init(SMB2_WRITE, io_parms->tcon, server, (void **) &req, &total_len); if (rc) return rc; @@ -5188,7 +5188,7 @@ SMB2_write(const unsigned int xid, struct cifs_io_par= ms *io_parms, io_parms->tcon->tid, io_parms->tcon->ses->Suid, io_parms->offset, io_parms->length, rc); - cifs_stats_fail_inc(io_parms->tcon, SMB2_WRITE_HE); + cifs_stats_fail_inc(io_parms->tcon, SMB2_WRITE); cifs_dbg(VFS, "Send error in write =3D %d\n", rc); } else { *nbytes =3D le32_to_cpu(rsp->DataLength); @@ -5374,7 +5374,7 @@ int SMB2_query_directory_init(const unsigned int xid, struct kvec *iov =3D rqst->rq_iov; int len, rc; =20 - rc =3D smb2_plain_req_init(SMB2_QUERY_DIRECTORY_HE, tcon, server, + rc =3D smb2_plain_req_init(SMB2_QUERY_DIRECTORY, tcon, server, (void **) &req, &total_len); if (rc) return rc; @@ -5568,7 +5568,7 @@ SMB2_query_directory(const unsigned int xid, struct c= ifs_tcon *tcon, } else { trace_smb3_query_dir_err(xid, persistent_fid, tcon->tid, tcon->ses->Suid, index, 0, rc); - cifs_stats_fail_inc(tcon, SMB2_QUERY_DIRECTORY_HE); + cifs_stats_fail_inc(tcon, SMB2_QUERY_DIRECTORY); } goto qdir_exit; } @@ -5608,7 +5608,7 @@ SMB2_set_info_init(struct cifs_tcon *tcon, struct TCP= _Server_Info *server, unsigned int i, total_len; int rc; =20 - rc =3D smb2_plain_req_init(SMB2_SET_INFO_HE, tcon, server, + rc =3D smb2_plain_req_init(SMB2_SET_INFO, tcon, server, (void **) &req, &total_len); if (rc) return rc; @@ -5704,7 +5704,7 @@ send_set_info(const unsigned int xid, struct cifs_tco= n *tcon, rsp =3D (struct smb2_set_info_rsp *)rsp_iov.iov_base; =20 if (rc !=3D 0) { - cifs_stats_fail_inc(tcon, SMB2_SET_INFO_HE); + cifs_stats_fail_inc(tcon, SMB2_SET_INFO); trace_smb3_set_info_err(xid, persistent_fid, tcon->tid, ses->Suid, info_class, (__u32)info_type, rc); } @@ -5782,7 +5782,7 @@ SMB2_oplock_break(const unsigned int xid, struct cifs= _tcon *tcon, server =3D cifs_pick_channel(ses); =20 cifs_dbg(FYI, "SMB2_oplock_break\n"); - rc =3D smb2_plain_req_init(SMB2_OPLOCK_BREAK_HE, tcon, server, + rc =3D smb2_plain_req_init(SMB2_OPLOCK_BREAK, tcon, server, (void **) &req, &total_len); if (rc) return rc; @@ -5811,7 +5811,7 @@ SMB2_oplock_break(const unsigned int xid, struct cifs= _tcon *tcon, &rqst, &resp_buf_type, flags, &rsp_iov); cifs_small_buf_release(req); if (rc) { - cifs_stats_fail_inc(tcon, SMB2_OPLOCK_BREAK_HE); + cifs_stats_fail_inc(tcon, SMB2_OPLOCK_BREAK); cifs_dbg(FYI, "Send error in Oplock Break =3D %d\n", rc); } =20 @@ -5868,7 +5868,7 @@ build_qfs_info_req(struct kvec *iov, struct cifs_tcon= *tcon, if ((tcon->ses =3D=3D NULL) || server =3D=3D NULL) return -EIO; =20 - rc =3D smb2_plain_req_init(SMB2_QUERY_INFO_HE, tcon, server, + rc =3D smb2_plain_req_init(SMB2_QUERY_INFO, tcon, server, (void **) &req, &total_len); if (rc) return rc; @@ -5935,7 +5935,7 @@ SMB311_posix_qfs_info(const unsigned int xid, struct = cifs_tcon *tcon, &rqst, &resp_buftype, flags, &rsp_iov); free_qfs_info_req(&iov); if (rc) { - cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE); + cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO); goto posix_qfsinf_exit; } rsp =3D (struct smb2_query_info_rsp *)rsp_iov.iov_base; @@ -6016,7 +6016,7 @@ SMB2_QFS_attr(const unsigned int xid, struct cifs_tco= n *tcon, &rqst, &resp_buftype, flags, &rsp_iov); free_qfs_info_req(&iov); if (rc) { - cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE); + cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO); goto qfsattr_exit; } rsp =3D (struct smb2_query_info_rsp *)rsp_iov.iov_base; @@ -6081,7 +6081,7 @@ smb2_lockv(const unsigned int xid, struct cifs_tcon *= tcon, =20 cifs_dbg(FYI, "smb2_lockv num lock %d\n", num_lock); =20 - rc =3D smb2_plain_req_init(SMB2_LOCK_HE, tcon, server, + rc =3D smb2_plain_req_init(SMB2_LOCK, tcon, server, (void **) &req, &total_len); if (rc) return rc; @@ -6117,7 +6117,7 @@ smb2_lockv(const unsigned int xid, struct cifs_tcon *= tcon, cifs_small_buf_release(req); if (rc) { cifs_dbg(FYI, "Send error in smb2_lockv =3D %d\n", rc); - cifs_stats_fail_inc(tcon, SMB2_LOCK_HE); + cifs_stats_fail_inc(tcon, SMB2_LOCK); trace_smb3_lock_err(xid, persist_fid, tcon->tid, tcon->ses->Suid, rc); } @@ -6164,7 +6164,7 @@ SMB2_lease_break(const unsigned int xid, struct cifs_= tcon *tcon, struct TCP_Server_Info *server =3D cifs_pick_channel(tcon->ses); =20 cifs_dbg(FYI, "SMB2_lease_break\n"); - rc =3D smb2_plain_req_init(SMB2_OPLOCK_BREAK_HE, tcon, server, + rc =3D smb2_plain_req_init(SMB2_OPLOCK_BREAK, tcon, server, (void **) &req, &total_len); if (rc) return rc; @@ -6195,7 +6195,7 @@ SMB2_lease_break(const unsigned int xid, struct cifs_= tcon *tcon, please_key_low =3D (__u64 *)lease_key; please_key_high =3D (__u64 *)(lease_key+8); if (rc) { - cifs_stats_fail_inc(tcon, SMB2_OPLOCK_BREAK_HE); + cifs_stats_fail_inc(tcon, SMB2_OPLOCK_BREAK); trace_smb3_lease_err(le32_to_cpu(lease_state), tcon->tid, ses->Suid, *please_key_low, *please_key_high, rc); cifs_dbg(FYI, "Send error in Lease Break =3D %d\n", rc); diff --git a/fs/smb/client/smb2transport.c b/fs/smb/client/smb2transport.c index 806ced5d0783..fcf0999e77aa 100644 --- a/fs/smb/client/smb2transport.c +++ b/fs/smb/client/smb2transport.c @@ -671,7 +671,7 @@ smb2_sign_rqst(struct smb_rqst *rqst, struct TCP_Server= _Info *server) shdr =3D (struct smb2_hdr *)rqst->rq_iov[0].iov_base; ssr =3D (struct smb2_sess_setup_req *)shdr; =20 - is_binding =3D le16_to_cpu(shdr->Command) =3D=3D SMB2_SESSION_SETUP_HE && + is_binding =3D le16_to_cpu(shdr->Command) =3D=3D SMB2_SESSION_SETUP && (ssr->Flags & SMB2_SESSION_REQ_FLAG_BINDING); is_signed =3D shdr->Flags & SMB2_FLAGS_SIGNED; =20 @@ -702,9 +702,9 @@ smb2_verify_signature(struct smb_rqst *rqst, struct TCP= _Server_Info *server) struct smb2_hdr *shdr =3D (struct smb2_hdr *)rqst->rq_iov[0].iov_base; =20 - if (le16_to_cpu(shdr->Command) =3D=3D SMB2_NEGOTIATE_HE || - le16_to_cpu(shdr->Command) =3D=3D SMB2_SESSION_SETUP_HE || - le16_to_cpu(shdr->Command) =3D=3D SMB2_OPLOCK_BREAK_HE || + if (le16_to_cpu(shdr->Command) =3D=3D SMB2_NEGOTIATE || + le16_to_cpu(shdr->Command) =3D=3D SMB2_SESSION_SETUP || + le16_to_cpu(shdr->Command) =3D=3D SMB2_OPLOCK_BREAK || server->ignore_signature || (!server->session_estab)) return 0; @@ -812,7 +812,7 @@ smb2_get_mid_entry(struct cifs_ses *ses, struct TCP_Ser= ver_Info *server, } =20 if (server->tcpStatus =3D=3D CifsNeedNegotiate && - le16_to_cpu(shdr->Command) !=3D SMB2_NEGOTIATE_HE) { + le16_to_cpu(shdr->Command) !=3D SMB2_NEGOTIATE) { spin_unlock(&server->srv_lock); return -EAGAIN; } @@ -820,8 +820,8 @@ smb2_get_mid_entry(struct cifs_ses *ses, struct TCP_Ser= ver_Info *server, =20 spin_lock(&ses->ses_lock); if (ses->ses_status =3D=3D SES_NEW) { - if (le16_to_cpu(shdr->Command) !=3D SMB2_SESSION_SETUP_HE && - le16_to_cpu(shdr->Command) !=3D SMB2_NEGOTIATE_HE) { + if (le16_to_cpu(shdr->Command) !=3D SMB2_SESSION_SETUP && + le16_to_cpu(shdr->Command) !=3D SMB2_NEGOTIATE) { spin_unlock(&ses->ses_lock); return -EAGAIN; } @@ -829,7 +829,7 @@ smb2_get_mid_entry(struct cifs_ses *ses, struct TCP_Ser= ver_Info *server, } =20 if (ses->ses_status =3D=3D SES_EXITING) { - if (le16_to_cpu(shdr->Command) !=3D SMB2_LOGOFF_HE) { + if (le16_to_cpu(shdr->Command) !=3D SMB2_LOGOFF) { spin_unlock(&ses->ses_lock); return -EAGAIN; } @@ -910,7 +910,7 @@ smb2_setup_async_request(struct TCP_Server_Info *server= , struct smb_rqst *rqst) =20 spin_lock(&server->srv_lock); if (server->tcpStatus =3D=3D CifsNeedNegotiate && - le16_to_cpu(shdr->Command) !=3D SMB2_NEGOTIATE_HE) { + le16_to_cpu(shdr->Command) !=3D SMB2_NEGOTIATE) { spin_unlock(&server->srv_lock); return ERR_PTR(-EAGAIN); } diff --git a/fs/smb/common/smb2pdu.h b/fs/smb/common/smb2pdu.h index 2f4b158518cd..7da40d229ab5 100644 --- a/fs/smb/common/smb2pdu.h +++ b/fs/smb/common/smb2pdu.h @@ -16,29 +16,29 @@ =20 /* List of commands in host endian */ enum smb2_command { - SMB2_NEGOTIATE_HE =3D 0x0000, - SMB2_SESSION_SETUP_HE =3D 0x0001, - SMB2_LOGOFF_HE =3D 0x0002, /* trivial request/resp */ - SMB2_TREE_CONNECT_HE =3D 0x0003, - SMB2_TREE_DISCONNECT_HE =3D 0x0004, /* trivial req/resp */ - SMB2_CREATE_HE =3D 0x0005, - SMB2_CLOSE_HE =3D 0x0006, - SMB2_FLUSH_HE =3D 0x0007, /* trivial resp */ - SMB2_READ_HE =3D 0x0008, - SMB2_WRITE_HE =3D 0x0009, - SMB2_LOCK_HE =3D 0x000A, - SMB2_IOCTL_HE =3D 0x000B, - SMB2_CANCEL_HE =3D 0x000C, - SMB2_ECHO_HE =3D 0x000D, - SMB2_QUERY_DIRECTORY_HE =3D 0x000E, - SMB2_CHANGE_NOTIFY_HE =3D 0x000F, - SMB2_QUERY_INFO_HE =3D 0x0010, - SMB2_SET_INFO_HE =3D 0x0011, - SMB2_OPLOCK_BREAK_HE =3D 0x0012, + SMB2_NEGOTIATE =3D 0x0000, + SMB2_SESSION_SETUP =3D 0x0001, + SMB2_LOGOFF =3D 0x0002, /* trivial request/resp */ + SMB2_TREE_CONNECT =3D 0x0003, + SMB2_TREE_DISCONNECT =3D 0x0004, /* trivial req/resp */ + SMB2_CREATE =3D 0x0005, + SMB2_CLOSE =3D 0x0006, + SMB2_FLUSH =3D 0x0007, /* trivial resp */ + SMB2_READ =3D 0x0008, + SMB2_WRITE =3D 0x0009, + SMB2_LOCK =3D 0x000A, + SMB2_IOCTL =3D 0x000B, + SMB2_CANCEL =3D 0x000C, + SMB2_ECHO =3D 0x000D, + SMB2_QUERY_DIRECTORY =3D 0x000E, + SMB2_CHANGE_NOTIFY =3D 0x000F, + SMB2_QUERY_INFO =3D 0x0010, + SMB2_SET_INFO =3D 0x0011, + SMB2_OPLOCK_BREAK =3D 0x0012, SMB2_SERVER_TO_CLIENT_NOTIFICATION =3D 0x0013 }; =20 -#define SMB2_INTERNAL_CMD_HE 0xFFFF +#define SMB2_INTERNAL_CMD 0xFFFF =20 #define NUMBER_OF_SMB2_COMMANDS 0x0013 =20 diff --git a/fs/smb/server/connection.c b/fs/smb/server/connection.c index 3f04a2977ba8..b9914c88f5c5 100644 --- a/fs/smb/server/connection.c +++ b/fs/smb/server/connection.c @@ -118,7 +118,7 @@ void ksmbd_conn_enqueue_request(struct ksmbd_work *work) struct ksmbd_conn *conn =3D work->conn; struct list_head *requests_queue =3D NULL; =20 - if (conn->ops->get_cmd_val(work) !=3D SMB2_CANCEL_HE) + if (conn->ops->get_cmd_val(work) !=3D SMB2_CANCEL) requests_queue =3D &conn->requests; =20 atomic_inc(&conn->req_running); diff --git a/fs/smb/server/oplock.c b/fs/smb/server/oplock.c index dd3c046aeae3..d99842336c62 100644 --- a/fs/smb/server/oplock.c +++ b/fs/smb/server/oplock.c @@ -642,7 +642,7 @@ static void __smb2_oplock_break_noti(struct work_struct= *wk) rsp_hdr->ProtocolId =3D SMB2_PROTO_NUMBER; rsp_hdr->StructureSize =3D SMB2_HEADER_STRUCTURE_SIZE; rsp_hdr->CreditRequest =3D cpu_to_le16(0); - rsp_hdr->Command =3D cpu_to_le16(SMB2_OPLOCK_BREAK_HE); + rsp_hdr->Command =3D cpu_to_le16(SMB2_OPLOCK_BREAK); rsp_hdr->Flags =3D (SMB2_FLAGS_SERVER_TO_REDIR); rsp_hdr->NextCommand =3D 0; rsp_hdr->MessageId =3D cpu_to_le64(-1); @@ -749,7 +749,7 @@ static void __smb2_lease_break_noti(struct work_struct = *wk) rsp_hdr->ProtocolId =3D SMB2_PROTO_NUMBER; rsp_hdr->StructureSize =3D SMB2_HEADER_STRUCTURE_SIZE; rsp_hdr->CreditRequest =3D cpu_to_le16(0); - rsp_hdr->Command =3D cpu_to_le16(SMB2_OPLOCK_BREAK_HE); + rsp_hdr->Command =3D cpu_to_le16(SMB2_OPLOCK_BREAK); rsp_hdr->Flags =3D (SMB2_FLAGS_SERVER_TO_REDIR); rsp_hdr->NextCommand =3D 0; rsp_hdr->MessageId =3D cpu_to_le64(-1); diff --git a/fs/smb/server/smb2misc.c b/fs/smb/server/smb2misc.c index 41323492f214..faa0346ca21c 100644 --- a/fs/smb/server/smb2misc.c +++ b/fs/smb/server/smb2misc.c @@ -96,17 +96,17 @@ static int smb2_get_data_area_len(unsigned int *off, un= signed int *len, * command. */ switch (le16_to_cpu(hdr->Command)) { - case SMB2_SESSION_SETUP_HE: + case SMB2_SESSION_SETUP: *off =3D le16_to_cpu(((struct smb2_sess_setup_req *)hdr)->SecurityBuffer= Offset); *len =3D le16_to_cpu(((struct smb2_sess_setup_req *)hdr)->SecurityBuffer= Length); break; - case SMB2_TREE_CONNECT_HE: + case SMB2_TREE_CONNECT: *off =3D max_t(unsigned short int, le16_to_cpu(((struct smb2_tree_connect_req *)hdr)->PathOffset), offsetof(struct smb2_tree_connect_req, Buffer)); *len =3D le16_to_cpu(((struct smb2_tree_connect_req *)hdr)->PathLength); break; - case SMB2_CREATE_HE: + case SMB2_CREATE: { unsigned short int name_off =3D max_t(unsigned short int, @@ -131,23 +131,23 @@ static int smb2_get_data_area_len(unsigned int *off, = unsigned int *len, *len =3D name_len; break; } - case SMB2_QUERY_INFO_HE: + case SMB2_QUERY_INFO: *off =3D max_t(unsigned int, le16_to_cpu(((struct smb2_query_info_req *)hdr)->InputBufferOffset= ), offsetof(struct smb2_query_info_req, Buffer)); *len =3D le32_to_cpu(((struct smb2_query_info_req *)hdr)->InputBufferLen= gth); break; - case SMB2_SET_INFO_HE: + case SMB2_SET_INFO: *off =3D max_t(unsigned int, le16_to_cpu(((struct smb2_set_info_req *)hdr)->BufferOffset), offsetof(struct smb2_set_info_req, Buffer)); *len =3D le32_to_cpu(((struct smb2_set_info_req *)hdr)->BufferLength); break; - case SMB2_READ_HE: + case SMB2_READ: *off =3D le16_to_cpu(((struct smb2_read_req *)hdr)->ReadChannelInfoOffse= t); *len =3D le16_to_cpu(((struct smb2_read_req *)hdr)->ReadChannelInfoLengt= h); break; - case SMB2_WRITE_HE: + case SMB2_WRITE: if (((struct smb2_write_req *)hdr)->DataOffset || ((struct smb2_write_req *)hdr)->Length) { *off =3D max_t(unsigned short int, @@ -160,13 +160,13 @@ static int smb2_get_data_area_len(unsigned int *off, = unsigned int *len, *off =3D le16_to_cpu(((struct smb2_write_req *)hdr)->WriteChannelInfoOff= set); *len =3D le16_to_cpu(((struct smb2_write_req *)hdr)->WriteChannelInfoLen= gth); break; - case SMB2_QUERY_DIRECTORY_HE: + case SMB2_QUERY_DIRECTORY: *off =3D max_t(unsigned short int, le16_to_cpu(((struct smb2_query_directory_req *)hdr)->FileNameOffs= et), offsetof(struct smb2_query_directory_req, Buffer)); *len =3D le16_to_cpu(((struct smb2_query_directory_req *)hdr)->FileNameL= ength); break; - case SMB2_LOCK_HE: + case SMB2_LOCK: { unsigned short lock_count; =20 @@ -177,7 +177,7 @@ static int smb2_get_data_area_len(unsigned int *off, un= signed int *len, } break; } - case SMB2_IOCTL_HE: + case SMB2_IOCTL: *off =3D max_t(unsigned int, le32_to_cpu(((struct smb2_ioctl_req *)hdr)->InputOffset), offsetof(struct smb2_ioctl_req, Buffer)); @@ -226,7 +226,7 @@ static int smb2_calc_size(void *buf, unsigned int *len) * regardless of number of locks. Subtract single * smb2_lock_element for correct buffer size check. */ - if (le16_to_cpu(hdr->Command) =3D=3D SMB2_LOCK_HE) + if (le16_to_cpu(hdr->Command) =3D=3D SMB2_LOCK) *len -=3D sizeof(struct smb2_lock_element); =20 if (has_smb2_data_area[le16_to_cpu(hdr->Command)] =3D=3D false) @@ -307,26 +307,26 @@ static int smb2_validate_credit_charge(struct ksmbd_c= onn *conn, int ret =3D 0; =20 switch (le16_to_cpu(hdr->Command)) { - case SMB2_QUERY_INFO_HE: + case SMB2_QUERY_INFO: req_len =3D smb2_query_info_req_len(__hdr); break; - case SMB2_SET_INFO_HE: + case SMB2_SET_INFO: req_len =3D smb2_set_info_req_len(__hdr); break; - case SMB2_READ_HE: + case SMB2_READ: req_len =3D smb2_read_req_len(__hdr); break; - case SMB2_WRITE_HE: + case SMB2_WRITE: req_len =3D smb2_write_req_len(__hdr); break; - case SMB2_QUERY_DIRECTORY_HE: + case SMB2_QUERY_DIRECTORY: req_len =3D smb2_query_dir_req_len(__hdr); break; - case SMB2_IOCTL_HE: + case SMB2_IOCTL: req_len =3D smb2_ioctl_req_len(__hdr); expect_resp_len =3D smb2_ioctl_resp_len(__hdr); break; - case SMB2_CANCEL_HE: + case SMB2_CANCEL: return 0; default: req_len =3D 1; @@ -401,7 +401,7 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work) } =20 if (smb2_req_struct_sizes[command] !=3D pdu->StructureSize2) { - if (!(command =3D=3D SMB2_OPLOCK_BREAK_HE && + if (!(command =3D=3D SMB2_OPLOCK_BREAK && (le16_to_cpu(pdu->StructureSize2) =3D=3D OP_BREAK_STRUCT_SIZE_20 || le16_to_cpu(pdu->StructureSize2) =3D=3D OP_BREAK_STRUCT_SIZE_21))) { /* special case for SMB2.1 lease break message */ @@ -414,7 +414,7 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work) =20 req_struct_size =3D le16_to_cpu(pdu->StructureSize2) + __SMB2_HEADER_STRUCTURE_SIZE; - if (command =3D=3D SMB2_LOCK_HE) + if (command =3D=3D SMB2_LOCK) req_struct_size -=3D sizeof(struct smb2_lock_element); =20 if (req_struct_size > len + 1) @@ -439,7 +439,7 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work) * SMB2 NEGOTIATE request will be validated when message * handling proceeds. */ - if (command =3D=3D SMB2_NEGOTIATE_HE) + if (command =3D=3D SMB2_NEGOTIATE) goto validate_credit; =20 /* @@ -469,5 +469,5 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work) =20 int smb2_negotiate_request(struct ksmbd_work *work) { - return ksmbd_smb_negotiate_common(work, SMB2_NEGOTIATE_HE); + return ksmbd_smb_negotiate_common(work, SMB2_NEGOTIATE); } diff --git a/fs/smb/server/smb2ops.c b/fs/smb/server/smb2ops.c index c9302dd71e53..a528f53b9be6 100644 --- a/fs/smb/server/smb2ops.c +++ b/fs/smb/server/smb2ops.c @@ -27,7 +27,7 @@ static struct smb_version_values smb21_server_values =3D { .header_size =3D sizeof(struct smb2_hdr), .max_header_size =3D MAX_SMB2_HDR_SIZE, .read_rsp_size =3D sizeof(struct smb2_read_rsp), - .lock_cmd =3D SMB2_LOCK_HE, + .lock_cmd =3D SMB2_LOCK, .cap_unix =3D 0, .cap_nt_find =3D SMB2_NT_FIND, .cap_large_files =3D SMB2_LARGE_FILES, @@ -53,7 +53,7 @@ static struct smb_version_values smb30_server_values =3D { .header_size =3D sizeof(struct smb2_hdr), .max_header_size =3D MAX_SMB2_HDR_SIZE, .read_rsp_size =3D sizeof(struct smb2_read_rsp), - .lock_cmd =3D SMB2_LOCK_HE, + .lock_cmd =3D SMB2_LOCK, .cap_unix =3D 0, .cap_nt_find =3D SMB2_NT_FIND, .cap_large_files =3D SMB2_LARGE_FILES, @@ -80,7 +80,7 @@ static struct smb_version_values smb302_server_values =3D= { .header_size =3D sizeof(struct smb2_hdr), .max_header_size =3D MAX_SMB2_HDR_SIZE, .read_rsp_size =3D sizeof(struct smb2_read_rsp), - .lock_cmd =3D SMB2_LOCK_HE, + .lock_cmd =3D SMB2_LOCK, .cap_unix =3D 0, .cap_nt_find =3D SMB2_NT_FIND, .cap_large_files =3D SMB2_LARGE_FILES, @@ -107,7 +107,7 @@ static struct smb_version_values smb311_server_values = =3D { .header_size =3D sizeof(struct smb2_hdr), .max_header_size =3D MAX_SMB2_HDR_SIZE, .read_rsp_size =3D sizeof(struct smb2_read_rsp), - .lock_cmd =3D SMB2_LOCK_HE, + .lock_cmd =3D SMB2_LOCK, .cap_unix =3D 0, .cap_nt_find =3D SMB2_NT_FIND, .cap_large_files =3D SMB2_LARGE_FILES, @@ -169,25 +169,25 @@ static struct smb_version_ops smb3_11_server_ops =3D { }; =20 static struct smb_version_cmds smb2_0_server_cmds[NUMBER_OF_SMB2_COMMANDS]= =3D { - [SMB2_NEGOTIATE_HE] =3D { .proc =3D smb2_negotiate_request, }, - [SMB2_SESSION_SETUP_HE] =3D { .proc =3D smb2_sess_setup, }, - [SMB2_TREE_CONNECT_HE] =3D { .proc =3D smb2_tree_connect,}, - [SMB2_TREE_DISCONNECT_HE] =3D { .proc =3D smb2_tree_disconnect,}, - [SMB2_LOGOFF_HE] =3D { .proc =3D smb2_session_logoff,}, - [SMB2_CREATE_HE] =3D { .proc =3D smb2_open}, - [SMB2_QUERY_INFO_HE] =3D { .proc =3D smb2_query_info}, - [SMB2_QUERY_DIRECTORY_HE] =3D { .proc =3D smb2_query_dir}, - [SMB2_CLOSE_HE] =3D { .proc =3D smb2_close}, - [SMB2_ECHO_HE] =3D { .proc =3D smb2_echo}, - [SMB2_SET_INFO_HE] =3D { .proc =3D smb2_set_info}, - [SMB2_READ_HE] =3D { .proc =3D smb2_read}, - [SMB2_WRITE_HE] =3D { .proc =3D smb2_write}, - [SMB2_FLUSH_HE] =3D { .proc =3D smb2_flush}, - [SMB2_CANCEL_HE] =3D { .proc =3D smb2_cancel}, - [SMB2_LOCK_HE] =3D { .proc =3D smb2_lock}, - [SMB2_IOCTL_HE] =3D { .proc =3D smb2_ioctl}, - [SMB2_OPLOCK_BREAK_HE] =3D { .proc =3D smb2_oplock_break}, - [SMB2_CHANGE_NOTIFY_HE] =3D { .proc =3D smb2_notify}, + [SMB2_NEGOTIATE] =3D { .proc =3D smb2_negotiate_request, }, + [SMB2_SESSION_SETUP] =3D { .proc =3D smb2_sess_setup, }, + [SMB2_TREE_CONNECT] =3D { .proc =3D smb2_tree_connect,}, + [SMB2_TREE_DISCONNECT] =3D { .proc =3D smb2_tree_disconnect,}, + [SMB2_LOGOFF] =3D { .proc =3D smb2_session_logoff,}, + [SMB2_CREATE] =3D { .proc =3D smb2_open}, + [SMB2_QUERY_INFO] =3D { .proc =3D smb2_query_info}, + [SMB2_QUERY_DIRECTORY] =3D { .proc =3D smb2_query_dir}, + [SMB2_CLOSE] =3D { .proc =3D smb2_close}, + [SMB2_ECHO] =3D { .proc =3D smb2_echo}, + [SMB2_SET_INFO] =3D { .proc =3D smb2_set_info}, + [SMB2_READ] =3D { .proc =3D smb2_read}, + [SMB2_WRITE] =3D { .proc =3D smb2_write}, + [SMB2_FLUSH] =3D { .proc =3D smb2_flush}, + [SMB2_CANCEL] =3D { .proc =3D smb2_cancel}, + [SMB2_LOCK] =3D { .proc =3D smb2_lock}, + [SMB2_IOCTL] =3D { .proc =3D smb2_ioctl}, + [SMB2_OPLOCK_BREAK] =3D { .proc =3D smb2_oplock_break}, + [SMB2_CHANGE_NOTIFY] =3D { .proc =3D smb2_notify}, }; =20 /** diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c index 74749c60d9f6..1ed2bcba649f 100644 --- a/fs/smb/server/smb2pdu.c +++ b/fs/smb/server/smb2pdu.c @@ -94,9 +94,9 @@ int smb2_get_ksmbd_tcon(struct ksmbd_work *work) unsigned int cmd =3D le16_to_cpu(req_hdr->Command); unsigned int tree_id; =20 - if (cmd =3D=3D SMB2_TREE_CONNECT_HE || - cmd =3D=3D SMB2_CANCEL_HE || - cmd =3D=3D SMB2_LOGOFF_HE) { + if (cmd =3D=3D SMB2_TREE_CONNECT || + cmd =3D=3D SMB2_CANCEL || + cmd =3D=3D SMB2_LOGOFF) { ksmbd_debug(SMB, "skip to check tree connect request\n"); return 0; } @@ -181,7 +181,7 @@ bool is_smb2_neg_cmd(struct ksmbd_work *work) if (hdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR) return false; =20 - if (le16_to_cpu(hdr->Command) !=3D SMB2_NEGOTIATE_HE) + if (le16_to_cpu(hdr->Command) !=3D SMB2_NEGOTIATE) return false; =20 return true; @@ -262,7 +262,7 @@ int init_smb2_neg_rsp(struct ksmbd_work *work) rsp_hdr->ProtocolId =3D SMB2_PROTO_NUMBER; rsp_hdr->StructureSize =3D SMB2_HEADER_STRUCTURE_SIZE; rsp_hdr->CreditRequest =3D cpu_to_le16(2); - rsp_hdr->Command =3D cpu_to_le16(SMB2_NEGOTIATE_HE); + rsp_hdr->Command =3D cpu_to_le16(SMB2_NEGOTIATE); rsp_hdr->Flags =3D (SMB2_FLAGS_SERVER_TO_REDIR); rsp_hdr->NextCommand =3D 0; rsp_hdr->MessageId =3D 0; @@ -349,7 +349,7 @@ int smb2_set_rsp_credits(struct ksmbd_work *work) * TODO: Need to adjuct CreditRequest value according to * current cpu load */ - if (le16_to_cpu(hdr->Command) =3D=3D SMB2_NEGOTIATE_HE) + if (le16_to_cpu(hdr->Command) =3D=3D SMB2_NEGOTIATE) aux_max =3D 1; else aux_max =3D conn->vals->max_credits - conn->total_credits; @@ -389,7 +389,7 @@ static void init_chained_smb2_rsp(struct ksmbd_work *wo= rk) /* Storing the current local FID which may be needed by subsequent * command in the compound request */ - if (req->Command =3D=3D cpu_to_le16(SMB2_CREATE_HE) && rsp->Status =3D=3D= STATUS_SUCCESS) { + if (req->Command =3D=3D cpu_to_le16(SMB2_CREATE) && rsp->Status =3D=3D ST= ATUS_SUCCESS) { work->compound_fid =3D ((struct smb2_create_rsp *)rsp)->VolatileFileId; work->compound_pfid =3D ((struct smb2_create_rsp *)rsp)->PersistentFileI= d; work->compound_sid =3D le64_to_cpu(rsp->SessionId); @@ -532,10 +532,10 @@ int smb2_allocate_rsp_buf(struct ksmbd_work *work) size_t sz =3D small_sz; int cmd =3D le16_to_cpu(hdr->Command); =20 - if (cmd =3D=3D SMB2_IOCTL_HE || cmd =3D=3D SMB2_QUERY_DIRECTORY_HE) + if (cmd =3D=3D SMB2_IOCTL || cmd =3D=3D SMB2_QUERY_DIRECTORY) sz =3D large_sz; =20 - if (cmd =3D=3D SMB2_QUERY_INFO_HE) { + if (cmd =3D=3D SMB2_QUERY_INFO) { struct smb2_query_info_req *req; =20 if (get_rfc1002_len(work->request_buf) < @@ -580,8 +580,8 @@ int smb2_check_user_session(struct ksmbd_work *work) * require a session id, so no need to validate user session's for * these commands. */ - if (cmd =3D=3D SMB2_ECHO_HE || cmd =3D=3D SMB2_NEGOTIATE_HE || - cmd =3D=3D SMB2_SESSION_SETUP_HE) + if (cmd =3D=3D SMB2_ECHO || cmd =3D=3D SMB2_NEGOTIATE || + cmd =3D=3D SMB2_SESSION_SETUP) return 0; =20 if (!ksmbd_conn_good(conn)) @@ -8819,9 +8819,9 @@ bool smb2_is_sign_req(struct ksmbd_work *work, unsign= ed int command) struct smb2_hdr *rcv_hdr2 =3D smb2_get_msg(work->request_buf); =20 if ((rcv_hdr2->Flags & SMB2_FLAGS_SIGNED) && - command !=3D SMB2_NEGOTIATE_HE && - command !=3D SMB2_SESSION_SETUP_HE && - command !=3D SMB2_OPLOCK_BREAK_HE) + command !=3D SMB2_NEGOTIATE && + command !=3D SMB2_SESSION_SETUP && + command !=3D SMB2_OPLOCK_BREAK) return true; =20 return false; @@ -8887,7 +8887,7 @@ void smb2_set_sign_rsp(struct ksmbd_work *work) hdr->Flags |=3D SMB2_FLAGS_SIGNED; memset(hdr->Signature, 0, SMB2_SIGNATURE_SIZE); =20 - if (hdr->Command =3D=3D cpu_to_le16(SMB2_READ_HE)) { + if (hdr->Command =3D=3D cpu_to_le16(SMB2_READ)) { iov =3D &work->iov[work->iov_idx - 1]; n_vec++; } else { @@ -8928,7 +8928,7 @@ int smb3_check_sign_req(struct ksmbd_work *work) len =3D get_rfc1002_len(work->request_buf) - work->next_smb2_rcv_hdr_off; =20 - if (le16_to_cpu(hdr->Command) =3D=3D SMB2_SESSION_SETUP_HE) { + if (le16_to_cpu(hdr->Command) =3D=3D SMB2_SESSION_SETUP) { signing_key =3D work->sess->smb3signingkey; } else { chann =3D lookup_chann_list(work->sess, conn); @@ -8977,7 +8977,7 @@ void smb3_set_sign_rsp(struct ksmbd_work *work) hdr =3D ksmbd_resp_buf_curr(work); =20 if (conn->binding =3D=3D false && - le16_to_cpu(hdr->Command) =3D=3D SMB2_SESSION_SETUP_HE) { + le16_to_cpu(hdr->Command) =3D=3D SMB2_SESSION_SETUP) { signing_key =3D work->sess->smb3signingkey; } else { chann =3D lookup_chann_list(work->sess, work->conn); @@ -8993,7 +8993,7 @@ void smb3_set_sign_rsp(struct ksmbd_work *work) hdr->Flags |=3D SMB2_FLAGS_SIGNED; memset(hdr->Signature, 0, SMB2_SIGNATURE_SIZE); =20 - if (hdr->Command =3D=3D cpu_to_le16(SMB2_READ_HE)) { + if (hdr->Command =3D=3D cpu_to_le16(SMB2_READ)) { iov =3D &work->iov[work->iov_idx - 1]; n_vec++; } else { @@ -9021,12 +9021,12 @@ void smb3_preauth_hash_rsp(struct ksmbd_work *work) =20 WORK_BUFFERS(work, req, rsp); =20 - if (le16_to_cpu(req->Command) =3D=3D SMB2_NEGOTIATE_HE && + if (le16_to_cpu(req->Command) =3D=3D SMB2_NEGOTIATE && conn->preauth_info) ksmbd_gen_preauth_integrity_hash(conn, work->response_buf, conn->preauth_info->Preauth_HashValue); =20 - if (le16_to_cpu(rsp->Command) =3D=3D SMB2_SESSION_SETUP_HE && sess) { + if (le16_to_cpu(rsp->Command) =3D=3D SMB2_SESSION_SETUP && sess) { __u8 *hash_value; =20 if (conn->binding) { @@ -9149,7 +9149,7 @@ bool smb3_11_final_sess_setup_resp(struct ksmbd_work = *work) if (work->next_smb2_rcv_hdr_off) rsp =3D ksmbd_resp_buf_next(work); =20 - if (le16_to_cpu(rsp->Command) =3D=3D SMB2_SESSION_SETUP_HE && + if (le16_to_cpu(rsp->Command) =3D=3D SMB2_SESSION_SETUP && sess->user && !user_guest(sess->user) && rsp->Status =3D=3D STATUS_SUCCESS) return true; diff --git a/fs/smb/server/smb_common.c b/fs/smb/server/smb_common.c index 425c756bcfb8..0e6250483776 100644 --- a/fs/smb/server/smb_common.c +++ b/fs/smb/server/smb_common.c @@ -596,7 +596,7 @@ int ksmbd_smb_negotiate_common(struct ksmbd_work *work,= unsigned int command) ksmbd_negotiate_smb_dialect(work->request_buf); ksmbd_debug(SMB, "conn->dialect 0x%x\n", conn->dialect); =20 - if (command =3D=3D SMB2_NEGOTIATE_HE) { + if (command =3D=3D SMB2_NEGOTIATE) { ret =3D smb2_handle_negotiate(work); return ret; } From nobody Thu Dec 18 03:20:29 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 470702BCF4A for ; Wed, 6 Aug 2025 20:38:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512696; cv=none; b=ISI80pqONYfl0wLIGUiTxl+ff/4VAqaR70aORdodfKRKqs4ItRypwyP8IAc20Enotl8r956XTuo11o6GBmhuJ4wB6ZHMGtvORzoqJdnGyQGdCfYjMEte85s8nB7HUajsa1qbZurek73LV8NxP8Sg1EbcwjgcyKsnruzS+S8tBoU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512696; c=relaxed/simple; bh=o2Se6X7f1I01126JVjWyB6Ukzkb1OmFmO1QzSoGtdIM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=gqDGwcMKZBbTg3Fhj62WPWzjCs3IKVhQRSf+TgWBcFy6mEFITP7ZiJN0ykDrtFPkjpPBkHPKYqsXnI0y55HCOctGGqDVwIII4B+FEj2Es3JP66K4+X3MMf2Tf5PLM/gQI4vtzRvoiANQtgHs/YERe0REZ+qTdJ6ildua9RMcnvQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=YRZ7TgYK; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="YRZ7TgYK" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1754512690; h=from:from:reply-to:subject:subject: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=G64e6jt2CdnkmDsoSf/wfbRhPuprMwqhhJmLQ88f750=; b=YRZ7TgYKS6M8ICm32k0VsmFkcX9b1+mQVvM090/sXzbrrQ8ENAxwtiYVU44oCurGgwiaou HhK1G+sBPGddRWEQQezk+4j6vgl+xoKNDWDsdAjDIIlMSI67vZcPyLk46NEfBv/SvG9ubw CWe2OPb8jGT2Q2P6k6XVMPoaRKEQV4s= Received: from mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-157-WKmTYZv0PRe2M0ZyhtLarQ-1; Wed, 06 Aug 2025 16:38:06 -0400 X-MC-Unique: WKmTYZv0PRe2M0ZyhtLarQ-1 X-Mimecast-MFC-AGG-ID: WKmTYZv0PRe2M0ZyhtLarQ_1754512685 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 154091955F3C; Wed, 6 Aug 2025 20:38:05 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.17]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 81FF51956086; Wed, 6 Aug 2025 20:38:00 +0000 (UTC) From: David Howells To: Steve French Cc: David Howells , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Wang Zhaolong , Stefan Metzmacher , Mina Almasry , linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org, netfs@lists.linux.dev, linux-fsdevel@vger.kernel.org Subject: [RFC PATCH 10/31] cifs: Make smb1's SendReceive() wrap cifs_send_recv() Date: Wed, 6 Aug 2025 21:36:31 +0100 Message-ID: <20250806203705.2560493-11-dhowells@redhat.com> In-Reply-To: <20250806203705.2560493-1-dhowells@redhat.com> References: <20250806203705.2560493-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Content-Type: text/plain; charset="utf-8" Make the smb1 transport's SendReceive() simply wrap cifs_send_recv() as does SendReceive2(). This will then allow that to pick up the transport changes there. Signed-off-by: David Howells cc: Steve French cc: Paulo Alcantara cc: Shyam Prasad N cc: Tom Talpey cc: linux-cifs@vger.kernel.org cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/smb/client/cifstransport.c | 85 +++++------------------------------ 1 file changed, 11 insertions(+), 74 deletions(-) diff --git a/fs/smb/client/cifstransport.c b/fs/smb/client/cifstransport.c index a3400a757968..f7fed73bc508 100644 --- a/fs/smb/client/cifstransport.c +++ b/fs/smb/client/cifstransport.c @@ -270,13 +270,13 @@ SendReceive(const unsigned int xid, struct cifs_ses *= ses, struct smb_hdr *in_buf, struct smb_hdr *out_buf, int *pbytes_returned, const int flags) { - int rc =3D 0; - struct smb_message *smb; unsigned int len =3D be32_to_cpu(in_buf->smb_buf_length); + struct TCP_Server_Info *server; + struct kvec resp_iov =3D {}; struct kvec iov =3D { .iov_base =3D in_buf, .iov_len =3D len }; struct smb_rqst rqst =3D { .rq_iov =3D &iov, .rq_nvec =3D 1 }; - struct cifs_credits credits =3D { .value =3D 1, .instance =3D 0 }; - struct TCP_Server_Info *server; + int resp_buf_type; + int rc =3D 0; =20 if (ses =3D=3D NULL) { cifs_dbg(VFS, "Null smb session\n"); @@ -305,78 +305,15 @@ SendReceive(const unsigned int xid, struct cifs_ses *= ses, return -EIO; } =20 - rc =3D wait_for_free_request(server, flags, &credits.instance); - if (rc) - return rc; - - /* make sure that we sign in the same order that we send on this socket - and avoid races inside tcp sendmsg code that could cause corruption - of smb data */ - - cifs_server_lock(server); - - rc =3D allocate_mid(ses, in_buf, &smb); - if (rc) { - cifs_server_unlock(server); - /* Update # of requests on wire to server */ - add_credits(server, &credits, 0); - return rc; - } - - rc =3D cifs_sign_smb(in_buf, server, &smb->sequence_number); - if (rc) { - cifs_server_unlock(server); - goto out; - } - - smb->mid_state =3D MID_REQUEST_SUBMITTED; - - rc =3D smb_send(server, in_buf, len); - cifs_save_when_sent(smb); - - if (rc < 0) - server->sequence_number -=3D 2; - - cifs_server_unlock(server); - + rc =3D cifs_send_recv(xid, ses, ses->server, + &rqst, &resp_buf_type, flags, &resp_iov); if (rc < 0) - goto out; - - rc =3D wait_for_response(server, smb); - if (rc !=3D 0) { - send_cancel(server, &rqst, smb); - spin_lock(&server->mid_lock); - if (smb->mid_state =3D=3D MID_REQUEST_SUBMITTED || - smb->mid_state =3D=3D MID_RESPONSE_RECEIVED) { - /* no longer considered to be "in-flight" */ - smb->callback =3D release_mid; - spin_unlock(&server->mid_lock); - add_credits(server, &credits, 0); - return rc; - } - spin_unlock(&server->mid_lock); - } - - rc =3D cifs_sync_mid_result(smb, server); - if (rc !=3D 0) { - add_credits(server, &credits, 0); return rc; - } - - if (!smb->resp_buf || !out_buf || - smb->mid_state !=3D MID_RESPONSE_READY) { - rc =3D -EIO; - cifs_server_dbg(VFS, "Bad MID state?\n"); - goto out; - } - - *pbytes_returned =3D get_rfc1002_length(smb->resp_buf); - memcpy(out_buf, smb->resp_buf, *pbytes_returned + 4); - rc =3D cifs_check_receive(smb, server, 0); -out: - delete_mid(smb); - add_credits(server, &credits, 0); - +=09 + *pbytes_returned =3D resp_iov.iov_len; + if (resp_iov.iov_len) + memcpy(out_buf, resp_iov.iov_base, resp_iov.iov_len); + free_rsp_buf(resp_buf_type, resp_iov.iov_base); return rc; } From nobody Thu Dec 18 03:20:29 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E518B220696 for ; Wed, 6 Aug 2025 20:38:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512698; cv=none; b=AoFn7PV2jXNpsJiJ8aTGMWAQqOwKwi6yO27Qk5AtzFdGqHbGnYHg0nS6sNIBjPKflSNXuKtNQOJbTs9M4wSGvpj6FxHLov63QI4ojwfNOfHAgbsiEPLDyJjkhp0Sq7LqgBZVc4ZxEfqQqyaifIFSAuZXNEEBRDPHxOXTKnnUlmg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512698; c=relaxed/simple; bh=gDaXEXJDUMkLWSrJWjx1ltg2Wa9lzByBdJ1ftNaDH3I=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=b0benYVQVFnaBMsEVPWho5PetA6xCloqbkdmDrNT1XFFXx3HLkjkboxXj6YqtkBy2qORVXZ7gO9/dHvJCqUtVAGsdBjPR4AewGkwAuY5UKwm9P+a4BVmAS0s1pULgyAdCB12vdxUj2vOHCCSQA1tYpFUHi1Zm0aLF+KWpLcg3uk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=XVXe7lFp; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="XVXe7lFp" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1754512695; h=from:from:reply-to:subject:subject: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=AZxxbXT3Ta/qf75DsVMKh90isbtBz2lEPc6Xx8XIGa0=; b=XVXe7lFpLy+iqruVPp0262pPDOEf8gyltymIPUMkbxmWvVeauUxRYnGZsIBNUFwK8yeuG8 75+eRKqb6RWVSFtWd4QT1FSmldtbNMhuEGMUrFTGguafeNfL53pFk+Qyd/4EH4HCQC0OAc 2L1XoqohI4TIGLLWVJG2Fp6SK4wfuIg= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-534-LYiIFpnuNyW4ZXlySuoW7Q-1; Wed, 06 Aug 2025 16:38:11 -0400 X-MC-Unique: LYiIFpnuNyW4ZXlySuoW7Q-1 X-Mimecast-MFC-AGG-ID: LYiIFpnuNyW4ZXlySuoW7Q_1754512689 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id B4D001955E95; Wed, 6 Aug 2025 20:38:09 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.17]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id A7C8D180035C; Wed, 6 Aug 2025 20:38:06 +0000 (UTC) From: David Howells To: Steve French Cc: David Howells , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Wang Zhaolong , Stefan Metzmacher , Mina Almasry , linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org, netfs@lists.linux.dev, linux-fsdevel@vger.kernel.org Subject: [RFC PATCH 11/31] cifs: Fix SMB1 to not require separate kvec for the rfc1002 header Date: Wed, 6 Aug 2025 21:36:32 +0100 Message-ID: <20250806203705.2560493-12-dhowells@redhat.com> In-Reply-To: <20250806203705.2560493-1-dhowells@redhat.com> References: <20250806203705.2560493-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Content-Type: text/plain; charset="utf-8" Fix SMB1 to not require separate kvec for the rfc1002 header, which seems to be something intended to make the signing algorithm simpler, but at the expense of additional complexity everywhere else. Signed-off-by: David Howells cc: Steve French cc: Paulo Alcantara cc: Shyam Prasad N cc: Tom Talpey cc: linux-cifs@vger.kernel.org cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/smb/client/cifsencrypt.c | 77 +++++++-------------------------- fs/smb/client/cifsproto.h | 5 --- fs/smb/client/cifssmb.c | 28 ++++++------ fs/smb/client/cifstransport.c | 81 +++++++---------------------------- fs/smb/client/smb1ops.c | 11 +++-- fs/smb/client/transport.c | 27 ++++++------ 6 files changed, 65 insertions(+), 164 deletions(-) diff --git a/fs/smb/client/cifsencrypt.c b/fs/smb/client/cifsencrypt.c index 35892df7335c..a1f17604b4c6 100644 --- a/fs/smb/client/cifsencrypt.c +++ b/fs/smb/client/cifsencrypt.c @@ -58,38 +58,25 @@ int __cifs_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server, char *signature, struct shash_desc *shash) { - int i; + struct iov_iter iter; ssize_t rc; - struct kvec *iov =3D rqst->rq_iov; - int n_vec =3D rqst->rq_nvec; - - /* iov[0] is actual data and not the rfc1002 length for SMB2+ */ - if (!is_smb1(server)) { - if (iov[0].iov_len <=3D 4) - return -EIO; - i =3D 0; - } else { - if (n_vec < 2 || iov[0].iov_len !=3D 4) - return -EIO; - i =3D 1; /* skip rfc1002 length */ - } + size_t size =3D 0; =20 - for (; i < n_vec; i++) { - if (iov[i].iov_len =3D=3D 0) - continue; - if (iov[i].iov_base =3D=3D NULL) { - cifs_dbg(VFS, "null iovec entry\n"); - return -EIO; - } + for (int i =3D 0; i < rqst->rq_nvec; i++) + size +=3D rqst->rq_iov[i].iov_len; =20 - rc =3D crypto_shash_update(shash, - iov[i].iov_base, iov[i].iov_len); - if (rc) { - cifs_dbg(VFS, "%s: Could not update with payload\n", - __func__); - return rc; - } - } + iov_iter_kvec(&iter, ITER_SOURCE, rqst->rq_iov, rqst->rq_nvec, size); + + /* Skip the rfc1002 length for SMB1 */ + if (is_smb1(server)) + iov_iter_advance(&iter, 4); + + if (iov_iter_count(&iter) <=3D 4) + return -EIO; + + rc =3D cifs_shash_iter(&iter, iov_iter_count(&iter), shash); + if (rc < 0) + return rc; =20 rc =3D cifs_shash_iter(&rqst->rq_iter, iov_iter_count(&rqst->rq_iter), sh= ash); if (rc < 0) @@ -145,10 +132,6 @@ int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_S= erver_Info *server, char smb_signature[20]; struct smb_hdr *cifs_pdu =3D (struct smb_hdr *)rqst->rq_iov[0].iov_base; =20 - if (rqst->rq_iov[0].iov_len !=3D 4 || - rqst->rq_iov[0].iov_base + 4 !=3D rqst->rq_iov[1].iov_base) - return -EIO; - if ((cifs_pdu =3D=3D NULL) || (server =3D=3D NULL)) return -EINVAL; =20 @@ -181,30 +164,6 @@ int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_S= erver_Info *server, return rc; } =20 -int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *se= rver, - __u32 *pexpected_response_sequence) -{ - struct smb_rqst rqst =3D { .rq_iov =3D iov, - .rq_nvec =3D n_vec }; - - return cifs_sign_rqst(&rqst, server, pexpected_response_sequence); -} - -/* must be called with server->srv_mutex held */ -int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server, - __u32 *pexpected_response_sequence_number) -{ - struct kvec iov[2]; - - iov[0].iov_base =3D cifs_pdu; - iov[0].iov_len =3D 4; - iov[1].iov_base =3D (char *)cifs_pdu + 4; - iov[1].iov_len =3D be32_to_cpu(cifs_pdu->smb_buf_length); - - return cifs_sign_smbv(iov, 2, server, - pexpected_response_sequence_number); -} - int cifs_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server, __u32 expected_sequence_number) @@ -214,10 +173,6 @@ int cifs_verify_signature(struct smb_rqst *rqst, char what_we_think_sig_should_be[20]; struct smb_hdr *cifs_pdu =3D (struct smb_hdr *)rqst->rq_iov[0].iov_base; =20 - if (rqst->rq_iov[0].iov_len !=3D 4 || - rqst->rq_iov[0].iov_base + 4 !=3D rqst->rq_iov[1].iov_base) - return -EIO; - if (cifs_pdu =3D=3D NULL || server =3D=3D NULL) return -EINVAL; =20 diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h index 1126feb4ba5f..2b89469187d8 100644 --- a/fs/smb/client/cifsproto.h +++ b/fs/smb/client/cifsproto.h @@ -29,8 +29,6 @@ extern void cifs_buf_release(void *); extern struct smb_hdr *cifs_small_buf_get(void); extern void cifs_small_buf_release(void *); extern void free_rsp_buf(int, void *); -extern int smb_send(struct TCP_Server_Info *, struct smb_hdr *, - unsigned int /* length */); extern int smb_send_kvec(struct TCP_Server_Info *server, struct msghdr *msg, size_t *sent); @@ -556,9 +554,6 @@ extern void tconInfoFree(struct cifs_tcon *tcon, enum s= mb3_tcon_ref_trace trace) =20 extern int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *s= erver, __u32 *pexpected_response_sequence_number); -extern int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_I= nfo *, - __u32 *); -extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *, __u32= *); extern int cifs_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server, __u32 expected_sequence_number); diff --git a/fs/smb/client/cifssmb.c b/fs/smb/client/cifssmb.c index 879fa0ad6e44..66d8e2ad8cde 100644 --- a/fs/smb/client/cifssmb.c +++ b/fs/smb/client/cifssmb.c @@ -591,9 +591,11 @@ CIFSSMBEcho(struct TCP_Server_Info *server) { ECHO_REQ *smb; int rc =3D 0; - struct kvec iov[2]; - struct smb_rqst rqst =3D { .rq_iov =3D iov, - .rq_nvec =3D 2 }; + struct kvec iov[1]; + struct smb_rqst rqst =3D { + .rq_iov =3D iov, + .rq_nvec =3D ARRAY_SIZE(iov), + }; =20 cifs_dbg(FYI, "In echo request\n"); =20 @@ -612,10 +614,8 @@ CIFSSMBEcho(struct TCP_Server_Info *server) smb->Data[0] =3D 'a'; inc_rfc1001_len(smb, 3); =20 - iov[0].iov_len =3D 4; + iov[0].iov_len =3D 4 + get_rfc1002_length(smb); iov[0].iov_base =3D smb; - iov[1].iov_len =3D get_rfc1002_length(smb); - iov[1].iov_base =3D (char *)smb + 4; =20 rc =3D cifs_call_async(server, &rqst, NULL, cifs_echo_callback, NULL, server, CIFS_NON_BLOCKING | CIFS_ECHO_OP, NULL); @@ -1392,7 +1392,7 @@ cifs_async_readv(struct cifs_io_subrequest *rdata) int wct; struct cifs_tcon *tcon =3D tlink_tcon(rdata->req->cfile->tlink); struct smb_rqst rqst =3D { .rq_iov =3D rdata->iov, - .rq_nvec =3D 2 }; + .rq_nvec =3D 1 }; =20 cifs_dbg(FYI, "%s: offset=3D%llu bytes=3D%zu\n", __func__, rdata->subreq.start, rdata->subreq.len); @@ -1433,9 +1433,7 @@ cifs_async_readv(struct cifs_io_subrequest *rdata) =20 /* 4 for RFC1001 length + 1 for BCC */ rdata->iov[0].iov_base =3D smb; - rdata->iov[0].iov_len =3D 4; - rdata->iov[1].iov_base =3D (char *)smb + 4; - rdata->iov[1].iov_len =3D get_rfc1002_length(smb); + rdata->iov[0].iov_len =3D 4 + get_rfc1002_length(smb); =20 rc =3D cifs_call_async(tcon->ses->server, &rqst, cifs_readv_receive, cifs_readv_callback, NULL, rdata, 0, NULL); @@ -1764,7 +1762,7 @@ cifs_async_writev(struct cifs_io_subrequest *wdata) WRITE_REQ *req =3D NULL; int wct; struct cifs_tcon *tcon =3D tlink_tcon(wdata->req->cfile->tlink); - struct kvec iov[2]; + struct kvec iov[1]; struct smb_rqst rqst =3D { }; =20 if (tcon->ses->capabilities & CAP_LARGE_FILES) { @@ -1798,13 +1796,11 @@ cifs_async_writev(struct cifs_io_subrequest *wdata) cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4); =20 /* 4 for RFC1001 length + 1 for BCC */ - iov[0].iov_len =3D 4; iov[0].iov_base =3D req; - iov[1].iov_len =3D get_rfc1002_length(req) + 1; - iov[1].iov_base =3D (char *)req + 4; + iov[0].iov_len =3D 4 + get_rfc1002_length(req) + 1; =20 rqst.rq_iov =3D iov; - rqst.rq_nvec =3D 2; + rqst.rq_nvec =3D 1; rqst.rq_iter =3D wdata->subreq.io_iter; =20 cifs_dbg(FYI, "async write at %llu %zu bytes\n", @@ -1822,7 +1818,7 @@ cifs_async_writev(struct cifs_io_subrequest *wdata) (struct smb_com_writex_req *)req; inc_rfc1001_len(&reqw->hdr, wdata->subreq.len + 5); put_bcc(wdata->subreq.len + 5, &reqw->hdr); - iov[1].iov_len +=3D 4; /* pad bigger by four bytes */ + iov[0].iov_len +=3D 4; /* pad bigger by four bytes */ } =20 rc =3D cifs_call_async(tcon->ses->server, &rqst, NULL, diff --git a/fs/smb/client/cifstransport.c b/fs/smb/client/cifstransport.c index f7fed73bc508..e5b75d9b9281 100644 --- a/fs/smb/client/cifstransport.c +++ b/fs/smb/client/cifstransport.c @@ -69,22 +69,6 @@ alloc_mid(const struct smb_hdr *smb_buffer, struct TCP_S= erver_Info *server) return smb; } =20 -int -smb_send(struct TCP_Server_Info *server, struct smb_hdr *smb_buffer, - unsigned int smb_buf_length) -{ - struct kvec iov[2]; - struct smb_rqst rqst =3D { .rq_iov =3D iov, - .rq_nvec =3D 2 }; - - iov[0].iov_base =3D smb_buffer; - iov[0].iov_len =3D 4; - iov[1].iov_base =3D (char *)smb_buffer + 4; - iov[1].iov_len =3D smb_buf_length; - - return __smb_send_rqst(server, 1, &rqst); -} - static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf, struct smb_message **ppmidQ) { @@ -124,10 +108,6 @@ cifs_setup_async_request(struct TCP_Server_Info *serve= r, struct smb_rqst *rqst) struct smb_hdr *hdr =3D (struct smb_hdr *)rqst->rq_iov[0].iov_base; struct smb_message *smb; =20 - if (rqst->rq_iov[0].iov_len !=3D 4 || - rqst->rq_iov[0].iov_base + 4 !=3D rqst->rq_iov[1].iov_base) - return ERR_PTR(-EIO); - /* enable signing if server requires it */ if (server->sign) hdr->Flags2 |=3D SMBFLG2_SECURITY_SIGNATURE; @@ -176,21 +156,19 @@ int cifs_check_receive(struct smb_message *smb, struct TCP_Server_Info *server, bool log_error) { - unsigned int len =3D get_rfc1002_length(smb->resp_buf) + 4; + unsigned int len =3D get_rfc1002_length(smb->resp_buf); =20 dump_smb(smb->resp_buf, min_t(u32, 92, len)); =20 /* convert the length into a more usable form */ if (server->sign) { - struct kvec iov[2]; + struct kvec iov[1]; int rc =3D 0; struct smb_rqst rqst =3D { .rq_iov =3D iov, - .rq_nvec =3D 2 }; + .rq_nvec =3D 1 }; =20 iov[0].iov_base =3D smb->resp_buf; - iov[0].iov_len =3D 4; - iov[1].iov_base =3D (char *)smb->resp_buf + 4; - iov[1].iov_len =3D len - 4; + iov[0].iov_len =3D len; /* FIXME: add code to kill session */ rc =3D cifs_verify_signature(&rqst, server, smb->sequence_number); @@ -211,10 +189,6 @@ cifs_setup_request(struct cifs_ses *ses, struct TCP_Se= rver_Info *ignored, struct smb_hdr *hdr =3D (struct smb_hdr *)rqst->rq_iov[0].iov_base; struct smb_message *smb; =20 - if (rqst->rq_iov[0].iov_len !=3D 4 || - rqst->rq_iov[0].iov_base + 4 !=3D rqst->rq_iov[1].iov_base) - return ERR_PTR(-EIO); - rc =3D allocate_mid(ses, hdr, &smb); if (rc) return ERR_PTR(rc); @@ -231,38 +205,13 @@ SendReceive2(const unsigned int xid, struct cifs_ses = *ses, struct kvec *iov, int n_vec, int *resp_buf_type /* ret */, const int flags, struct kvec *resp_iov) { - struct smb_rqst rqst; - struct kvec s_iov[CIFS_MAX_IOV_SIZE], *new_iov; - int rc; + struct smb_rqst rqst =3D { + .rq_iov =3D iov, + .rq_nvec =3D n_vec, + }; =20 - if (n_vec + 1 > CIFS_MAX_IOV_SIZE) { - new_iov =3D kmalloc_array(n_vec + 1, sizeof(struct kvec), - GFP_KERNEL); - if (!new_iov) { - /* otherwise cifs_send_recv below sets resp_buf_type */ - *resp_buf_type =3D CIFS_NO_BUFFER; - return -ENOMEM; - } - } else - new_iov =3D s_iov; - - /* 1st iov is a RFC1001 length followed by the rest of the packet */ - memcpy(new_iov + 1, iov, (sizeof(struct kvec) * n_vec)); - - new_iov[0].iov_base =3D new_iov[1].iov_base; - new_iov[0].iov_len =3D 4; - new_iov[1].iov_base +=3D 4; - new_iov[1].iov_len -=3D 4; - - memset(&rqst, 0, sizeof(struct smb_rqst)); - rqst.rq_iov =3D new_iov; - rqst.rq_nvec =3D n_vec + 1; - - rc =3D cifs_send_recv(xid, ses, ses->server, - &rqst, resp_buf_type, flags, resp_iov); - if (n_vec + 1 > CIFS_MAX_IOV_SIZE) - kfree(new_iov); - return rc; + return cifs_send_recv(xid, ses, ses->server, + &rqst, resp_buf_type, flags, resp_iov); } =20 int @@ -273,7 +222,7 @@ SendReceive(const unsigned int xid, struct cifs_ses *se= s, unsigned int len =3D be32_to_cpu(in_buf->smb_buf_length); struct TCP_Server_Info *server; struct kvec resp_iov =3D {}; - struct kvec iov =3D { .iov_base =3D in_buf, .iov_len =3D len }; + struct kvec iov =3D { .iov_base =3D in_buf, .iov_len =3D len + 4 }; struct smb_rqst rqst =3D { .rq_iov =3D &iov, .rq_nvec =3D 1 }; int resp_buf_type; int rc =3D 0; @@ -309,7 +258,7 @@ SendReceive(const unsigned int xid, struct cifs_ses *se= s, &rqst, &resp_buf_type, flags, &resp_iov); if (rc < 0) return rc; -=09 + *pbytes_returned =3D resp_iov.iov_len; if (resp_iov.iov_len) memcpy(out_buf, resp_iov.iov_base, resp_iov.iov_len); @@ -352,7 +301,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct = cifs_tcon *tcon, struct smb_message *smb; struct cifs_ses *ses; unsigned int len =3D be32_to_cpu(in_buf->smb_buf_length); - struct kvec iov =3D { .iov_base =3D in_buf, .iov_len =3D len }; + struct kvec iov =3D { .iov_base =3D in_buf, .iov_len =3D len + 4 }; struct smb_rqst rqst =3D { .rq_iov =3D &iov, .rq_nvec =3D 1 }; unsigned int instance; struct TCP_Server_Info *server; @@ -402,7 +351,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct = cifs_tcon *tcon, return rc; } =20 - rc =3D cifs_sign_smb(in_buf, server, &smb->sequence_number); + rc =3D cifs_sign_rqst(&rqst, server, &smb->sequence_number); if (rc) { delete_mid(smb); cifs_server_unlock(server); @@ -410,7 +359,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct = cifs_tcon *tcon, } =20 smb->mid_state =3D MID_REQUEST_SUBMITTED; - rc =3D smb_send(server, in_buf, len); + rc =3D __smb_send_rqst(server, 1, &rqst); cifs_save_when_sent(smb); =20 if (rc < 0) diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c index dc2daba936e2..401450eadf2c 100644 --- a/fs/smb/client/smb1ops.c +++ b/fs/smb/client/smb1ops.c @@ -31,8 +31,10 @@ static int send_nt_cancel(struct TCP_Server_Info *server, struct smb_rqst *rqst, struct smb_message *smb) { - int rc =3D 0; struct smb_hdr *in_buf =3D (struct smb_hdr *)rqst->rq_iov[0].iov_base; + struct kvec iov[1]; + struct smb_rqst crqst =3D { .rq_iov =3D iov, .rq_nvec =3D 1 }; + int rc =3D 0; =20 /* -4 for RFC1001 length and +2 for BCC field */ in_buf->smb_buf_length =3D cpu_to_be32(sizeof(struct smb_hdr) - 4 + 2); @@ -40,8 +42,11 @@ send_nt_cancel(struct TCP_Server_Info *server, struct sm= b_rqst *rqst, in_buf->WordCount =3D 0; put_bcc(0, in_buf); =20 + iov[0].iov_base =3D in_buf; + iov[0].iov_len =3D sizeof(struct smb_hdr) + 2; + cifs_server_lock(server); - rc =3D cifs_sign_smb(in_buf, server, &smb->sequence_number); + rc =3D cifs_sign_rqst(&crqst, server, &smb->sequence_number); if (rc) { cifs_server_unlock(server); return rc; @@ -53,7 +58,7 @@ send_nt_cancel(struct TCP_Server_Info *server, struct smb= _rqst *rqst, * after signing here. */ --server->sequence_number; - rc =3D smb_send(server, in_buf, be32_to_cpu(in_buf->smb_buf_length)); + rc =3D __smb_send_rqst(server, 1, &crqst); if (rc < 0) server->sequence_number--; =20 diff --git a/fs/smb/client/transport.c b/fs/smb/client/transport.c index d55b24d1aa77..db9ce9e84406 100644 --- a/fs/smb/client/transport.c +++ b/fs/smb/client/transport.c @@ -1036,23 +1036,24 @@ compound_send_recv(const unsigned int xid, struct c= ifs_ses *ses, goto out; } =20 - buf =3D (char *)smb[i]->resp_buf; - resp_iov[i].iov_base =3D buf; - resp_iov[i].iov_len =3D smb[i]->resp_buf_size + - HEADER_PREAMBLE_SIZE(server); - - if (smb[i]->large_buf) - resp_buf_type[i] =3D CIFS_LARGE_BUFFER; - else - resp_buf_type[i] =3D CIFS_SMALL_BUFFER; - rc =3D server->ops->check_receive(smb[i], server, flags & CIFS_LOG_ERROR); =20 - /* mark it so buf will not be freed by delete_mid */ - if ((flags & CIFS_NO_RSP_BUF) =3D=3D 0) - smb[i]->resp_buf =3D NULL; + if (resp_iov) { + buf =3D (char *)smb[i]->resp_buf; + resp_iov[i].iov_base =3D buf; + resp_iov[i].iov_len =3D smb[i]->resp_buf_size + + HEADER_PREAMBLE_SIZE(server); =20 + if (smb[i]->large_buf) + resp_buf_type[i] =3D CIFS_LARGE_BUFFER; + else + resp_buf_type[i] =3D CIFS_SMALL_BUFFER; + + /* mark it so buf will not be freed by delete_mid */ + if ((flags & CIFS_NO_RSP_BUF) =3D=3D 0) + smb[i]->resp_buf =3D NULL; + } } =20 /* From nobody Thu Dec 18 03:20:29 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A998F2C08A1 for ; Wed, 6 Aug 2025 20:38:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512706; cv=none; b=NLuIsvroMsgz05xlTKpqtw8wfs0uySJJCt1Qte7+3Le/67s/lJMMwpFT6afmBKYux+m17HyyDcMOwuUAkZYOnjmj0egdpA7aoSq0RHtQhD5a3/4euIy3MzT/a6nisOcgPSSqgG4IRm3OKnNSt8FJ7/i76eUTHUgBJOb57fSR2z0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512706; c=relaxed/simple; bh=USHb/9ST6euzn8k1SoAYww8YpgqPF1u/4oDdqQDdqyM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=aqxtPk0GWWy40JDBJYL4bRvssbtiKxVGF6dVuF/j3xygMcKTIWvjk/1IT9NR0mTnoTATmhlE/SQATOyWQddMRnpoJO8E6a148LKDtRFtoETg93wPJYCcyPO89VU+y/EKmW/Ob7EZY9GA1KNkxqUXtcLsGzEVS5bqA1w2lADDQK4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=K6mU6Jfi; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="K6mU6Jfi" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1754512701; h=from:from:reply-to:subject:subject: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=YhE39acOxKaWa3jRA1y9EkrgI1hlfMsajgqv0cvCMhQ=; b=K6mU6JfiaA3XGI5bCNhhqK0y/LYj2k/+gdWvAbqcHmsebOYb0YMLIiBCymnnmBPG/caRQH XmOMgC2qzVzjBi97SKp5JJ7pU07WVXHBUi3zpafyI+odUGRuIIhqTzO/jCBg1rW7isvhzk s0tXsNyoP9ZxEnE+8b2sSAIp6guS0kM= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-624-TIw1OLlQNcacZ2As5m9uVg-1; Wed, 06 Aug 2025 16:38:17 -0400 X-MC-Unique: TIw1OLlQNcacZ2As5m9uVg-1 X-Mimecast-MFC-AGG-ID: TIw1OLlQNcacZ2As5m9uVg_1754512694 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 4E5CE1956089; Wed, 6 Aug 2025 20:38:14 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.17]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 476CB30001A6; Wed, 6 Aug 2025 20:38:11 +0000 (UTC) From: David Howells To: Steve French Cc: David Howells , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Wang Zhaolong , Stefan Metzmacher , Mina Almasry , linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org, netfs@lists.linux.dev, linux-fsdevel@vger.kernel.org Subject: [RFC PATCH 12/31] cifs: Replace SendReceiveBlockingLock() with SendReceive() plus flags Date: Wed, 6 Aug 2025 21:36:33 +0100 Message-ID: <20250806203705.2560493-13-dhowells@redhat.com> In-Reply-To: <20250806203705.2560493-1-dhowells@redhat.com> References: <20250806203705.2560493-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Content-Type: text/plain; charset="utf-8" Replace the smb1 transport's SendReceiveBlockingLock() with SendReceive() plus a couple of flags. This will then allow that to pick up the transport changes there. The first flag, CIFS_INTERRUPTIBLE_WAIT, is added to indicate that the wait should be interruptible and the second, CIFS_WINDOWS_LOCK, indicates that we need to send a Lock command with unlock type rather than a Cancel. send_lock_cancel() is then called from cifs_lock_cancel() which is called f= rom the main transport loop in compound_send_recv(). [!] I *think* the error code handling is probably right. Signed-off-by: David Howells cc: Steve French cc: Paulo Alcantara cc: Shyam Prasad N cc: Tom Talpey cc: linux-cifs@vger.kernel.org cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/smb/client/cifsglob.h | 8 +- fs/smb/client/cifsproto.h | 12 +- fs/smb/client/cifssmb.c | 18 +-- fs/smb/client/cifstransport.c | 210 +--------------------------------- fs/smb/client/smb1ops.c | 45 +++++++- fs/smb/client/transport.c | 10 +- 6 files changed, 75 insertions(+), 228 deletions(-) diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index 60350213a02b..091d92ed670a 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h @@ -312,8 +312,9 @@ struct cifs_open_parms; struct cifs_credits; =20 struct smb_version_operations { - int (*send_cancel)(struct TCP_Server_Info *, struct smb_rqst *, - struct smb_message *smb); + int (*send_cancel)(struct cifs_ses *ses, struct TCP_Server_Info *server, + struct smb_rqst *rqst, struct smb_message *smb, + unsigned int xid); bool (*compare_fids)(struct cifsFileInfo *, struct cifsFileInfo *); /* setup request: allocate mid, sign message */ struct smb_message *(*setup_request)(struct cifs_ses *, @@ -1713,6 +1714,7 @@ struct smb_message { __u16 credits_received; /* number of credits from the response */ __u32 pid; /* process id */ __u32 sequence_number; /* for CIFS signing */ + unsigned int sr_flags; /* Flags passed to send_recv() */ unsigned long when_alloc; /* when mid was created */ #ifdef CONFIG_CIFS_STATS2 unsigned long when_sent; /* time when smb send finished */ @@ -1922,6 +1924,8 @@ static inline bool is_replayable_error(int error) #define CIFS_TRANSFORM_REQ 0x0800 /* transform request before sendi= ng */ #define CIFS_NO_SRV_RSP 0x1000 /* there is no server response */ #define CIFS_COMPRESS_REQ 0x4000 /* compress request before sendin= g */ +#define CIFS_INTERRUPTIBLE_WAIT 0x8000 /* Interruptible wait (e.g. lock = request) */ +#define CIFS_WINDOWS_LOCK 0x10000 /* We're trying to get a Windows= lock */ =20 /* Security Flags: indicate type of session setup needed */ #define CIFSSEC_MAY_SIGN 0x00001 diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h index 2b89469187d8..3249fe473aa1 100644 --- a/fs/smb/client/cifsproto.h +++ b/fs/smb/client/cifsproto.h @@ -131,11 +131,12 @@ extern int cifs_wait_mtu_credits(struct TCP_Server_In= fo *server, struct cifs_credits *credits); =20 static inline int -send_cancel(struct TCP_Server_Info *server, struct smb_rqst *rqst, - struct smb_message *smb) +send_cancel(struct cifs_ses *ses, struct TCP_Server_Info *server, + struct smb_rqst *rqst, struct smb_message *smb, + unsigned int xid) { return server->ops->send_cancel ? - server->ops->send_cancel(server, rqst, smb) : 0; + server->ops->send_cancel(ses, server, rqst, smb, xid) : 0; } =20 int wait_for_response(struct TCP_Server_Info *server, struct smb_message *= smb); @@ -143,11 +144,6 @@ extern int SendReceive2(const unsigned int /* xid */ ,= struct cifs_ses *, struct kvec *, int /* nvec to send */, int * /* type of buf returned */, const int flags, struct kvec * /* resp vec */); -extern int SendReceiveBlockingLock(const unsigned int xid, - struct cifs_tcon *ptcon, - struct smb_hdr *in_buf, - struct smb_hdr *out_buf, - int *bytes_returned); =20 void smb2_query_server_interfaces(struct work_struct *work); void diff --git a/fs/smb/client/cifssmb.c b/fs/smb/client/cifssmb.c index 66d8e2ad8cde..a7a9f63f8c21 100644 --- a/fs/smb/client/cifssmb.c +++ b/fs/smb/client/cifssmb.c @@ -1997,7 +1997,7 @@ CIFSSMBLock(const unsigned int xid, struct cifs_tcon = *tcon, LOCK_REQ *pSMB =3D NULL; /* LOCK_RSP *pSMBr =3D NULL; */ /* No response data other than rc to parse= */ int bytes_returned; - int flags =3D 0; + int flags =3D CIFS_WINDOWS_LOCK | CIFS_INTERRUPTIBLE_WAIT; __u16 count; =20 cifs_dbg(FYI, "CIFSSMBLock timeout %d numLock %d\n", @@ -2041,8 +2041,9 @@ CIFSSMBLock(const unsigned int xid, struct cifs_tcon = *tcon, pSMB->ByteCount =3D cpu_to_le16(count); =20 if (waitFlag) - rc =3D SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMB, &bytes_returned); + rc =3D SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, + (struct smb_hdr *) pSMB, &bytes_returned, + flags); else rc =3D SendReceiveNoRsp(xid, tcon->ses, (char *)pSMB, flags); cifs_small_buf_release(pSMB); @@ -2066,7 +2067,7 @@ CIFSSMBPosixLock(const unsigned int xid, struct cifs_= tcon *tcon, struct smb_com_transaction2_sfi_rsp *pSMBr =3D NULL; struct cifs_posix_lock *parm_data; int rc =3D 0; - int timeout =3D 0; + int sr_flags =3D CIFS_INTERRUPTIBLE_WAIT; int bytes_returned =3D 0; int resp_buf_type =3D 0; __u16 params, param_offset, offset, byte_count, count; @@ -2111,7 +2112,7 @@ CIFSSMBPosixLock(const unsigned int xid, struct cifs_= tcon *tcon, =20 parm_data->lock_type =3D cpu_to_le16(lock_type); if (waitFlag) { - timeout =3D CIFS_BLOCKING_OP; /* blocking operation, no timeout */ + sr_flags |=3D CIFS_BLOCKING_OP; /* blocking operation, no timeout */ parm_data->lock_flags =3D cpu_to_le16(1); pSMB->Timeout =3D cpu_to_le32(-1); } else @@ -2128,13 +2129,14 @@ CIFSSMBPosixLock(const unsigned int xid, struct cif= s_tcon *tcon, inc_rfc1001_len(pSMB, byte_count); pSMB->ByteCount =3D cpu_to_le16(byte_count); if (waitFlag) { - rc =3D SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned); + rc =3D SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, + (struct smb_hdr *) pSMBr, &bytes_returned, + sr_flags); } else { iov[0].iov_base =3D (char *)pSMB; iov[0].iov_len =3D be32_to_cpu(pSMB->hdr.smb_buf_length) + 4; rc =3D SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */, - &resp_buf_type, timeout, &rsp_iov); + &resp_buf_type, sr_flags, &rsp_iov); pSMBr =3D (struct smb_com_transaction2_sfi_rsp *)rsp_iov.iov_base; } cifs_small_buf_release(pSMB); diff --git a/fs/smb/client/cifstransport.c b/fs/smb/client/cifstransport.c index e5b75d9b9281..b5f652ad9e59 100644 --- a/fs/smb/client/cifstransport.c +++ b/fs/smb/client/cifstransport.c @@ -227,23 +227,6 @@ SendReceive(const unsigned int xid, struct cifs_ses *s= es, int resp_buf_type; int rc =3D 0; =20 - if (ses =3D=3D NULL) { - cifs_dbg(VFS, "Null smb session\n"); - return -EIO; - } - server =3D ses->server; - if (server =3D=3D NULL) { - cifs_dbg(VFS, "Null tcp session\n"); - return -EIO; - } - - spin_lock(&server->srv_lock); - if (server->tcpStatus =3D=3D CifsExiting) { - spin_unlock(&server->srv_lock); - return -ENOENT; - } - spin_unlock(&server->srv_lock); - /* Ensure that we do not send more than 50 overlapping requests to the same server. We may make this configurable later or use ses->maxReq */ @@ -259,194 +242,11 @@ SendReceive(const unsigned int xid, struct cifs_ses = *ses, if (rc < 0) return rc; =20 - *pbytes_returned =3D resp_iov.iov_len; - if (resp_iov.iov_len) - memcpy(out_buf, resp_iov.iov_base, resp_iov.iov_len); - free_rsp_buf(resp_buf_type, resp_iov.iov_base); - return rc; -} - -/* We send a LOCKINGX_CANCEL_LOCK to cause the Windows - blocking lock to return. */ - -static int -send_lock_cancel(const unsigned int xid, struct cifs_tcon *tcon, - struct smb_hdr *in_buf, - struct smb_hdr *out_buf) -{ - int bytes_returned; - struct cifs_ses *ses =3D tcon->ses; - LOCK_REQ *pSMB =3D (LOCK_REQ *)in_buf; - - /* We just modify the current in_buf to change - the type of lock from LOCKING_ANDX_SHARED_LOCK - or LOCKING_ANDX_EXCLUSIVE_LOCK to - LOCKING_ANDX_CANCEL_LOCK. */ - - pSMB->LockType =3D LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES; - pSMB->Timeout =3D 0; - pSMB->hdr.Mid =3D get_next_mid(ses->server); - - return SendReceive(xid, ses, in_buf, out_buf, - &bytes_returned, 0); -} - -int -SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, - struct smb_hdr *in_buf, struct smb_hdr *out_buf, - int *pbytes_returned) -{ - int rc =3D 0; - int rstart =3D 0; - struct smb_message *smb; - struct cifs_ses *ses; - unsigned int len =3D be32_to_cpu(in_buf->smb_buf_length); - struct kvec iov =3D { .iov_base =3D in_buf, .iov_len =3D len + 4 }; - struct smb_rqst rqst =3D { .rq_iov =3D &iov, .rq_nvec =3D 1 }; - unsigned int instance; - struct TCP_Server_Info *server; - - if (tcon =3D=3D NULL || tcon->ses =3D=3D NULL) { - cifs_dbg(VFS, "Null smb session\n"); - return -EIO; - } - ses =3D tcon->ses; - server =3D ses->server; - - if (server =3D=3D NULL) { - cifs_dbg(VFS, "Null tcp session\n"); - return -EIO; - } - - spin_lock(&server->srv_lock); - if (server->tcpStatus =3D=3D CifsExiting) { - spin_unlock(&server->srv_lock); - return -ENOENT; - } - spin_unlock(&server->srv_lock); - - /* Ensure that we do not send more than 50 overlapping requests - to the same server. We may make this configurable later or - use ses->maxReq */ - - if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { - cifs_tcon_dbg(VFS, "Invalid length, greater than maximum frame, %d\n", - len); - return -EIO; - } - - rc =3D wait_for_free_request(server, CIFS_BLOCKING_OP, &instance); - if (rc) - return rc; - - /* make sure that we sign in the same order that we send on this socket - and avoid races inside tcp sendmsg code that could cause corruption - of smb data */ - - cifs_server_lock(server); - - rc =3D allocate_mid(ses, in_buf, &smb); - if (rc) { - cifs_server_unlock(server); - return rc; - } - - rc =3D cifs_sign_rqst(&rqst, server, &smb->sequence_number); - if (rc) { - delete_mid(smb); - cifs_server_unlock(server); - return rc; - } - - smb->mid_state =3D MID_REQUEST_SUBMITTED; - rc =3D __smb_send_rqst(server, 1, &rqst); - cifs_save_when_sent(smb); - - if (rc < 0) - server->sequence_number -=3D 2; - - cifs_server_unlock(server); - - if (rc < 0) { - delete_mid(smb); - return rc; - } - - /* Wait for a reply - allow signals to interrupt. */ - rc =3D wait_event_interruptible(server->response_q, - (!(smb->mid_state =3D=3D MID_REQUEST_SUBMITTED || - smb->mid_state =3D=3D MID_RESPONSE_RECEIVED)) || - ((server->tcpStatus !=3D CifsGood) && - (server->tcpStatus !=3D CifsNew))); - - /* Were we interrupted by a signal ? */ - spin_lock(&server->srv_lock); - if ((rc =3D=3D -ERESTARTSYS) && - (smb->mid_state =3D=3D MID_REQUEST_SUBMITTED || - smb->mid_state =3D=3D MID_RESPONSE_RECEIVED) && - ((server->tcpStatus =3D=3D CifsGood) || - (server->tcpStatus =3D=3D CifsNew))) { - spin_unlock(&server->srv_lock); - - if (in_buf->Command =3D=3D SMB_COM_TRANSACTION2) { - /* POSIX lock. We send a NT_CANCEL SMB to cause the - blocking lock to return. */ - rc =3D send_cancel(server, &rqst, smb); - if (rc) { - delete_mid(smb); - return rc; - } - } else { - /* Windows lock. We send a LOCKINGX_CANCEL_LOCK - to cause the blocking lock to return. */ - - rc =3D send_lock_cancel(xid, tcon, in_buf, out_buf); - - /* If we get -ENOLCK back the lock may have - already been removed. Don't exit in this case. */ - if (rc && rc !=3D -ENOLCK) { - delete_mid(smb); - return rc; - } - } - - rc =3D wait_for_response(server, smb); - if (rc) { - send_cancel(server, &rqst, smb); - spin_lock(&server->mid_lock); - if (smb->mid_state =3D=3D MID_REQUEST_SUBMITTED || - smb->mid_state =3D=3D MID_RESPONSE_RECEIVED) { - /* no longer considered to be "in-flight" */ - smb->callback =3D release_mid; - spin_unlock(&server->mid_lock); - return rc; - } - spin_unlock(&server->mid_lock); - } - - /* We got the response - restart system call. */ - rstart =3D 1; - spin_lock(&server->srv_lock); + if (out_buf) { + *pbytes_returned =3D resp_iov.iov_len; + if (resp_iov.iov_len) + memcpy(out_buf, resp_iov.iov_base, resp_iov.iov_len); } - spin_unlock(&server->srv_lock); - - rc =3D cifs_sync_mid_result(smb, server); - if (rc !=3D 0) - return rc; - - /* rcvd frame is ok */ - if (out_buf =3D=3D NULL || smb->mid_state !=3D MID_RESPONSE_READY) { - rc =3D -EIO; - cifs_tcon_dbg(VFS, "Bad MID state?\n"); - goto out; - } - - *pbytes_returned =3D get_rfc1002_length(smb->resp_buf); - memcpy(out_buf, smb->resp_buf, *pbytes_returned + 4); - rc =3D cifs_check_receive(smb, server, 0); -out: - delete_mid(smb); - if (rstart && rc =3D=3D -EACCES) - return -ERESTARTSYS; + free_rsp_buf(resp_buf_type, resp_iov.iov_base); return rc; } diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c index 401450eadf2c..d2094b8872ac 100644 --- a/fs/smb/client/smb1ops.c +++ b/fs/smb/client/smb1ops.c @@ -28,8 +28,9 @@ * SMB_COM_NT_CANCEL request and then sends it. */ static int -send_nt_cancel(struct TCP_Server_Info *server, struct smb_rqst *rqst, - struct smb_message *smb) +send_nt_cancel(struct cifs_ses *ses, struct TCP_Server_Info *server, + struct smb_rqst *rqst, struct smb_message *smb, + unsigned int xid) { struct smb_hdr *in_buf =3D (struct smb_hdr *)rqst->rq_iov[0].iov_base; struct kvec iov[1]; @@ -70,6 +71,44 @@ send_nt_cancel(struct TCP_Server_Info *server, struct sm= b_rqst *rqst, return rc; } =20 +/* + * Send a LOCKINGX_CANCEL_LOCK to cause the Windows blocking lock to + * return. + */ +static int +send_lock_cancel(struct cifs_ses *ses, struct TCP_Server_Info *server, + struct smb_rqst *rqst, struct smb_message *smb, + unsigned int xid) +{ + struct smb_hdr *in_buf =3D (struct smb_hdr *)rqst->rq_iov[0].iov_base; + LOCK_REQ *pSMB =3D (LOCK_REQ *)in_buf; + int rc; + + /* We just modify the current in_buf to change + * the type of lock from LOCKING_ANDX_SHARED_LOCK + * or LOCKING_ANDX_EXCLUSIVE_LOCK to + * LOCKING_ANDX_CANCEL_LOCK. */ + + pSMB->LockType =3D LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES; + pSMB->Timeout =3D 0; + pSMB->hdr.Mid =3D get_next_mid(ses->server); + + rc =3D SendReceive(xid, ses, in_buf, NULL, NULL, 0); + if (rc =3D=3D -ENOLCK) + rc =3D 0; /* If we get back -ENOLCK, it probably means we managed + * to cancel the lock command before it took effect. */ + return rc; +} + +static int cifs_send_cancel(struct cifs_ses *ses, struct TCP_Server_Info *= server, + struct smb_rqst *rqst, struct smb_message *smb, + unsigned int xid) +{ + if (smb->sr_flags & CIFS_WINDOWS_LOCK) + return send_lock_cancel(ses, server, rqst, smb, xid); + return send_nt_cancel(ses, server, rqst, smb, xid); +} + static bool cifs_compare_fids(struct cifsFileInfo *ob1, struct cifsFileInfo *ob2) { @@ -1324,7 +1363,7 @@ cifs_is_network_name_deleted(char *buf, struct TCP_Se= rver_Info *server) } =20 struct smb_version_operations smb1_operations =3D { - .send_cancel =3D send_nt_cancel, + .send_cancel =3D cifs_send_cancel, .compare_fids =3D cifs_compare_fids, .setup_request =3D cifs_setup_request, .setup_async_request =3D cifs_setup_async_request, diff --git a/fs/smb/client/transport.c b/fs/smb/client/transport.c index db9ce9e84406..9282a3276318 100644 --- a/fs/smb/client/transport.c +++ b/fs/smb/client/transport.c @@ -636,12 +636,16 @@ cifs_wait_mtu_credits(struct TCP_Server_Info *server,= size_t size, =20 int wait_for_response(struct TCP_Server_Info *server, struct smb_message *= smb) { + unsigned int sleep_state =3D TASK_KILLABLE; int error; =20 + if (smb->sr_flags & CIFS_INTERRUPTIBLE_WAIT) + sleep_state =3D TASK_INTERRUPTIBLE; + error =3D wait_event_state(server->response_q, smb->mid_state !=3D MID_REQUEST_SUBMITTED && smb->mid_state !=3D MID_RESPONSE_RECEIVED, - (TASK_KILLABLE|TASK_FREEZABLE_UNSAFE)); + (sleep_state | TASK_FREEZABLE_UNSAFE)); if (error < 0) return -ERESTARTSYS; =20 @@ -695,6 +699,7 @@ cifs_call_async(struct TCP_Server_Info *server, struct = smb_rqst *rqst, return PTR_ERR(smb); } =20 + smb->sr_flags =3D flags; smb->receive =3D receive; smb->callback =3D callback; smb->callback_data =3D cbdata; @@ -939,6 +944,7 @@ compound_send_recv(const unsigned int xid, struct cifs_= ses *ses, return PTR_ERR(smb[i]); } =20 + smb[i]->sr_flags =3D flags; smb[i]->mid_state =3D MID_REQUEST_SUBMITTED; smb[i]->optype =3D optype; /* @@ -1005,7 +1011,7 @@ compound_send_recv(const unsigned int xid, struct cif= s_ses *ses, for (; i < num_rqst; i++) { cifs_server_dbg(FYI, "Cancelling wait for mid %llu cmd: %d\n", smb[i]->mid, smb[i]->command_id); - send_cancel(server, &rqst[i], smb[i]); + send_cancel(ses, server, &rqst[i], smb[i], xid); spin_lock(&server->mid_lock); smb[i]->mid_flags |=3D MID_WAIT_CANCELLED; if (smb[i]->mid_state =3D=3D MID_REQUEST_SUBMITTED || From nobody Thu Dec 18 03:20:29 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 50B4C2C1580 for ; Wed, 6 Aug 2025 20:38:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512712; cv=none; b=C3kumw+t2Y9vqxS8TTM4aPcZagnw75grdrX+FSMm7szGUbxvJlF+9DZl1Zywe9Bk7pM94UYVXV3EZt8vEB6cVbndQlcI8xREP9M+hdOua3Y+zFkpVi4AKP52fu/kPB9gwomOPqDAPydL0i0Cd0VnPSVyb4dGaegdPim0YrqWUyk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512712; c=relaxed/simple; bh=3ubwCXKBoRQm2ONk6hVA9wWEGfO6giCUjHgBw+Uhg3U=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=r1kUN4yE1fJTW9BHI3MH5YmuoeQrGdDzDNSJblNTzwnshNipA/NFHvYbbfH+/rHCF5vTcatmMa/KAlYex0vy/DBm8FcXG2z4mFlTTRXmwXaC/TwpoS9XsNjme1RVzpAMVYFzdjskxsXnEPBRIIsDSuJWSNUr3gWN66t49jy5ZvA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=ivr8GTIv; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="ivr8GTIv" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1754512703; h=from:from:reply-to:subject:subject: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=2G/zyqpIOISsinPIKYCP2yH6Hi/Kj9o4wevMU97HsGE=; b=ivr8GTIvAyDJP5qDLomfg1c9vHrfOTKvzl33YBxbaIHerLVQ/esEEiDZJD5fyoz6/7ErOc SNdo3RYS/99wxq2Lu/UG4ssVYXDMXVXwORu0Qly2lwoG9MlFRVqF79Sp/n+bG56l0l0r/h Mdqi9PD4XL5rcaYuSPGSExoHu7OS+rY= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-619-XHmhqDBNPdySZ0z0xhIu8A-1; Wed, 06 Aug 2025 16:38:20 -0400 X-MC-Unique: XHmhqDBNPdySZ0z0xhIu8A-1 X-Mimecast-MFC-AGG-ID: XHmhqDBNPdySZ0z0xhIu8A_1754512698 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id CB12B1800280; Wed, 6 Aug 2025 20:38:18 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.17]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id BF7FD1956086; Wed, 6 Aug 2025 20:38:15 +0000 (UTC) From: David Howells To: Steve French Cc: David Howells , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Wang Zhaolong , Stefan Metzmacher , Mina Almasry , linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org, netfs@lists.linux.dev, linux-fsdevel@vger.kernel.org Subject: [RFC PATCH 13/31] cifs: Institute message managing struct Date: Wed, 6 Aug 2025 21:36:34 +0100 Message-ID: <20250806203705.2560493-14-dhowells@redhat.com> In-Reply-To: <20250806203705.2560493-1-dhowells@redhat.com> References: <20250806203705.2560493-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Content-Type: text/plain; charset="utf-8" Turn the smb_message struct into a message handling struct to aid in building an SMB message, queuing them and holding the resources and buffers. It has absorbed the mid_q_struct and now other fields are added. The idea is that the smb_message struct will be allocated and filled in much higher up (typically in the PDU encoding code) and passed down to the transport. In particular, the following fields: (*) ->next: This is used to link together messages into compounds and then walk through the message list. (*) ->credits: The credit requirements for the message. (*) ->request: Pointer to the smb_hdr struct for the request. (*) ->command_id: The ID of the command in CPU endian form (better for if- and switch-statements). (*) ->total_len: The total length of the request message, not including rfc1002 or transform headers. (*) ->response: Pointer to the smb_hdr struct for the response. (*) ->rqst, ->resp_buf_type, ->resp_iov: The old request info stuff. Functions are provided to get and put refs upon the struct and also to drop all the refs on a compound string of structs. Signed-off-by: David Howells cc: Steve French cc: Paulo Alcantara cc: Shyam Prasad N cc: Tom Talpey cc: linux-cifs@vger.kernel.org cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/smb/client/cifsglob.h | 101 ++++++++++++++++++++++++---------- fs/smb/client/cifsproto.h | 10 +++- fs/smb/client/cifstransport.c | 2 +- fs/smb/client/connect.c | 6 +- fs/smb/client/smb1ops.c | 2 +- fs/smb/client/smb2ops.c | 2 +- fs/smb/client/smb2transport.c | 4 +- fs/smb/client/transport.c | 46 ++++++++++++++-- 8 files changed, 130 insertions(+), 43 deletions(-) diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index 091d92ed670a..90dafae1e9ab 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h @@ -1704,38 +1704,81 @@ typedef void (*mid_callback_t)(struct smb_message *= smb); typedef int (*mid_handle_t)(struct TCP_Server_Info *server, struct smb_message *smb); =20 -/* one of these for every pending CIFS request to the server */ +/* + * Definition of an SMB request message to be transmitted. These may be + * chained together and will automatically be turned into compound message= s if + * they are. + * + * +-----------------------+ + * | NetBIOS/padding | + * +-----------------------+ <--- smb->request + pre_offset + * | (Transform header) | + * +-----------------------+ <--- smb->request + * | SMB2 Header | } } + * +-----------------------+ } header_size } + * | Req/Rsp struct | } } + * +-----------------------+ <--- smb->request + ext_offset } protocol_size + * | | } + * | Extra protocol data | } + * | | } + * +-----------------------+ <--- smb->request + smb->data_offset + * | | + * | Data Payload | data_size + * | | + * +-----------------------+ + * + * + * If the data is to be RDMA'd, it will be kept separate from the protocol. + */ struct smb_message { - struct list_head qhead; /* mids waiting on reply from this server */ - struct kref refcount; - struct TCP_Server_Info *server; /* server corresponding to this mid */ - __u64 mid; /* multiplex id */ - __u16 credits; /* number of credits consumed by this mid */ - __u16 credits_received; /* number of credits from the response */ - __u32 pid; /* process id */ - __u32 sequence_number; /* for CIFS signing */ - unsigned int sr_flags; /* Flags passed to send_recv() */ - unsigned long when_alloc; /* when mid was created */ + struct smb_message *next; /* Next message in compound */ + struct cifs_credits credits; /* Credit requirements for this message */ + void *request; /* Pointer to request message body */ + refcount_t ref; + bool sensitive; /* Request contains sensitive data */ + bool cancelled; /* T if cancelled */ + unsigned int sr_flags; /* Flags passed to send_recv() */ + + /* Queue state */ + struct list_head qhead; /* mids waiting on reply from this server */ + struct TCP_Server_Info *server; /* server corresponding to this mid */ + __u64 mid; /* multiplex id */ + __u16 credits_consumed; /* number of credits consumed by this op */ + __u16 credits_received; /* number of credits from the response */ + __u32 pid; /* process id */ + __u32 sequence_number; /* for CIFS signing */ + unsigned long when_alloc; /* when mid was created */ #ifdef CONFIG_CIFS_STATS2 - unsigned long when_sent; /* time when smb send finished */ - unsigned long when_received; /* when demux complete (taken off wire) */ + unsigned long when_sent; /* time when smb send finished */ + unsigned long when_received; /* when demux complete (taken off wire) */ #endif - mid_receive_t receive; /* call receive callback */ - mid_callback_t callback; /* call completion callback */ - mid_handle_t handle; /* call handle mid callback */ - void *callback_data; /* general purpose pointer for callback */ - struct task_struct *creator; - void *resp_buf; /* pointer to received SMB header */ - unsigned int resp_buf_size; - int mid_state; /* wish this were enum but can not pass to wait_event */ - int mid_rc; /* rc for MID_RC */ - unsigned int mid_flags; - unsigned int optype; /* operation type */ - enum smb2_command command_id; /* smb command code */ - bool large_buf:1; /* if valid response, is pointer to large buf */ - bool multiRsp:1; /* multiple trans2 responses for one request */ - bool multiEnd:1; /* both received */ - bool decrypted:1; /* decrypted entry */ + mid_receive_t receive; /* call receive callback */ + mid_callback_t callback; /* call completion callback */ + mid_handle_t handle; /* call handle mid callback */ + void *callback_data; /* general purpose pointer for callback */ + struct task_struct *creator; + void *resp_buf; /* pointer to received SMB header */ + unsigned int resp_buf_size; + int mid_state; /* wish this were enum but can not pass to wait_event */ + int mid_rc; /* rc for MID_RC */ + unsigned int mid_flags; + unsigned int optype; /* operation type */ + bool large_buf:1; /* if valid response, is pointer to large buf */ + bool multiRsp:1; /* multiple trans2 responses for one request */ + bool multiEnd:1; /* both received */ + bool decrypted:1; /* decrypted entry */ + + /* Request details */ + enum smb2_command command_id; /* Command ID */ + s16 pre_offset; /* Offset of pre-headers from ->body (negative) */ + unsigned int total_len; /* Total length of from hdr_offset onwards */ + /* Response */ + void *response; /* Protocol part of response */ + u32 response_len; /* Size of response */ + /* Compat with old code */ + struct smb_rqst rqst; + int *resp_buf_type; + struct kvec *resp_iov; }; =20 struct close_cancelled_open { diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h index 3249fe473aa1..6f27fb6ef5dc 100644 --- a/fs/smb/client/cifsproto.h +++ b/fs/smb/client/cifsproto.h @@ -82,7 +82,7 @@ extern char *cifs_build_path_to_root(struct smb3_fs_conte= xt *ctx, extern char *build_wildcard_path_from_dentry(struct dentry *direntry); char *cifs_build_devname(char *nodename, const char *prepath); extern void delete_mid(struct smb_message *smb); -void __release_mid(struct kref *refcount); +void __release_mid(struct smb_message *smb); extern void cifs_wake_up_task(struct smb_message *smb); extern int cifs_handle_standard(struct TCP_Server_Info *server, struct smb_message *smb); @@ -755,7 +755,8 @@ static inline bool dfs_src_pathname_equal(const char *s= 1, const char *s2) =20 static inline void release_mid(struct smb_message *smb) { - kref_put(&smb->refcount, __release_mid); + if (refcount_dec_and_test(&smb->ref)) + __release_mid(smb); } =20 static inline void cifs_free_open_info(struct cifs_open_info_data *data) @@ -765,4 +766,9 @@ static inline void cifs_free_open_info(struct cifs_open= _info_data *data) memset(data, 0, sizeof(*data)); } =20 +struct smb_message *smb_message_alloc(enum smb2_command cmd, gfp_t gfp); +void smb_get_message(struct smb_message *smb); +void smb_put_message(struct smb_message *smb); +void smb_put_messages(struct smb_message *smb); + #endif /* _CIFSPROTO_H */ diff --git a/fs/smb/client/cifstransport.c b/fs/smb/client/cifstransport.c index b5f652ad9e59..a2db95faeb17 100644 --- a/fs/smb/client/cifstransport.c +++ b/fs/smb/client/cifstransport.c @@ -45,7 +45,7 @@ alloc_mid(const struct smb_hdr *smb_buffer, struct TCP_Se= rver_Info *server) =20 smb =3D mempool_alloc(&smb_message_pool, GFP_NOFS); memset(smb, 0, sizeof(struct smb_message)); - kref_init(&smb->refcount); + refcount_set(&smb->ref, 1); smb->mid =3D get_mid(smb_buffer); smb->pid =3D current->pid; smb->command_id =3D le16_to_cpu(smb_buffer->Command); diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c index 9abaca4c8eba..d26e2a6d7674 100644 --- a/fs/smb/client/connect.c +++ b/fs/smb/client/connect.c @@ -323,7 +323,7 @@ cifs_abort_connection(struct TCP_Server_Info *server) cifs_dbg(FYI, "%s: moving mids to private list\n", __func__); spin_lock(&server->mid_lock); list_for_each_entry_safe(smb, nsmb, &server->pending_mid_q, qhead) { - kref_get(&smb->refcount); + smb_get_message(smb); if (smb->mid_state =3D=3D MID_REQUEST_SUBMITTED) smb->mid_state =3D MID_RETRY_NEEDED; list_move(&smb->qhead, &retry_list); @@ -886,7 +886,7 @@ is_smb_response(struct TCP_Server_Info *server, unsigne= d char type) */ spin_lock(&server->mid_lock); list_for_each_entry_safe(smb, nsmb, &server->pending_mid_q, qhead) { - kref_get(&smb->refcount); + smb_get_message(smb); list_move(&smb->qhead, &dispose_list); smb->mid_flags |=3D MID_DELETED; } @@ -1105,7 +1105,7 @@ clean_demultiplex_info(struct TCP_Server_Info *server) list_for_each_safe(tmp, tmp2, &server->pending_mid_q) { smb =3D list_entry(tmp, struct smb_message, qhead); cifs_dbg(FYI, "Clearing mid %llu\n", smb->mid); - kref_get(&smb->refcount); + smb_get_message(smb); smb->mid_state =3D MID_SHUTDOWN; list_move(&smb->qhead, &dispose_list); smb->mid_flags |=3D MID_DELETED; diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c index d2094b8872ac..cc5b3c531c77 100644 --- a/fs/smb/client/smb1ops.c +++ b/fs/smb/client/smb1ops.c @@ -144,7 +144,7 @@ cifs_find_mid(struct TCP_Server_Info *server, char *buf= fer) if (compare_mid(smb->mid, buf) && smb->mid_state =3D=3D MID_REQUEST_SUBMITTED && smb->command_id =3D=3D command) { - kref_get(&smb->refcount); + smb_get_message(smb); spin_unlock(&server->mid_lock); return smb; } diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c index 36c506577b0e..7b714e50f681 100644 --- a/fs/smb/client/smb2ops.c +++ b/fs/smb/client/smb2ops.c @@ -407,7 +407,7 @@ __smb2_find_mid(struct TCP_Server_Info *server, char *b= uf, bool dequeue) if ((smb->mid =3D=3D wire_mid) && (smb->mid_state =3D=3D MID_REQUEST_SUBMITTED) && (smb->command_id =3D=3D command)) { - kref_get(&smb->refcount); + smb_get_message(smb); if (dequeue) { list_del_init(&smb->qhead); smb->mid_flags |=3D MID_DELETED; diff --git a/fs/smb/client/smb2transport.c b/fs/smb/client/smb2transport.c index fcf0999e77aa..b217bc0e8e5b 100644 --- a/fs/smb/client/smb2transport.c +++ b/fs/smb/client/smb2transport.c @@ -770,9 +770,9 @@ smb2_mid_entry_alloc(const struct smb2_hdr *shdr, =20 smb =3D mempool_alloc(&smb_message_pool, GFP_NOFS); memset(smb, 0, sizeof(*smb)); - kref_init(&smb->refcount); + refcount_set(&smb->ref, 1); smb->mid =3D le64_to_cpu(shdr->MessageId); - smb->credits =3D credits > 0 ? credits : 1; + smb->credits_consumed =3D credits > 0 ? credits : 1; smb->pid =3D current->pid; smb->command_id =3D le16_to_cpu(shdr->Command); smb->when_alloc =3D jiffies; diff --git a/fs/smb/client/transport.c b/fs/smb/client/transport.c index 9282a3276318..288351c27fc4 100644 --- a/fs/smb/client/transport.c +++ b/fs/smb/client/transport.c @@ -30,6 +30,46 @@ #include "smbdirect.h" #include "compress.h" =20 +struct smb_message *smb_message_alloc(enum smb2_command cmd, gfp_t gfp) +{ + struct smb_message *smb; + + smb =3D mempool_alloc(&smb_message_pool, gfp); + if (smb) { + memset(smb, 0, sizeof(*smb)); + refcount_set(&smb->ref, 1); + smb->command_id =3D cmd; + } + return smb; +} + +void smb_get_message(struct smb_message *smb) +{ + refcount_inc(&smb->ref); +} + +/* + * Drop a ref on a message. This does not touch the chained messages. + */ +void smb_put_message(struct smb_message *smb) +{ + if (refcount_dec_and_test(&smb->ref)) + mempool_free(smb, &smb_message_pool); +} + +/* + * Dispose of a chain of compound messages. + */ +void smb_put_messages(struct smb_message *smb) +{ + struct smb_message *next; + + for (; smb; smb =3D next) { + next =3D smb->next; + smb_put_message(smb); + } +} + void cifs_wake_up_task(struct smb_message *smb) { @@ -38,10 +78,8 @@ cifs_wake_up_task(struct smb_message *smb) wake_up_process(smb->callback_data); } =20 -void __release_mid(struct kref *refcount) +void __release_mid(struct smb_message *smb) { - struct smb_message *smb =3D - container_of(refcount, struct smb_message, refcount); #ifdef CONFIG_CIFS_STATS2 enum smb2_command command =3D smb->server->vals->lock_cmd; enum smb2_command smb_cmd =3D smb->command_id; @@ -719,7 +757,7 @@ cifs_call_async(struct TCP_Server_Info *server, struct = smb_rqst *rqst, rc =3D smb_send_rqst(server, 1, rqst, flags); =20 if (rc < 0) { - revert_current_mid(server, smb->credits); + revert_current_mid(server, smb->credits_consumed); server->sequence_number -=3D 2; delete_mid(smb); } From nobody Thu Dec 18 03:20:29 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5F5B92BDC27 for ; Wed, 6 Aug 2025 20:38:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512711; cv=none; b=j75cXLRlnncJnqn0FQxjBT223ktXUUhtrRSk9aL5chd7zlzDvNkYKtLCZtDrqa+kzI2ZJbWUQVSGTDRUUl2eK2KOwEs60bvHT2zPUqi49EkRFDZ8ZFH+9JuLQTAoLkLsXZuvVBUIDOEVYMjA2qbdpLgwkOYDavpR8YRXYOWlS+Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512711; c=relaxed/simple; bh=RADfIKwPhj+DkAPatNQkX2gb7fWflAIEqUTVTjDwFZs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=cxmIF8nw6z/HQn/38liiJzCUTL3Lp1BE6xqCpgu2KqY8v1sEtRwPlHq1vFS0PpQW/QPnQYOz0ecnOg6fT5vz8QW4cD2tzWiQrkGUAv8VnxJxz9cGJ1wDI8lp8dtPsvzPsYXGv2uUbgSbgsS4ibg454NDdREn2Wz/usqyxru5U6Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=EWpuGyPi; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="EWpuGyPi" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1754512708; h=from:from:reply-to:subject:subject: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=V53J5dLsJ8va+hHlO5XgVswqLQWMnx9lx0yK9P6Bodw=; b=EWpuGyPiwtPbOgouHE0851awW6fNPZvWULjROaDkTogdHGwb1AEMwLd0rMzHmDWxj5gBlk oVVVCu91NrJfWapXmAEROA2DWv0RM00SKXTVTCiJuCPWnJVx0nnUDQ+6h7InDSzKpDRHJa N5uxwfmpXGS7kadmtgLF4SZ0InmkCoY= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-685-bKiLt4O8MsOY2Yur167_xg-1; Wed, 06 Aug 2025 16:38:25 -0400 X-MC-Unique: bKiLt4O8MsOY2Yur167_xg-1 X-Mimecast-MFC-AGG-ID: bKiLt4O8MsOY2Yur167_xg_1754512703 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 8E0EA1800342; Wed, 6 Aug 2025 20:38:23 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.17]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 714FE180035C; Wed, 6 Aug 2025 20:38:20 +0000 (UTC) From: David Howells To: Steve French Cc: David Howells , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Wang Zhaolong , Stefan Metzmacher , Mina Almasry , linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org, netfs@lists.linux.dev, linux-fsdevel@vger.kernel.org Subject: [RFC PATCH 14/31] cifs: Split crypt_message() into encrypt and decrypt variants Date: Wed, 6 Aug 2025 21:36:35 +0100 Message-ID: <20250806203705.2560493-15-dhowells@redhat.com> In-Reply-To: <20250806203705.2560493-1-dhowells@redhat.com> References: <20250806203705.2560493-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Content-Type: text/plain; charset="utf-8" Split crypt_message() into encrypt and decrypt variants so that the encrypt variant can be substantially changed. Signed-off-by: David Howells cc: Steve French cc: Paulo Alcantara cc: Shyam Prasad N cc: Tom Talpey cc: linux-cifs@vger.kernel.org cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/smb/client/smb2ops.c | 100 ++++++++++++++++++++++++++++++++++------ 1 file changed, 85 insertions(+), 15 deletions(-) diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c index 7b714e50f681..0ad4a2a012a0 100644 --- a/fs/smb/client/smb2ops.c +++ b/fs/smb/client/smb2ops.c @@ -4297,16 +4297,17 @@ smb2_get_enc_key(struct TCP_Server_Info *server, __= u64 ses_id, int enc, u8 *key) =20 return -EAGAIN; } + /* - * Encrypt or decrypt @rqst message. @rqst[0] has the following format: + * Encrypt @rqst message. @rqst[0] has the following format: * iov[0] - transform header (associate data), * iov[1-N] - SMB2 header and pages - data to encrypt. * On success return encrypted data in iov[1-N] and pages, leave iov[0] * untouched. */ static int -crypt_message(struct TCP_Server_Info *server, int num_rqst, - struct smb_rqst *rqst, int enc, struct crypto_aead *tfm) +encrypt_message(struct TCP_Server_Info *server, int num_rqst, + struct smb_rqst *rqst, struct crypto_aead *tfm) { struct smb2_transform_hdr *tr_hdr =3D (struct smb2_transform_hdr *)rqst[0].rq_iov[0].iov_base; @@ -4321,10 +4322,10 @@ crypt_message(struct TCP_Server_Info *server, int n= um_rqst, void *creq; size_t sensitive_size; =20 - rc =3D smb2_get_enc_key(server, le64_to_cpu(tr_hdr->SessionId), enc, key); + rc =3D smb2_get_enc_key(server, le64_to_cpu(tr_hdr->SessionId), 1, key); if (rc) { - cifs_server_dbg(FYI, "%s: Could not get %scryption key. sid: 0x%llx\n", = __func__, - enc ? "en" : "de", le64_to_cpu(tr_hdr->SessionId)); + cifs_server_dbg(FYI, "%s: Could not get encryption key. sid: 0x%llx\n", + __func__, le64_to_cpu(tr_hdr->SessionId)); return rc; } =20 @@ -4350,11 +4351,6 @@ crypt_message(struct TCP_Server_Info *server, int nu= m_rqst, if (IS_ERR(creq)) return PTR_ERR(creq); =20 - if (!enc) { - memcpy(sign, &tr_hdr->Signature, SMB2_SIGNATURE_SIZE); - crypt_len +=3D SMB2_SIGNATURE_SIZE; - } - if ((server->cipher_type =3D=3D SMB2_ENCRYPTION_AES128_GCM) || (server->cipher_type =3D=3D SMB2_ENCRYPTION_AES256_GCM)) memcpy(iv, (char *)tr_hdr->Nonce, SMB3_AES_GCM_NONCE); @@ -4367,15 +4363,89 @@ crypt_message(struct TCP_Server_Info *server, int n= um_rqst, aead_request_set_crypt(req, sg, sg, crypt_len, iv); aead_request_set_ad(req, assoc_data_len); =20 - rc =3D enc ? crypto_aead_encrypt(req) : crypto_aead_decrypt(req); + rc =3D crypto_aead_encrypt(req); =20 - if (!rc && enc) + if (!rc) memcpy(&tr_hdr->Signature, sign, SMB2_SIGNATURE_SIZE); =20 kvfree_sensitive(creq, sensitive_size); return rc; } =20 +/* + * Decrypt @rqst message. @rqst[0] has the following format: + * iov[0] - transform header (associate data), + * iov[1-N] - SMB2 header and pages - data to decrypt. + * On success return encrypted data in iov[1-N] and pages, leave iov[0] + * untouched. + */ +static int +decrypt_message(struct TCP_Server_Info *server, int num_rqst, + struct smb_rqst *rqst, struct crypto_aead *tfm) +{ + struct smb2_transform_hdr *tr_hdr =3D + (struct smb2_transform_hdr *)rqst[0].rq_iov[0].iov_base; + unsigned int assoc_data_len =3D sizeof(struct smb2_transform_hdr) - 20; + int rc =3D 0; + struct scatterlist *sg; + u8 sign[SMB2_SIGNATURE_SIZE] =3D {}; + u8 key[SMB3_ENC_DEC_KEY_SIZE]; + struct aead_request *req; + u8 *iv; + unsigned int crypt_len =3D le32_to_cpu(tr_hdr->OriginalMessageSize); + void *creq; + size_t sensitive_size; + + rc =3D smb2_get_enc_key(server, le64_to_cpu(tr_hdr->SessionId), 0, key); + if (rc) { + cifs_server_dbg(FYI, "%s: Could not get decryption key. sid: 0x%llx\n", + __func__, le64_to_cpu(tr_hdr->SessionId)); + return rc; + } + + if ((server->cipher_type =3D=3D SMB2_ENCRYPTION_AES256_CCM) || + (server->cipher_type =3D=3D SMB2_ENCRYPTION_AES256_GCM)) + rc =3D crypto_aead_setkey(tfm, key, SMB3_GCM256_CRYPTKEY_SIZE); + else + rc =3D crypto_aead_setkey(tfm, key, SMB3_GCM128_CRYPTKEY_SIZE); + + if (rc) { + cifs_server_dbg(VFS, "%s: Failed to set aead key %d\n", __func__, rc); + return rc; + } + + rc =3D crypto_aead_setauthsize(tfm, SMB2_SIGNATURE_SIZE); + if (rc) { + cifs_server_dbg(VFS, "%s: Failed to set authsize %d\n", __func__, rc); + return rc; + } + + creq =3D smb2_get_aead_req(tfm, rqst, num_rqst, sign, &iv, &req, &sg, + &sensitive_size); + if (IS_ERR(creq)) + return PTR_ERR(creq); + + memcpy(sign, &tr_hdr->Signature, SMB2_SIGNATURE_SIZE); + crypt_len +=3D SMB2_SIGNATURE_SIZE; + + if ((server->cipher_type =3D=3D SMB2_ENCRYPTION_AES128_GCM) || + (server->cipher_type =3D=3D SMB2_ENCRYPTION_AES256_GCM)) + memcpy(iv, (char *)tr_hdr->Nonce, SMB3_AES_GCM_NONCE); + else { + iv[0] =3D 3; + memcpy(iv + 1, (char *)tr_hdr->Nonce, SMB3_AES_CCM_NONCE); + } + + aead_request_set_tfm(req, tfm); + aead_request_set_crypt(req, sg, sg, crypt_len, iv); + aead_request_set_ad(req, assoc_data_len); + + rc =3D crypto_aead_decrypt(req); + + kvfree_sensitive(creq, sensitive_size); + return rc; +} + /* * Clear a read buffer, discarding the folios which have the 1st mark set. */ @@ -4509,7 +4579,7 @@ smb3_init_transform_rq(struct TCP_Server_Info *server= , int num_rqst, /* fill the 1st iov with a transform header */ fill_transform_hdr(tr_hdr, orig_len, old_rq, server->cipher_type); =20 - rc =3D crypt_message(server, num_rqst, new_rq, 1, server->secmech.enc); + rc =3D encrypt_message(server, num_rqst, new_rq, server->secmech.enc); cifs_dbg(FYI, "Encrypt message returned %d\n", rc); if (rc) goto err_free; @@ -4571,7 +4641,7 @@ decrypt_raw_data(struct TCP_Server_Info *server, char= *buf, tfm =3D server->secmech.dec; } =20 - rc =3D crypt_message(server, 1, &rqst, 0, tfm); + rc =3D decrypt_message(server, 1, &rqst, tfm); cifs_dbg(FYI, "Decrypt message returned %d\n", rc); =20 if (is_offloaded) From nobody Thu Dec 18 03:20:29 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3D2052BDC20 for ; Wed, 6 Aug 2025 20:38:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512720; cv=none; b=HOx2U0rOFSfT1rkayRGqZXwMEeVZprhnU50sYConVcFf/QN5E9HTOGJkO6p08VzZJP4orLSlbPkBM2scyBLklAtbE0ZzBNAlU0yaceqXD6PD6/QcKNuao3vpZp47gKU3MP6sIXVI7P2pRBsL6VXMaYhLfeNvwmVB4vGClVq+1vc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512720; c=relaxed/simple; bh=VnqapvoeUl8a0mWesAi40SyStyvdPjrMa3U/I1C8HPE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=p8rOumoF+ElXkoLhFKkp9UB6ST5wiEF3v/hMXjA5VCVlWXP5jxiMOJb5byj1nmONBFPaRn9apOaaw0wMsQy5ykJs0J4LQpZHIlMz69FUYiCp98D48ALIF+TuS3MZiN0kX6ZPKmhq0JWBlRyvs951C0uanUkdnsM1Pw4SMOvBQWk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=WJ7qClMk; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="WJ7qClMk" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1754512716; h=from:from:reply-to:subject:subject: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=nsDK5Zd7b247EgGukZBaGMeBw3sasv4i13b60wegV74=; b=WJ7qClMkwFMT+pUjrseN/HEqKdSkmL40wN+cMK/2W9RJrufnfIfuVfG8bekEt8y0Qws4Am UMNN94vC4FbSWLX3lLQHfaFjFcjNm94rF3zGjcCDlHNszIA0y5njRUc8TKkKPxMPpSrmb5 n3V9M5R08WqoGGfB4L70CL5woLXoG6s= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-166-uJdsIU7PNimj8aT6PLh88A-1; Wed, 06 Aug 2025 16:38:30 -0400 X-MC-Unique: uJdsIU7PNimj8aT6PLh88A-1 X-Mimecast-MFC-AGG-ID: uJdsIU7PNimj8aT6PLh88A_1754512708 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 4D50A180035B; Wed, 6 Aug 2025 20:38:28 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.17]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 2EDED3000198; Wed, 6 Aug 2025 20:38:24 +0000 (UTC) From: David Howells To: Steve French Cc: David Howells , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Wang Zhaolong , Stefan Metzmacher , Mina Almasry , linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org, netfs@lists.linux.dev, linux-fsdevel@vger.kernel.org Subject: [RFC PATCH 15/31] cifs: Use netfs_alloc/free_folioq_buffer() Date: Wed, 6 Aug 2025 21:36:36 +0100 Message-ID: <20250806203705.2560493-16-dhowells@redhat.com> In-Reply-To: <20250806203705.2560493-1-dhowells@redhat.com> References: <20250806203705.2560493-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Content-Type: text/plain; charset="utf-8" Use netfs_alloc/free_folioq_buffer() rather than doing its own version. Signed-off-by: David Howells cc: Steve French cc: Paulo Alcantara cc: Shyam Prasad N cc: Tom Talpey (RDMA, smbdirect) cc: linux-cifs@vger.kernel.org cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/smb/client/smb2ops.c | 73 ++++++----------------------------------- 1 file changed, 10 insertions(+), 63 deletions(-) diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c index 0ad4a2a012a0..161cef316346 100644 --- a/fs/smb/client/smb2ops.c +++ b/fs/smb/client/smb2ops.c @@ -4446,61 +4446,6 @@ decrypt_message(struct TCP_Server_Info *server, int = num_rqst, return rc; } =20 -/* - * Clear a read buffer, discarding the folios which have the 1st mark set. - */ -static void cifs_clear_folioq_buffer(struct folio_queue *buffer) -{ - struct folio_queue *folioq; - - while ((folioq =3D buffer)) { - for (int s =3D 0; s < folioq_count(folioq); s++) - if (folioq_is_marked(folioq, s)) - folio_put(folioq_folio(folioq, s)); - buffer =3D folioq->next; - kfree(folioq); - } -} - -/* - * Allocate buffer space into a folio queue. - */ -static struct folio_queue *cifs_alloc_folioq_buffer(ssize_t size) -{ - struct folio_queue *buffer =3D NULL, *tail =3D NULL, *p; - struct folio *folio; - unsigned int slot; - - do { - if (!tail || folioq_full(tail)) { - p =3D kmalloc(sizeof(*p), GFP_NOFS); - if (!p) - goto nomem; - folioq_init(p, 0); - if (tail) { - tail->next =3D p; - p->prev =3D tail; - } else { - buffer =3D p; - } - tail =3D p; - } - - folio =3D folio_alloc(GFP_KERNEL|__GFP_HIGHMEM, 0); - if (!folio) - goto nomem; - - slot =3D folioq_append_mark(tail, folio); - size -=3D folioq_folio_size(tail, slot); - } while (size > 0); - - return buffer; - -nomem: - cifs_clear_folioq_buffer(buffer); - return NULL; -} - /* * Copy data from an iterator to the folios in a folio queue buffer. */ @@ -4526,7 +4471,7 @@ void smb3_free_compound_rqst(int num_rqst, struct smb_rqst *rqst) { for (int i =3D 0; i < num_rqst; i++) - cifs_clear_folioq_buffer(rqst[i].rq_buffer); + netfs_free_folioq_buffer(rqst[i].rq_buffer); } =20 /* @@ -4561,8 +4506,10 @@ smb3_init_transform_rq(struct TCP_Server_Info *serve= r, int num_rqst, new->rq_nvec =3D old->rq_nvec; =20 if (size > 0) { - buffer =3D cifs_alloc_folioq_buffer(size); - if (!buffer) + size_t cur_size =3D 0; + rc =3D netfs_alloc_folioq_buffer(NULL, &buffer, &cur_size, + size, GFP_NOFS); + if (rc < 0) goto err_free; =20 new->rq_buffer =3D buffer; @@ -4894,7 +4841,7 @@ static void smb2_decrypt_offload(struct work_struct *= work) } =20 free_pages: - cifs_clear_folioq_buffer(dw->buffer); + netfs_free_folioq_buffer(dw->buffer); cifs_small_buf_release(dw->buf); kfree(dw); } @@ -4932,9 +4879,9 @@ receive_encrypted_read(struct TCP_Server_Info *server= , struct smb_message **smb, dw->len =3D len; len =3D round_up(dw->len, PAGE_SIZE); =20 - rc =3D -ENOMEM; - dw->buffer =3D cifs_alloc_folioq_buffer(len); - if (!dw->buffer) + size_t cur_size =3D 0; + rc =3D netfs_alloc_folioq_buffer(NULL, &dw->buffer, &cur_size, len, GFP_N= OFS); + if (rc < 0) goto discard_data; =20 iov_iter_folio_queue(&iter, ITER_DEST, dw->buffer, 0, 0, len); @@ -4995,7 +4942,7 @@ receive_encrypted_read(struct TCP_Server_Info *server= , struct smb_message **smb, } =20 free_pages: - cifs_clear_folioq_buffer(dw->buffer); + netfs_free_folioq_buffer(dw->buffer); free_dw: kfree(dw); return rc; From nobody Thu Dec 18 03:20:29 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 94B742C3749 for ; Wed, 6 Aug 2025 20:38:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512722; cv=none; b=aEv0cfTf6B6ZcOLotEzJZL6KERo8GuxQZdbNAk1G30IxFlxhGy2wyFz/FjB+h0ms4uhodWck3HFHnNQStmdJAKlj6MSRq840fvN7LIbVSIdddoJ6WglwkKtmPDZCNfroWKt+CfSVlkLgKqM/VE6vEH+o+Ygk9UJaSHNHUlwX8dI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512722; c=relaxed/simple; bh=Ev9aDVlQl03tSih1Vac14+mpYMO5Vzjk9GuHD3Qq5Zk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Ij6p9w2aTJXkX3vzXTdNJflW666LejmhpvPi8xe5Ogan8uExkCW+VZahUpH9oHq4WbQzINGi9kYwUDQyTU3/JFhsM/TMXB6mqEb5LpxEFCcY3qcVI5z5LoIGLrqxMlnzsf/tBM3ZvXlqAtKa8sWp1n2/bIZxFyORpwChwcVXHNw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=AJU8j05x; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="AJU8j05x" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1754512718; h=from:from:reply-to:subject:subject: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=nYpFtBQ1DTRlehEoGRFF9StIG4KMdzYznICqXS3nZGg=; b=AJU8j05xVPdHWscInxpeF4TahkepAJjrqChvAEfh0f7gT4SSKErWKm6T1+R42y1B6cb3S+ BPBX6Um4WAH4UcPl6iQJKaaX4eWuFyxU3r65n1j81S8HePME3C2C+vVElJLeVvYJRZpOcI Kxg5e9vtpjHm/1AZsAm0kcfj9M9T6dQ= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-455-NvBeLjk3PH-T2pf-0kfhIA-1; Wed, 06 Aug 2025 16:38:35 -0400 X-MC-Unique: NvBeLjk3PH-T2pf-0kfhIA-1 X-Mimecast-MFC-AGG-ID: NvBeLjk3PH-T2pf-0kfhIA_1754512713 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 4E2F3195608E; Wed, 6 Aug 2025 20:38:33 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.17]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 05B311800447; Wed, 6 Aug 2025 20:38:29 +0000 (UTC) From: David Howells To: Steve French Cc: David Howells , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Wang Zhaolong , Stefan Metzmacher , Mina Almasry , linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org, netfs@lists.linux.dev, linux-fsdevel@vger.kernel.org Subject: [RFC PATCH 16/31] cifs: Rewrite base TCP transmission Date: Wed, 6 Aug 2025 21:36:37 +0100 Message-ID: <20250806203705.2560493-17-dhowells@redhat.com> In-Reply-To: <20250806203705.2560493-1-dhowells@redhat.com> References: <20250806203705.2560493-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Content-Type: text/plain; charset="utf-8" [!] NOTE: This patch is not fully complete: RDMA is untested and compression is currently disabled Rewrite the base TCP transmission in cifs to copy all the content in a (compound) message into a buffer of pages in a bvecq chain. In future, the pages in this bvecq chain will be allocated from the netmem allocator so that the advance DMA/IOMMU handling will be done. This list of pages can then be attached to an ITER_BVEC_QUEUE-type iov_iter and passed in a single call to sendmsg() with MSG_SPLICE_PAGES, thereby avoiding the need to copy the data in the TCP stack. The encryption code can also be simplified as it only needs to encrypt the data stored in those pages, with the bonus that the content in the pages is correctly aligned for the encryption in place such that it does not need to copy the data whilst encrypting it. It could be arranged for the data to be held in contiguous pages if possible and if necessary such that crypto can be offloaded to devices that only permit a single contiguous buffer. Signed-off-by: David Howells cc: Steve French cc: Paulo Alcantara cc: Shyam Prasad N cc: Tom Talpey cc: linux-cifs@vger.kernel.org cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/netfs/buffer.c | 3 +- fs/smb/client/cifsglob.h | 7 +- fs/smb/client/cifsproto.h | 5 +- fs/smb/client/smb1ops.c | 5 +- fs/smb/client/smb2ops.c | 193 ++++++++++++------------- fs/smb/client/smbdirect.c | 88 ++---------- fs/smb/client/smbdirect.h | 5 +- fs/smb/client/transport.c | 291 +++++++++++++++++++++++++++----------- 8 files changed, 330 insertions(+), 267 deletions(-) diff --git a/fs/netfs/buffer.c b/fs/netfs/buffer.c index 1e4ed2746e95..84d5ddc2a2c0 100644 --- a/fs/netfs/buffer.c +++ b/fs/netfs/buffer.c @@ -93,7 +93,8 @@ void netfs_free_bvecq_buffer(struct bvecq *bq) =20 for (; bq; bq =3D next) { for (int seg =3D 0; seg < bq->nr_segs; seg++) - __free_page(bq->bv[seg].bv_page); + if (bq->bv[seg].bv_page) + __free_page(bq->bv[seg].bv_page); next =3D bq->next; kfree(bq); } diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index 90dafae1e9ab..ae06c2b5a9c8 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h @@ -594,8 +594,10 @@ struct smb_version_operations { long (*fallocate)(struct file *, struct cifs_tcon *, int, loff_t, loff_t); /* init transform (compress/encrypt) request */ - int (*init_transform_rq)(struct TCP_Server_Info *, int num_rqst, - struct smb_rqst *, struct smb_rqst *); + int (*init_transform_rq)(struct TCP_Server_Info *server, + int num_rqst, const struct smb_rqst *rqst, + struct smb2_transform_hdr *tr_hdr, + struct iov_iter *iter); int (*is_transform_hdr)(void *buf); int (*receive_transform)(struct TCP_Server_Info *, struct smb_message **smb, char **, int *); @@ -1356,7 +1358,6 @@ struct tcon_link { }; =20 extern struct tcon_link *cifs_sb_tlink(struct cifs_sb_info *cifs_sb); -extern void smb3_free_compound_rqst(int num_rqst, struct smb_rqst *rqst); =20 static inline struct cifs_tcon * tlink_tcon(struct tcon_link *tlink) diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h index 6f27fb6ef5dc..76cb047b2715 100644 --- a/fs/smb/client/cifsproto.h +++ b/fs/smb/client/cifsproto.h @@ -32,6 +32,8 @@ extern void free_rsp_buf(int, void *); extern int smb_send_kvec(struct TCP_Server_Info *server, struct msghdr *msg, size_t *sent); +int smb_sendmsg(struct TCP_Server_Info *server, struct msghdr *smb_msg, + size_t *sent); extern unsigned int _get_xid(void); extern void _free_xid(unsigned int); #define get_xid() \ @@ -120,8 +122,7 @@ extern struct smb_message *cifs_setup_request(struct ci= fs_ses *, struct smb_rqst *); extern struct smb_message *cifs_setup_async_request(struct TCP_Server_Info= *, struct smb_rqst *); -int __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst, - struct smb_rqst *rqst); +int __smb_send_rqst(struct TCP_Server_Info *server, struct iov_iter *iter); extern int cifs_check_receive(struct smb_message *msg, struct TCP_Server_Info *server, bool log_error); int wait_for_free_request(struct TCP_Server_Info *server, const int flags, diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c index cc5b3c531c77..185210b7fd03 100644 --- a/fs/smb/client/smb1ops.c +++ b/fs/smb/client/smb1ops.c @@ -32,6 +32,7 @@ send_nt_cancel(struct cifs_ses *ses, struct TCP_Server_In= fo *server, struct smb_rqst *rqst, struct smb_message *smb, unsigned int xid) { + struct iov_iter iter; struct smb_hdr *in_buf =3D (struct smb_hdr *)rqst->rq_iov[0].iov_base; struct kvec iov[1]; struct smb_rqst crqst =3D { .rq_iov =3D iov, .rq_nvec =3D 1 }; @@ -53,13 +54,15 @@ send_nt_cancel(struct cifs_ses *ses, struct TCP_Server_= Info *server, return rc; } =20 + iov_iter_kvec(&iter, ITER_SOURCE, iov, 1, iov[0].iov_len); + /* * The response to this call was already factored into the sequence * number when the call went out, so we must adjust it back downward * after signing here. */ --server->sequence_number; - rc =3D __smb_send_rqst(server, 1, &crqst); + rc =3D __smb_send_rqst(server, &iter); if (rc < 0) server->sequence_number--; =20 diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c index 161cef316346..baa54e746f0f 100644 --- a/fs/smb/client/smb2ops.c +++ b/fs/smb/client/smb2ops.c @@ -4169,21 +4169,21 @@ smb2_dir_needs_close(struct cifsFileInfo *cfile) =20 static void fill_transform_hdr(struct smb2_transform_hdr *tr_hdr, unsigned int orig_le= n, - struct smb_rqst *old_rq, __le16 cipher_type) + const struct smb_rqst *old_rq, __le16 cipher_type) { - struct smb2_hdr *shdr =3D - (struct smb2_hdr *)old_rq->rq_iov[0].iov_base; + struct smb2_hdr *shdr =3D (struct smb2_hdr *)old_rq->rq_iov[0].iov_base; =20 - memset(tr_hdr, 0, sizeof(struct smb2_transform_hdr)); - tr_hdr->ProtocolId =3D SMB2_TRANSFORM_PROTO_NUM; - tr_hdr->OriginalMessageSize =3D cpu_to_le32(orig_len); - tr_hdr->Flags =3D cpu_to_le16(0x01); + *tr_hdr =3D (struct smb2_transform_hdr){ + .ProtocolId =3D SMB2_TRANSFORM_PROTO_NUM, + .OriginalMessageSize =3D cpu_to_le32(orig_len), + .Flags =3D cpu_to_le16(0x01), + .SessionId =3D shdr->SessionId, + }; if ((cipher_type =3D=3D SMB2_ENCRYPTION_AES128_GCM) || (cipher_type =3D=3D SMB2_ENCRYPTION_AES256_GCM)) get_random_bytes(&tr_hdr->Nonce, SMB3_AES_GCM_NONCE); else get_random_bytes(&tr_hdr->Nonce, SMB3_AES_CCM_NONCE); - memcpy(&tr_hdr->SessionId, &shdr->SessionId, 8); } =20 static void *smb2_aead_req_alloc(struct crypto_aead *tfm, const struct smb= _rqst *rqst, @@ -4269,6 +4269,75 @@ static void *smb2_get_aead_req(struct crypto_aead *t= fm, struct smb_rqst *rqst, return p; } =20 +/* + * Allocate the context info needed for the encryption operation, along wi= th a + * scatterlist to point to the buffer. + */ +static void *smb2_aead_req_alloc_new(struct crypto_aead *tfm, const struct= iov_iter *iter, + const u8 *sig, u8 **iv, + struct aead_request **req, struct sg_table *sgt, + unsigned int *num_sgs, size_t *sensitive_size) +{ + unsigned int req_size =3D sizeof(**req) + crypto_aead_reqsize(tfm); + unsigned int iv_size =3D crypto_aead_ivsize(tfm); + unsigned int len; + u8 *p; + + *num_sgs =3D iov_iter_npages(iter, INT_MAX); + + len =3D iv_size; + len +=3D crypto_aead_alignmask(tfm) & ~(crypto_tfm_ctx_alignment() - 1); + len =3D ALIGN(len, crypto_tfm_ctx_alignment()); + len +=3D req_size; + len =3D ALIGN(len, __alignof__(struct scatterlist)); + len +=3D array_size(*num_sgs, sizeof(struct scatterlist)); + *sensitive_size =3D len; + + p =3D kvzalloc(len, GFP_NOFS); + if (!p) + return ERR_PTR(-ENOMEM); + + *iv =3D (u8 *)PTR_ALIGN(p, crypto_aead_alignmask(tfm) + 1); + *req =3D (struct aead_request *)PTR_ALIGN(*iv + iv_size, + crypto_tfm_ctx_alignment()); + sgt->sgl =3D (struct scatterlist *)PTR_ALIGN((u8 *)*req + req_size, + __alignof__(struct scatterlist)); + return p; +} + +/* + * Set up for doing a crypto operation, building a scatterlist from the + * supplied iterator. + */ +static void *smb2_get_aead_req_new(struct crypto_aead *tfm, const struct i= ov_iter *iter, + const u8 *sig, u8 **iv, + struct aead_request **req, struct scatterlist **sgl, + size_t *sensitive_size) +{ + struct sg_table sgtable =3D {}; + struct iov_iter tmp =3D *iter; + unsigned int num_sgs; + ssize_t rc; + void *p; + + p =3D smb2_aead_req_alloc_new(tfm, iter, sig, iv, req, &sgtable, + &num_sgs, sensitive_size); + if (IS_ERR(p)) + return ERR_CAST(p); + + sg_init_marker(sgtable.sgl, num_sgs); + + rc =3D extract_iter_to_sg(&tmp, iov_iter_count(iter), &sgtable, num_sgs, = 0); + sgtable.orig_nents =3D sgtable.nents; + if (rc < 0) + return ERR_PTR(rc); + + cifs_sg_set_buf(&sgtable, sig, SMB2_SIGNATURE_SIZE); + sg_mark_end(&sgtable.sgl[sgtable.nents - 1]); + *sgl =3D sgtable.sgl; + return p; +} + static int smb2_get_enc_key(struct TCP_Server_Info *server, __u64 ses_id, int enc, u8= *key) { @@ -4299,18 +4368,15 @@ smb2_get_enc_key(struct TCP_Server_Info *server, __= u64 ses_id, int enc, u8 *key) } =20 /* - * Encrypt @rqst message. @rqst[0] has the following format: - * iov[0] - transform header (associate data), - * iov[1-N] - SMB2 header and pages - data to encrypt. + * Encrypt the message in the buffer described by the iterator. * On success return encrypted data in iov[1-N] and pages, leave iov[0] * untouched. */ static int -encrypt_message(struct TCP_Server_Info *server, int num_rqst, - struct smb_rqst *rqst, struct crypto_aead *tfm) +encrypt_message(struct TCP_Server_Info *server, + struct smb2_transform_hdr *tr_hdr, + struct iov_iter *iter, struct crypto_aead *tfm) { - struct smb2_transform_hdr *tr_hdr =3D - (struct smb2_transform_hdr *)rqst[0].rq_iov[0].iov_base; unsigned int assoc_data_len =3D sizeof(struct smb2_transform_hdr) - 20; int rc =3D 0; struct scatterlist *sg; @@ -4346,8 +4412,8 @@ encrypt_message(struct TCP_Server_Info *server, int n= um_rqst, return rc; } =20 - creq =3D smb2_get_aead_req(tfm, rqst, num_rqst, sign, &iv, &req, &sg, - &sensitive_size); + creq =3D smb2_get_aead_req_new(tfm, iter, sign, &iv, &req, &sg, + &sensitive_size); if (IS_ERR(creq)) return PTR_ERR(creq); =20 @@ -4447,94 +4513,23 @@ decrypt_message(struct TCP_Server_Info *server, int= num_rqst, } =20 /* - * Copy data from an iterator to the folios in a folio queue buffer. - */ -static bool cifs_copy_iter_to_folioq(struct iov_iter *iter, size_t size, - struct folio_queue *buffer) -{ - for (; buffer; buffer =3D buffer->next) { - for (int s =3D 0; s < folioq_count(buffer); s++) { - struct folio *folio =3D folioq_folio(buffer, s); - size_t part =3D folioq_folio_size(buffer, s); - - part =3D umin(part, size); - - if (copy_folio_from_iter(folio, 0, part, iter) !=3D part) - return false; - size -=3D part; - } - } - return true; -} - -void -smb3_free_compound_rqst(int num_rqst, struct smb_rqst *rqst) -{ - for (int i =3D 0; i < num_rqst; i++) - netfs_free_folioq_buffer(rqst[i].rq_buffer); -} - -/* - * This function will initialize new_rq and encrypt the content. - * The first entry, new_rq[0], only contains a single iov which contains - * a smb2_transform_hdr and is pre-allocated by the caller. - * This function then populates new_rq[1+] with the content from olq_rq[0+= ]. - * - * The end result is an array of smb_rqst structures where the first struc= ture - * only contains a single iov for the transform header which we then can p= ass - * to crypt_message(). - * - * new_rq[0].rq_iov[0] : smb2_transform_hdr pre-allocated by the caller - * new_rq[1+].rq_iov[*] =3D=3D old_rq[0+].rq_iov[*] : SMB2/3 requests + * This function encrypts the content in the buffer described by the itera= tor + * and fills in the transform header. The source request buffers are prov= ided + * for reference. */ static int -smb3_init_transform_rq(struct TCP_Server_Info *server, int num_rqst, - struct smb_rqst *new_rq, struct smb_rqst *old_rq) +smb3_init_transform_rq(struct TCP_Server_Info *server, + int num_rqst, const struct smb_rqst *rqst, + struct smb2_transform_hdr *tr_hdr, + struct iov_iter *iter) { - struct smb2_transform_hdr *tr_hdr =3D new_rq[0].rq_iov[0].iov_base; - unsigned int orig_len =3D 0; - int rc =3D -ENOMEM; - - for (int i =3D 1; i < num_rqst; i++) { - struct smb_rqst *old =3D &old_rq[i - 1]; - struct smb_rqst *new =3D &new_rq[i]; - struct folio_queue *buffer; - size_t size =3D iov_iter_count(&old->rq_iter); - - orig_len +=3D smb_rqst_len(server, old); - new->rq_iov =3D old->rq_iov; - new->rq_nvec =3D old->rq_nvec; - - if (size > 0) { - size_t cur_size =3D 0; - rc =3D netfs_alloc_folioq_buffer(NULL, &buffer, &cur_size, - size, GFP_NOFS); - if (rc < 0) - goto err_free; - - new->rq_buffer =3D buffer; - iov_iter_folio_queue(&new->rq_iter, ITER_SOURCE, - buffer, 0, 0, size); - - if (!cifs_copy_iter_to_folioq(&old->rq_iter, size, buffer)) { - rc =3D -EIO; - goto err_free; - } - } - } + int rc; =20 - /* fill the 1st iov with a transform header */ - fill_transform_hdr(tr_hdr, orig_len, old_rq, server->cipher_type); + fill_transform_hdr(tr_hdr, iov_iter_count(iter), rqst, + server->cipher_type); =20 - rc =3D encrypt_message(server, num_rqst, new_rq, server->secmech.enc); + rc =3D encrypt_message(server, tr_hdr, iter, server->secmech.enc); cifs_dbg(FYI, "Encrypt message returned %d\n", rc); - if (rc) - goto err_free; - - return rc; - -err_free: - smb3_free_compound_rqst(num_rqst - 1, &new_rq[1]); return rc; } =20 diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c index 754e94a0e07f..a75cb3f0ca72 100644 --- a/fs/smb/client/smbdirect.c +++ b/fs/smb/client/smbdirect.c @@ -1015,27 +1015,6 @@ static int smbd_post_send_empty(struct smbd_connecti= on *info) return smbd_post_send_iter(info, NULL, &remaining_data_length); } =20 -static int smbd_post_send_full_iter(struct smbd_connection *info, - struct iov_iter *iter, - int *_remaining_data_length) -{ - int rc =3D 0; - - /* - * smbd_post_send_iter() respects the - * negotiated max_send_size, so we need to - * loop until the full iter is posted - */ - - while (iov_iter_count(iter) > 0) { - rc =3D smbd_post_send_iter(info, iter, _remaining_data_length); - if (rc < 0) - break; - } - - return rc; -} - /* * Post a receive request to the transport * The remote peer can only send data when a receive request is posted @@ -1929,75 +1908,38 @@ int smbd_recv(struct smbd_connection *info, struct = msghdr *msg) =20 /* * Send data to transport - * Each rqst is transported as a SMBDirect payload - * rqst: the data to write * return value: 0 if successfully write, otherwise error code */ -int smbd_send(struct TCP_Server_Info *server, - int num_rqst, struct smb_rqst *rqst_array) +int smbd_send(struct TCP_Server_Info *server, struct iov_iter *iter) { struct smbd_connection *info =3D server->smbd_conn; struct smbdirect_socket *sc =3D &info->socket; struct smbdirect_socket_parameters *sp =3D &sc->parameters; - struct smb_rqst *rqst; - struct iov_iter iter; - unsigned int remaining_data_length, klen; - int rc, i, rqst_idx; + size_t size =3D iov_iter_count(iter); + unsigned int remain =3D 0; + int rc; =20 if (sc->status !=3D SMBDIRECT_SOCKET_CONNECTED) return -EAGAIN; =20 - /* - * Add in the page array if there is one. The caller needs to set - * rq_tailsz to PAGE_SIZE when the buffer has multiple pages and - * ends at page boundary - */ - remaining_data_length =3D 0; - for (i =3D 0; i < num_rqst; i++) - remaining_data_length +=3D smb_rqst_len(server, &rqst_array[i]); - - if (unlikely(remaining_data_length > sp->max_fragmented_send_size)) { + if (unlikely(size > sp->max_fragmented_send_size)) { /* assertion: payload never exceeds negotiated maximum */ - log_write(ERR, "payload size %d > max size %d\n", - remaining_data_length, sp->max_fragmented_send_size); + log_write(ERR, "payload size %zu > max size %d\n", + size, sp->max_fragmented_send_size); return -EINVAL; } =20 - log_write(INFO, "num_rqst=3D%d total length=3D%u\n", - num_rqst, remaining_data_length); - - rqst_idx =3D 0; - do { - rqst =3D &rqst_array[rqst_idx]; - - cifs_dbg(FYI, "Sending smb (RDMA): idx=3D%d smb_len=3D%lu\n", - rqst_idx, smb_rqst_len(server, rqst)); - for (i =3D 0; i < rqst->rq_nvec; i++) - dump_smb(rqst->rq_iov[i].iov_base, rqst->rq_iov[i].iov_len); - - log_write(INFO, "RDMA-WR[%u] nvec=3D%d len=3D%u iter=3D%zu rqlen=3D%lu\n= ", - rqst_idx, rqst->rq_nvec, remaining_data_length, - iov_iter_count(&rqst->rq_iter), smb_rqst_len(server, rqst)); + log_write(INFO, "size=3D%zu\n", size); =20 - /* Send the metadata pages. */ - klen =3D 0; - for (i =3D 0; i < rqst->rq_nvec; i++) - klen +=3D rqst->rq_iov[i].iov_len; - iov_iter_kvec(&iter, ITER_SOURCE, rqst->rq_iov, rqst->rq_nvec, klen); - - rc =3D smbd_post_send_full_iter(info, &iter, &remaining_data_length); + /* + * smbd_post_send_iter() respects the negotiated max_send_size, so we + * need to loop until the full iter is posted + */ + while (iov_iter_count(iter) > 0) { + rc =3D smbd_post_send_iter(info, iter, &remain); if (rc < 0) break; - - if (iov_iter_count(&rqst->rq_iter) > 0) { - /* And then the data pages if there are any */ - rc =3D smbd_post_send_full_iter(info, &rqst->rq_iter, - &remaining_data_length); - if (rc < 0) - break; - } - - } while (++rqst_idx < num_rqst); + } =20 /* * As an optimization, we don't wait for individual I/O to finish diff --git a/fs/smb/client/smbdirect.h b/fs/smb/client/smbdirect.h index 75b3f491c3ad..aec119d95c5c 100644 --- a/fs/smb/client/smbdirect.h +++ b/fs/smb/client/smbdirect.h @@ -214,8 +214,7 @@ void smbd_destroy(struct TCP_Server_Info *server); =20 /* Interface for carrying upper layer I/O through send/recv */ int smbd_recv(struct smbd_connection *info, struct msghdr *msg); -int smbd_send(struct TCP_Server_Info *server, - int num_rqst, struct smb_rqst *rqst); +int smbd_send(struct TCP_Server_Info *server, struct iov_iter *iter); =20 enum mr_state { MR_READY, @@ -254,7 +253,7 @@ static inline void *smbd_get_connection( static inline int smbd_reconnect(struct TCP_Server_Info *server) {return -= 1; } static inline void smbd_destroy(struct TCP_Server_Info *server) {} static inline int smbd_recv(struct smbd_connection *info, struct msghdr *m= sg) {return -1; } -static inline int smbd_send(struct TCP_Server_Info *server, int num_rqst, = struct smb_rqst *rqst) {return -1; } +static inline int smbd_send(struct TCP_Server_Info *server, struct iov_ite= r *iter) {return -1; } #endif =20 #endif diff --git a/fs/smb/client/transport.c b/fs/smb/client/transport.c index 288351c27fc4..6459acf959f3 100644 --- a/fs/smb/client/transport.c +++ b/fs/smb/client/transport.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include "rfc1002pdu.h" #include "cifspdu.h" #include "cifsglob.h" #include "cifsproto.h" @@ -244,6 +246,80 @@ smb_send_kvec(struct TCP_Server_Info *server, struct m= sghdr *smb_msg, return 0; } =20 +/* + * smb_sendmsg - send a buffer to the socket + * @server: Server to send the data to + * @smb_msg: Message to send + * @sent: amount of data sent on socket is stored here + * + * Our basic "send data to server" function. Should be called with srv_mut= ex + * held. The caller is responsible for handling the results. + */ +int smb_sendmsg(struct TCP_Server_Info *server, struct msghdr *smb_msg, + size_t *sent) +{ + int rc =3D 0; + int retries =3D 0; + struct socket *ssocket =3D server->ssocket; + + *sent =3D 0; + + if (server->noblocksnd) + smb_msg->msg_flags =3D MSG_DONTWAIT + MSG_NOSIGNAL; + else + smb_msg->msg_flags =3D MSG_NOSIGNAL; + smb_msg->msg_flags =3D MSG_SPLICE_PAGES; + + while (msg_data_left(smb_msg)) { + /* + * If blocking send, we try 3 times, since each can block + * for 5 seconds. For nonblocking we have to try more + * but wait increasing amounts of time allowing time for + * socket to clear. The overall time we wait in either + * case to send on the socket is about 15 seconds. + * Similarly we wait for 15 seconds for a response from + * the server in SendReceive[2] for the server to send + * a response back for most types of requests (except + * SMB Write past end of file which can be slow, and + * blocking lock operations). NFS waits slightly longer + * than CIFS, but this can make it take longer for + * nonresponsive servers to be detected and 15 seconds + * is more than enough time for modern networks to + * send a packet. In most cases if we fail to send + * after the retries we will kill the socket and + * reconnect which may clear the network problem. + */ + rc =3D sock_sendmsg(ssocket, smb_msg); + if (rc =3D=3D -EAGAIN) { + retries++; + if (retries >=3D 14 || + (!server->noblocksnd && (retries > 2))) { + cifs_server_dbg(VFS, "sends on sock %p stuck for 15 seconds\n", + ssocket); + return -EAGAIN; + } + msleep(1 << retries); + continue; + } + + if (rc < 0) + return rc; + + if (rc =3D=3D 0) { + /* should never happen, letting socket clear before + retrying is our only obvious option here */ + cifs_server_dbg(VFS, "tcp sent no data\n"); + msleep(500); + continue; + } + + /* send was at least partially successful */ + *sent +=3D rc; + retries =3D 0; /* in case we get ENOSPC on the next send */ + } + return 0; +} + unsigned long smb_rqst_len(struct TCP_Server_Info *server, struct smb_rqst *rqst) { @@ -269,26 +345,22 @@ smb_rqst_len(struct TCP_Server_Info *server, struct s= mb_rqst *rqst) return buflen; } =20 -int __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst, - struct smb_rqst *rqst) +int +__smb_send_rqst(struct TCP_Server_Info *server, struct iov_iter *iter) { - int rc; - struct kvec *iov; - int n_vec; + struct socket *ssocket =3D server->ssocket; + struct msghdr smb_msg =3D { .msg_iter =3D *iter, }; unsigned int send_length =3D 0; - unsigned int i, j; sigset_t mask, oldmask; - size_t total_len =3D 0, sent, size; - struct socket *ssocket =3D server->ssocket; - struct msghdr smb_msg =3D {}; - __be32 rfc1002_marker; + size_t total_len =3D 0, sent; + int rc; =20 cifs_in_send_inc(server); if (cifs_rdma_enabled(server)) { /* return -EAGAIN when connecting or reconnecting */ rc =3D -EAGAIN; if (server->smbd_conn) - rc =3D smbd_send(server, num_rqst, rqst); + rc =3D smbd_send(server, iter); goto smbd_done; } =20 @@ -306,10 +378,6 @@ int __smb_send_rqst(struct TCP_Server_Info *server, in= t num_rqst, /* cork the socket */ tcp_sock_set_cork(ssocket->sk, true); =20 - for (j =3D 0; j < num_rqst; j++) - send_length +=3D smb_rqst_len(server, &rqst[j]); - rfc1002_marker =3D cpu_to_be32(send_length); - /* * We should not allow signals to interrupt the network send because * any partial send will cause session reconnects thus increasing @@ -320,52 +388,9 @@ int __smb_send_rqst(struct TCP_Server_Info *server, in= t num_rqst, sigfillset(&mask); sigprocmask(SIG_BLOCK, &mask, &oldmask); =20 - /* Generate a rfc1002 marker for SMB2+ */ - if (!is_smb1(server)) { - struct kvec hiov =3D { - .iov_base =3D &rfc1002_marker, - .iov_len =3D 4 - }; - iov_iter_kvec(&smb_msg.msg_iter, ITER_SOURCE, &hiov, 1, 4); - rc =3D smb_send_kvec(server, &smb_msg, &sent); - if (rc < 0) - goto unmask; - - total_len +=3D sent; - send_length +=3D 4; - } - - cifs_dbg(FYI, "Sending smb: smb_len=3D%u\n", send_length); - - for (j =3D 0; j < num_rqst; j++) { - iov =3D rqst[j].rq_iov; - n_vec =3D rqst[j].rq_nvec; - - size =3D 0; - for (i =3D 0; i < n_vec; i++) { - dump_smb(iov[i].iov_base, iov[i].iov_len); - size +=3D iov[i].iov_len; - } - - iov_iter_kvec(&smb_msg.msg_iter, ITER_SOURCE, iov, n_vec, size); - - rc =3D smb_send_kvec(server, &smb_msg, &sent); - if (rc < 0) - goto unmask; + cifs_dbg(FYI, "Sending smb: smb_len=3D%zu\n", iov_iter_count(iter)); + rc =3D smb_sendmsg(server, &smb_msg, &sent); =20 - total_len +=3D sent; - - if (iov_iter_count(&rqst[j].rq_iter) > 0) { - smb_msg.msg_iter =3D rqst[j].rq_iter; - rc =3D smb_send_kvec(server, &smb_msg, &sent); - if (rc < 0) - break; - total_len +=3D sent; - } - -} - -unmask: sigprocmask(SIG_SETMASK, &oldmask, NULL); =20 /* @@ -379,7 +404,7 @@ int __smb_send_rqst(struct TCP_Server_Info *server, int= num_rqst, * won't be any response from the server to handle. */ =20 - if (signal_pending(current) && (total_len !=3D send_length)) { + if (signal_pending(current) && (total_len !=3D iov_iter_count(iter))) { cifs_dbg(FYI, "signal is pending after attempt to send\n"); rc =3D -ERESTARTSYS; } @@ -387,7 +412,7 @@ int __smb_send_rqst(struct TCP_Server_Info *server, int= num_rqst, /* uncork it */ tcp_sock_set_cork(ssocket->sk, false); =20 - if ((total_len > 0) && (total_len !=3D send_length)) { + if (total_len > 0 && total_len !=3D iov_iter_count(iter)) { cifs_dbg(FYI, "partial send (wanted=3D%u sent=3D%zu): terminating sessio= n\n", send_length, total_len); /* @@ -417,41 +442,137 @@ int __smb_send_rqst(struct TCP_Server_Info *server, = int num_rqst, return rc; } =20 +static size_t smb3_copy_data_iter(void *iter_from, size_t progress, size_t= len, + void *priv, void *priv2) +{ + struct iov_iter *iter =3D priv; + return copy_to_iter(iter_from, len, iter) =3D=3D len ? 0 : len; +} + +/* + * Copy the data into a buffer that we can use for encryption in place and= also + * pass to sendmsg() with MSG_SPLICE_PAGES. This avoids a lot of copies i= n TCP + * at the expense of an upfront here. A spare slot is left in the bvec qu= eue + * at the front for the header(s). + */ +static int smb_copy_data_into_buffer(struct TCP_Server_Info *server, + int num_rqst, struct smb_rqst *rqst, + struct iov_iter *iter, struct bvecq **_bq) +{ + struct bvecq *bq; + size_t total_len =3D 0, offset =3D 0; + + for (int i =3D 0; i < num_rqst; i++) { + struct smb_rqst *req =3D &rqst[i]; + size_t size =3D iov_iter_count(&req->rq_iter); + + for (int j =3D 0; j < req->rq_nvec; j++) + size +=3D req->rq_iov[j].iov_len; + total_len =3D ALIGN8(total_len); + total_len +=3D size; + } + + bq =3D netfs_alloc_bvecq_buffer(total_len, 1, GFP_NOFS); + if (!bq) + return -ENOMEM; + + iov_iter_bvec_queue(iter, ITER_DEST, bq, 1, 0, total_len); + + for (int i =3D 0; i < num_rqst; i++) { + struct smb_rqst *req =3D &rqst[i]; + size_t size =3D iov_iter_count(&req->rq_iter); + + if (offset & 7) { + unsigned int tmp =3D offset; + offset =3D ALIGN8(offset); + iov_iter_zero(offset - tmp, iter); + } + + for (int j =3D 0; j < req->rq_nvec; j++) { + size_t len =3D req->rq_iov[j].iov_len; + if (copy_to_iter(req->rq_iov[j].iov_base, len, iter) !=3D len) + goto error; + offset +=3D len; + } + + if (iterate_and_advance_kernel(&req->rq_iter, + size, iter, NULL, + smb3_copy_data_iter) !=3D size) + goto error; + + offset +=3D size; + } + + if (WARN_ONCE(offset !=3D total_len, + "offset=3D%zx total_len=3D%zx\n", offset, total_len)) { + goto error; + } + iov_iter_bvec_queue(iter, ITER_DEST, bq, 1, 0, total_len); + *_bq =3D bq; + return 0; +error: + netfs_free_bvecq_buffer(bq); + *_bq =3D NULL; + return -EIO; +} + static int smb_send_rqst(struct TCP_Server_Info *server, int num_rqst, struct smb_rqst *rqst, int flags) { - struct smb2_transform_hdr tr_hdr; - struct smb_rqst new_rqst[MAX_COMPOUND] =3D {}; - struct kvec iov =3D { - .iov_base =3D &tr_hdr, - .iov_len =3D sizeof(tr_hdr), - }; + struct smb2_transform_hdr *tr_hdr; + struct iov_iter iter; + struct bvecq *bq; + u32 content_len; int rc; =20 - if (flags & CIFS_COMPRESS_REQ) - return smb_compress(server, &rqst[0], __smb_send_rqst); - - if (!(flags & CIFS_TRANSFORM_REQ)) - return __smb_send_rqst(server, num_rqst, rqst); - - if (WARN_ON_ONCE(num_rqst > MAX_COMPOUND - 1)) - return -EIO; - - if (!server->ops->init_transform_rq) { + if ((flags & CIFS_TRANSFORM_REQ) && + !server->ops->init_transform_rq) { cifs_server_dbg(VFS, "Encryption requested but transform callback is mis= sing\n"); return -EIO; } =20 - new_rqst[0].rq_iov =3D &iov; - new_rqst[0].rq_nvec =3D 1; + rc =3D smb_copy_data_into_buffer(server, num_rqst, rqst, &iter, &bq); + if (rc) + return rc; + content_len =3D iov_iter_count(&iter); + + if (is_smb1(server)) { + iov_iter_bvec_queue(&iter, ITER_SOURCE, bq, 1, 0, content_len); + } else { + __le32 *rfc1002; + void *hdr_blob; + u32 hdr_len =3D 0; + + /* TODO: Allocate netmem here */ + rc =3D -ENOMEM; + hdr_blob =3D (void *)__get_free_page(GFP_NOFS); + if (!hdr_blob) + goto error; + + //if (flags & CIFS_COMPRESS_REQ) + // return smb_compress(server, &iter, &bq); + + /* Set the RFC1002 header at the front. */ + rfc1002 =3D hdr_blob; + *rfc1002 =3D cpu_to_be32(RFC1002_SESSION_MESSAGE << 24 | content_len); + + if (flags & CIFS_TRANSFORM_REQ) { + tr_hdr =3D hdr_blob + 4; + hdr_len +=3D sizeof(*tr_hdr); + iov_iter_bvec_queue(&iter, ITER_SOURCE, bq, 1, 0, content_len); + + rc =3D server->ops->init_transform_rq(server, num_rqst, rqst, tr_hdr, &= iter); + if (rc) + goto error; + } =20 - rc =3D server->ops->init_transform_rq(server, num_rqst + 1, - new_rqst, rqst); - if (!rc) { - rc =3D __smb_send_rqst(server, num_rqst + 1, new_rqst); - smb3_free_compound_rqst(num_rqst, &new_rqst[1]); + bvec_set_virt(&bq->bv[0], hdr_blob, hdr_len); + iov_iter_bvec_queue(&iter, ITER_SOURCE, bq, 0, 0, hdr_len + content_len); } + rc =3D __smb_send_rqst(server, &iter); +error: + netfs_free_bvecq_buffer(bq); return rc; } From nobody Thu Dec 18 03:20:29 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EFF342D0C60 for ; Wed, 6 Aug 2025 20:38:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512724; cv=none; b=oF+eQWWbmkNbkkA/N1BiGsUoXs1b/D421WXkpgE9WN3hIK3StklH6ym0lKzG1HqmjIdavJtKGnC2EcrksheJWcRr1IUmgas4CTS+KDJObcE27rf3rBLMoatmRti6McEEciGbsBwVgC6XzSkULGgbSdZINUE5FH1VJF9UVotnWnw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512724; c=relaxed/simple; bh=opiE35Rt9JSQmH+BQkXffbwbE089hXV3NX6PfZCng0o=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=WYccygxyZ2ofzUwga/yE7RSBViw+SrKK6a6R5fG/jTJznAjIVP5apRMBRFvNSmwkyFHFOvYNHC+mNyP9Mk45rh8435K70+2TJ57j3C6o4rapoqzdsRidOXacoEFoGoZoPYMVKYtFssAB2v0NJ3ymgzsF0f7f0DAgcYnrBTg52Is= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=MMRfoK4j; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="MMRfoK4j" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1754512722; h=from:from:reply-to:subject:subject: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=07VRXIBfvgv7/M7c2aX/ef138JEk7cb8LOoVOWgb+UY=; b=MMRfoK4jZCqY2U2RQcua92zLnz8G5fui1imRLXF+4h+p3qjIuM3jKtknWMGy/HGeHWzOhS yapROy/A/HcMZkddwnaZqZ6VeGkUB96QgNKPMdMhkOKSZE9um0K2+FA28KQkcCP1jxA+FD gE5LN70Z+3xrIzKJ+3suHWeMPksArNY= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-510-wi4ZoEewOyCnoGzN9CuKKw-1; Wed, 06 Aug 2025 16:38:39 -0400 X-MC-Unique: wi4ZoEewOyCnoGzN9CuKKw-1 X-Mimecast-MFC-AGG-ID: wi4ZoEewOyCnoGzN9CuKKw_1754512718 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 017AA195608E; Wed, 6 Aug 2025 20:38:38 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.17]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id E9EA530001A2; Wed, 6 Aug 2025 20:38:34 +0000 (UTC) From: David Howells To: Steve French Cc: David Howells , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Wang Zhaolong , Stefan Metzmacher , Mina Almasry , linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org, netfs@lists.linux.dev, linux-fsdevel@vger.kernel.org Subject: [RFC PATCH 17/31] cifs: Rework smb2 decryption Date: Wed, 6 Aug 2025 21:36:38 +0100 Message-ID: <20250806203705.2560493-18-dhowells@redhat.com> In-Reply-To: <20250806203705.2560493-1-dhowells@redhat.com> References: <20250806203705.2560493-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Howells cc: Steve French cc: Paulo Alcantara cc: Shyam Prasad N cc: Tom Talpey cc: linux-cifs@vger.kernel.org cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/smb/client/cifsglob.h | 60 ----------------- fs/smb/client/smb2ops.c | 138 +++++---------------------------------- 2 files changed, 15 insertions(+), 183 deletions(-) diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index ae06c2b5a9c8..1eed8a463b58 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h @@ -2280,66 +2280,6 @@ static inline void move_cifs_info_to_smb2(struct smb= 2_file_all_info *dst, const dst->FileNameLength =3D src->FileNameLength; } =20 -static inline int cifs_get_num_sgs(const struct smb_rqst *rqst, - int num_rqst, - const u8 *sig) -{ - unsigned int len, skip; - unsigned int nents =3D 0; - unsigned long addr; - size_t data_size; - int i, j; - - /* - * The first rqst has a transform header where the first 20 bytes are - * not part of the encrypted blob. - */ - skip =3D 20; - - /* Assumes the first rqst has a transform header as the first iov. - * I.e. - * rqst[0].rq_iov[0] is transform header - * rqst[0].rq_iov[1+] data to be encrypted/decrypted - * rqst[1+].rq_iov[0+] data to be encrypted/decrypted - */ - for (i =3D 0; i < num_rqst; i++) { - data_size =3D iov_iter_count(&rqst[i].rq_iter); - - /* We really don't want a mixture of pinned and unpinned pages - * in the sglist. It's hard to keep track of which is what. - * Instead, we convert to a BVEC-type iterator higher up. - */ - if (data_size && - WARN_ON_ONCE(user_backed_iter(&rqst[i].rq_iter))) - return -EIO; - - /* We also don't want to have any extra refs or pins to clean - * up in the sglist. - */ - if (data_size && - WARN_ON_ONCE(iov_iter_extract_will_pin(&rqst[i].rq_iter))) - return -EIO; - - for (j =3D 0; j < rqst[i].rq_nvec; j++) { - struct kvec *iov =3D &rqst[i].rq_iov[j]; - - addr =3D (unsigned long)iov->iov_base + skip; - if (is_vmalloc_or_module_addr((void *)addr)) { - len =3D iov->iov_len - skip; - nents +=3D DIV_ROUND_UP(offset_in_page(addr) + len, - PAGE_SIZE); - } else { - nents++; - } - skip =3D 0; - } - if (data_size) - nents +=3D iov_iter_npages(&rqst[i].rq_iter, INT_MAX); - } - nents +=3D DIV_ROUND_UP(offset_in_page(sig) + SMB2_SIGNATURE_SIZE, PAGE_S= IZE); - return nents; -} - /* We can not use the normal sg_set_buf() as we will sometimes pass a * stack object as buf. */ diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c index baa54e746f0f..5933757d0170 100644 --- a/fs/smb/client/smb2ops.c +++ b/fs/smb/client/smb2ops.c @@ -4186,94 +4186,11 @@ fill_transform_hdr(struct smb2_transform_hdr *tr_hd= r, unsigned int orig_len, get_random_bytes(&tr_hdr->Nonce, SMB3_AES_CCM_NONCE); } =20 -static void *smb2_aead_req_alloc(struct crypto_aead *tfm, const struct smb= _rqst *rqst, - int num_rqst, const u8 *sig, u8 **iv, - struct aead_request **req, struct sg_table *sgt, - unsigned int *num_sgs, size_t *sensitive_size) -{ - unsigned int req_size =3D sizeof(**req) + crypto_aead_reqsize(tfm); - unsigned int iv_size =3D crypto_aead_ivsize(tfm); - unsigned int len; - u8 *p; - - *num_sgs =3D cifs_get_num_sgs(rqst, num_rqst, sig); - if (IS_ERR_VALUE((long)(int)*num_sgs)) - return ERR_PTR(*num_sgs); - - len =3D iv_size; - len +=3D crypto_aead_alignmask(tfm) & ~(crypto_tfm_ctx_alignment() - 1); - len =3D ALIGN(len, crypto_tfm_ctx_alignment()); - len +=3D req_size; - len =3D ALIGN(len, __alignof__(struct scatterlist)); - len +=3D array_size(*num_sgs, sizeof(struct scatterlist)); - *sensitive_size =3D len; - - p =3D kvzalloc(len, GFP_NOFS); - if (!p) - return ERR_PTR(-ENOMEM); - - *iv =3D (u8 *)PTR_ALIGN(p, crypto_aead_alignmask(tfm) + 1); - *req =3D (struct aead_request *)PTR_ALIGN(*iv + iv_size, - crypto_tfm_ctx_alignment()); - sgt->sgl =3D (struct scatterlist *)PTR_ALIGN((u8 *)*req + req_size, - __alignof__(struct scatterlist)); - return p; -} - -static void *smb2_get_aead_req(struct crypto_aead *tfm, struct smb_rqst *r= qst, - int num_rqst, const u8 *sig, u8 **iv, - struct aead_request **req, struct scatterlist **sgl, - size_t *sensitive_size) -{ - struct sg_table sgtable =3D {}; - unsigned int skip, num_sgs, i, j; - ssize_t rc; - void *p; - - p =3D smb2_aead_req_alloc(tfm, rqst, num_rqst, sig, iv, req, &sgtable, - &num_sgs, sensitive_size); - if (IS_ERR(p)) - return ERR_CAST(p); - - sg_init_marker(sgtable.sgl, num_sgs); - - /* - * The first rqst has a transform header where the - * first 20 bytes are not part of the encrypted blob. - */ - skip =3D 20; - - for (i =3D 0; i < num_rqst; i++) { - struct iov_iter *iter =3D &rqst[i].rq_iter; - size_t count =3D iov_iter_count(iter); - - for (j =3D 0; j < rqst[i].rq_nvec; j++) { - cifs_sg_set_buf(&sgtable, - rqst[i].rq_iov[j].iov_base + skip, - rqst[i].rq_iov[j].iov_len - skip); - - /* See the above comment on the 'skip' assignment */ - skip =3D 0; - } - sgtable.orig_nents =3D sgtable.nents; - - rc =3D extract_iter_to_sg(iter, count, &sgtable, - num_sgs - sgtable.nents, 0); - iov_iter_revert(iter, rc); - sgtable.orig_nents =3D sgtable.nents; - } - - cifs_sg_set_buf(&sgtable, sig, SMB2_SIGNATURE_SIZE); - sg_mark_end(&sgtable.sgl[sgtable.nents - 1]); - *sgl =3D sgtable.sgl; - return p; -} - /* * Allocate the context info needed for the encryption operation, along wi= th a * scatterlist to point to the buffer. */ -static void *smb2_aead_req_alloc_new(struct crypto_aead *tfm, const struct= iov_iter *iter, +static void *smb2_aead_req_alloc(struct crypto_aead *tfm, const struct iov= _iter *iter, const u8 *sig, u8 **iv, struct aead_request **req, struct sg_table *sgt, unsigned int *num_sgs, size_t *sensitive_size) @@ -4309,10 +4226,10 @@ static void *smb2_aead_req_alloc_new(struct crypto_= aead *tfm, const struct iov_i * Set up for doing a crypto operation, building a scatterlist from the * supplied iterator. */ -static void *smb2_get_aead_req_new(struct crypto_aead *tfm, const struct i= ov_iter *iter, - const u8 *sig, u8 **iv, - struct aead_request **req, struct scatterlist **sgl, - size_t *sensitive_size) +static void *smb2_get_aead_req(struct crypto_aead *tfm, const struct iov_i= ter *iter, + const u8 *sig, u8 **iv, + struct aead_request **req, struct scatterlist **sgl, + size_t *sensitive_size) { struct sg_table sgtable =3D {}; struct iov_iter tmp =3D *iter; @@ -4320,8 +4237,8 @@ static void *smb2_get_aead_req_new(struct crypto_aead= *tfm, const struct iov_ite ssize_t rc; void *p; =20 - p =3D smb2_aead_req_alloc_new(tfm, iter, sig, iv, req, &sgtable, - &num_sgs, sensitive_size); + p =3D smb2_aead_req_alloc(tfm, iter, sig, iv, req, &sgtable, + &num_sgs, sensitive_size); if (IS_ERR(p)) return ERR_CAST(p); =20 @@ -4412,8 +4329,8 @@ encrypt_message(struct TCP_Server_Info *server, return rc; } =20 - creq =3D smb2_get_aead_req_new(tfm, iter, sign, &iv, &req, &sg, - &sensitive_size); + creq =3D smb2_get_aead_req(tfm, iter, sign, &iv, &req, &sg, + &sensitive_size); if (IS_ERR(creq)) return PTR_ERR(creq); =20 @@ -4446,11 +4363,10 @@ encrypt_message(struct TCP_Server_Info *server, * untouched. */ static int -decrypt_message(struct TCP_Server_Info *server, int num_rqst, - struct smb_rqst *rqst, struct crypto_aead *tfm) +decrypt_message(struct TCP_Server_Info *server, + struct smb2_transform_hdr *tr_hdr, + struct iov_iter *iter, struct crypto_aead *tfm) { - struct smb2_transform_hdr *tr_hdr =3D - (struct smb2_transform_hdr *)rqst[0].rq_iov[0].iov_base; unsigned int assoc_data_len =3D sizeof(struct smb2_transform_hdr) - 20; int rc =3D 0; struct scatterlist *sg; @@ -4486,8 +4402,7 @@ decrypt_message(struct TCP_Server_Info *server, int n= um_rqst, return rc; } =20 - creq =3D smb2_get_aead_req(tfm, rqst, num_rqst, sign, &iv, &req, &sg, - &sensitive_size); + creq =3D smb2_get_aead_req(tfm, iter, sign, &iv, &req, &sg, &sensitive_si= ze); if (IS_ERR(creq)) return PTR_ERR(creq); =20 @@ -4546,24 +4461,10 @@ decrypt_raw_data(struct TCP_Server_Info *server, ch= ar *buf, unsigned int buf_data_size, struct iov_iter *iter, bool is_offloaded) { + struct smb2_transform_hdr *tr_hdr =3D (struct smb2_transform_hdr *)buf; struct crypto_aead *tfm; - struct smb_rqst rqst =3D {NULL}; - struct kvec iov[2]; - size_t iter_size =3D 0; int rc; =20 - iov[0].iov_base =3D buf; - iov[0].iov_len =3D sizeof(struct smb2_transform_hdr); - iov[1].iov_base =3D buf + sizeof(struct smb2_transform_hdr); - iov[1].iov_len =3D buf_data_size; - - rqst.rq_iov =3D iov; - rqst.rq_nvec =3D 2; - if (iter) { - rqst.rq_iter =3D *iter; - iter_size =3D iov_iter_count(iter); - } - if (is_offloaded) { if ((server->cipher_type =3D=3D SMB2_ENCRYPTION_AES128_GCM) || (server->cipher_type =3D=3D SMB2_ENCRYPTION_AES256_GCM)) @@ -4583,20 +4484,11 @@ decrypt_raw_data(struct TCP_Server_Info *server, ch= ar *buf, tfm =3D server->secmech.dec; } =20 - rc =3D decrypt_message(server, 1, &rqst, tfm); + rc =3D decrypt_message(server, tr_hdr, iter, tfm); cifs_dbg(FYI, "Decrypt message returned %d\n", rc); =20 if (is_offloaded) crypto_free_aead(tfm); - - if (rc) - return rc; - - memmove(buf, iov[1].iov_base, buf_data_size); - - if (!is_offloaded) - server->total_read =3D buf_data_size + iter_size; - return rc; } From nobody Thu Dec 18 03:20:29 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6368E2BE65B for ; Wed, 6 Aug 2025 20:38:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512736; cv=none; b=psPLpmVgHa//PauUhQi1HhfaUagy7bMhDma3gLRSv49TMTnB8YURf2SjELZrAGSLKI2+iq8O/FnE2gAWihEbbGWkx9wpNWrRihApPH8ATIw4/+J/+lmQqdnO+OB2TxZmZpGLFe20S4xT+Tu1VHG/4+YLqEsr1EAY7e3UctJNbZ8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512736; c=relaxed/simple; bh=/KYLWM66HsCIyLrUD2j4x9ZdDVeh1/ghbwWgJ/qIhSU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=i+JDLy8VF0bgajLoErX/vGVuU2fCmJJsj1ymbguj3T0Mk39x+np1+OMPokIC2RGkEg5+ojNw4g7h0mkSAsSSUXTr9SOIKuHtccJImna/xQKrdMkilaE0za34qTwwT/399MjqB5/pPh7LmtGSRo4Us5UhEpsb5hHWiAPJHFAHhvE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=Mif45bl1; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="Mif45bl1" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1754512731; h=from:from:reply-to:subject:subject: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=EE4nIVk7xOe+TmD1HbRuyEA8rxzcr7xUzi3JYj5/pKs=; b=Mif45bl1WQ760jlKpnZCcw/cSlpG+SDo2rrCOhLiX55URGmwBbo9MOiqClwUsudSk/VCsC 3d1QNOvd/V1Lu0xbg9BncvBWENgGoaQSfLtw3bqUHRuBF4a6FJ3udzVkYXLE5EUDQ1oDRX enqVncpEVFoae72ihDPAR6D9DXlpDbM= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-407-MW2HQGbPPXW6kZm-6mDnBg-1; Wed, 06 Aug 2025 16:38:44 -0400 X-MC-Unique: MW2HQGbPPXW6kZm-6mDnBg-1 X-Mimecast-MFC-AGG-ID: MW2HQGbPPXW6kZm-6mDnBg_1754512723 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 111D7195419B; Wed, 6 Aug 2025 20:38:43 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.17]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 8D676180035C; Wed, 6 Aug 2025 20:38:39 +0000 (UTC) From: David Howells To: Steve French Cc: David Howells , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Wang Zhaolong , Stefan Metzmacher , Mina Almasry , linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org, netfs@lists.linux.dev, linux-fsdevel@vger.kernel.org Subject: [RFC PATCH 18/31] cifs: Pass smb_message structs down into the transport layer Date: Wed, 6 Aug 2025 21:36:39 +0100 Message-ID: <20250806203705.2560493-19-dhowells@redhat.com> In-Reply-To: <20250806203705.2560493-1-dhowells@redhat.com> References: <20250806203705.2560493-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Content-Type: text/plain; charset="utf-8" Institute the creation of smb_message structs at the layer above the transport layer and pass them down into the transport layer. This replaces the handling of mid_q_structs entirely within the transport layer. This includes the following changes: (1) The smb_rqst struct is partially absorbed into the smb_message struct. Because the latter is on a linked list, the fixed-size arrays of requests can be got rid of - along with the COMPOUND_MAX-1 limit that gets imposed by the encryption code because it needs to steal a slot for the transform header. (2) Hand smb_message structs into the message sending code in the transport rather than allocating them (as it did for mid_q_structs) in the ->setup_request/->setup_async_request functions. For the moment compound_send_rcv() does the generation of smb_message structs, stringing them together before passing them down. Signed-off-by: David Howells cc: Steve French cc: Paulo Alcantara cc: Shyam Prasad N cc: Tom Talpey cc: linux-cifs@vger.kernel.org cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/smb/client/cifsglob.h | 38 ++-- fs/smb/client/cifsproto.h | 39 ++-- fs/smb/client/cifssmb.c | 1 - fs/smb/client/cifstransport.c | 8 +- fs/smb/client/compress.h | 6 +- fs/smb/client/connect.c | 24 +-- fs/smb/client/netmisc.c | 5 +- fs/smb/client/smb1ops.c | 19 +- fs/smb/client/smb2misc.c | 45 ++--- fs/smb/client/smb2ops.c | 40 +++-- fs/smb/client/smb2pdu.c | 212 +++++++++++++--------- fs/smb/client/smb2proto.h | 31 ++-- fs/smb/client/smb2transport.c | 183 +++++++------------ fs/smb/client/transport.c | 325 +++++++++++++++++++--------------- 14 files changed, 501 insertions(+), 475 deletions(-) diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index 1eed8a463b58..4173b87bdf0f 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h @@ -313,26 +313,24 @@ struct cifs_credits; =20 struct smb_version_operations { int (*send_cancel)(struct cifs_ses *ses, struct TCP_Server_Info *server, - struct smb_rqst *rqst, struct smb_message *smb, - unsigned int xid); + struct smb_message *smb, unsigned int xid); bool (*compare_fids)(struct cifsFileInfo *, struct cifsFileInfo *); - /* setup request: allocate mid, sign message */ - struct smb_message *(*setup_request)(struct cifs_ses *, - struct TCP_Server_Info *, - struct smb_rqst *); + /* setup request: set up mid, sign message */ + int (*setup_request)(struct cifs_ses *ses, + struct TCP_Server_Info *server, + struct smb_message *smb); /* setup async request: allocate mid, sign message */ - struct smb_message *(*setup_async_request)(struct TCP_Server_Info *, - struct smb_rqst *); + int (*setup_async_request)(struct TCP_Server_Info *server, struct smb_mes= sage *smb); /* check response: verify signature, map error */ - int (*check_receive)(struct smb_message *, struct TCP_Server_Info *, - bool); + int (*check_receive)(struct smb_message *smb, struct TCP_Server_Info *ser= ver, + bool log_error); void (*add_credits)(struct TCP_Server_Info *server, struct cifs_credits *credits, const int optype); void (*set_credits)(struct TCP_Server_Info *, const int); int * (*get_credits_field)(struct TCP_Server_Info *, const int); unsigned int (*get_credits)(struct smb_message *smb); - __u64 (*get_next_mid)(struct TCP_Server_Info *); + __u64 (*get_next_mid)(struct TCP_Server_Info *server, unsigned int count); void (*revert_current_mid)(struct TCP_Server_Info *server, const unsigned int val); /* data offset from read response message */ @@ -537,8 +535,8 @@ struct smb_version_operations { void (*new_lease_key)(struct cifs_fid *); int (*generate_signingkey)(struct cifs_ses *ses, struct TCP_Server_Info *server); - int (*calc_signature)(struct smb_rqst *, struct TCP_Server_Info *, - bool allocate_crypto); + int (*calc_signature)(struct smb_message *smb, struct TCP_Server_Info *se= rver, + bool allocate_crypto); int (*set_integrity)(const unsigned int, struct cifs_tcon *tcon, struct cifsFileInfo *src_file); int (*enum_snapshots)(const unsigned int xid, struct cifs_tcon *tcon, @@ -594,10 +592,8 @@ struct smb_version_operations { long (*fallocate)(struct file *, struct cifs_tcon *, int, loff_t, loff_t); /* init transform (compress/encrypt) request */ - int (*init_transform_rq)(struct TCP_Server_Info *server, - int num_rqst, const struct smb_rqst *rqst, - struct smb2_transform_hdr *tr_hdr, - struct iov_iter *iter); + int (*init_transform_rq)(struct TCP_Server_Info *server, struct smb_messa= ge *head_smb, + struct smb2_transform_hdr *tr_hdr, struct iov_iter *iter); int (*is_transform_hdr)(void *buf); int (*receive_transform)(struct TCP_Server_Info *, struct smb_message **smb, char **, int *); @@ -945,16 +941,16 @@ adjust_credits(struct TCP_Server_Info *server, struct= cifs_io_subrequest *subreq server->ops->adjust_credits(server, subreq, trace) : 0; } =20 -static inline __le64 -get_next_mid64(struct TCP_Server_Info *server) +static inline __u64 +get_next_mid64(struct TCP_Server_Info *server, unsigned int count) { - return cpu_to_le64(server->ops->get_next_mid(server)); + return server->ops->get_next_mid(server, count); } =20 static inline __le16 get_next_mid(struct TCP_Server_Info *server) { - __u16 mid =3D server->ops->get_next_mid(server); + __u16 mid =3D server->ops->get_next_mid(server, 1); /* * The value in the SMB header should be little endian for easy * on-the-wire decoding. diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h index 76cb047b2715..fd5fe2723b4a 100644 --- a/fs/smb/client/cifsproto.h +++ b/fs/smb/client/cifsproto.h @@ -83,8 +83,6 @@ extern char *cifs_build_path_to_root(struct smb3_fs_conte= xt *ctx, int add_treename); extern char *build_wildcard_path_from_dentry(struct dentry *direntry); char *cifs_build_devname(char *nodename, const char *prepath); -extern void delete_mid(struct smb_message *smb); -void __release_mid(struct smb_message *smb); extern void cifs_wake_up_task(struct smb_message *smb); extern int cifs_handle_standard(struct TCP_Server_Info *server, struct smb_message *smb); @@ -96,15 +94,16 @@ extern int cifs_ipaddr_cmp(struct sockaddr *srcaddr, st= ruct sockaddr *rhs); extern bool cifs_match_ipaddr(struct sockaddr *srcaddr, struct sockaddr *r= hs); extern int cifs_discard_remaining_data(struct TCP_Server_Info *server); extern int cifs_call_async(struct TCP_Server_Info *server, - struct smb_rqst *rqst, - mid_receive_t receive, mid_callback_t callback, - mid_handle_t handle, void *cbdata, const int flags, - const struct cifs_credits *exist_credits); + struct smb_message *msg, const int flags, + const struct cifs_credits *exist_credits); extern struct TCP_Server_Info *cifs_pick_channel(struct cifs_ses *ses); extern int cifs_send_recv(const unsigned int xid, struct cifs_ses *ses, struct TCP_Server_Info *server, struct smb_rqst *rqst, int *resp_buf_type, const int flags, struct kvec *resp_iov); +int smb_send_recv_messages(const unsigned int xid, struct cifs_ses *ses, + struct TCP_Server_Info *server, + struct smb_message *smb, const int flags); extern int compound_send_recv(const unsigned int xid, struct cifs_ses *ses, struct TCP_Server_Info *server, const int flags, const int num_rqst, @@ -117,14 +116,14 @@ extern int SendReceive(const unsigned int /* xid */ ,= struct cifs_ses *, extern int SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses, char *in_buf, int flags); int cifs_sync_mid_result(struct smb_message *smb, struct TCP_Server_Info *= server); -extern struct smb_message *cifs_setup_request(struct cifs_ses *, - struct TCP_Server_Info *, - struct smb_rqst *); -extern struct smb_message *cifs_setup_async_request(struct TCP_Server_Info= *, - struct smb_rqst *); +int cifs_setup_request(struct cifs_ses *ses, + struct TCP_Server_Info *server, + struct smb_message *smb); +int cifs_setup_async_request(struct TCP_Server_Info *server, + struct smb_message *smb); int __smb_send_rqst(struct TCP_Server_Info *server, struct iov_iter *iter); -extern int cifs_check_receive(struct smb_message *msg, - struct TCP_Server_Info *server, bool log_error); +int cifs_check_receive(struct smb_message *smb, + struct TCP_Server_Info *server, bool log_error); int wait_for_free_request(struct TCP_Server_Info *server, const int flags, unsigned int *instance); extern int cifs_wait_mtu_credits(struct TCP_Server_Info *server, @@ -133,11 +132,10 @@ extern int cifs_wait_mtu_credits(struct TCP_Server_In= fo *server, =20 static inline int send_cancel(struct cifs_ses *ses, struct TCP_Server_Info *server, - struct smb_rqst *rqst, struct smb_message *smb, - unsigned int xid) + struct smb_message *smb, unsigned int xid) { return server->ops->send_cancel ? - server->ops->send_cancel(ses, server, rqst, smb, xid) : 0; + server->ops->send_cancel(ses, server, smb, xid) : 0; } =20 int wait_for_response(struct TCP_Server_Info *server, struct smb_message *= smb); @@ -181,7 +179,8 @@ extern int decode_negTokenInit(unsigned char *security_= blob, int length, extern int cifs_convert_address(struct sockaddr *dst, const char *src, int= len); extern void cifs_set_port(struct sockaddr *addr, const unsigned short int = port); extern int map_smb_to_linux_error(char *buf, bool logErr); -extern int map_and_check_smb_error(struct smb_message *smb, bool logErr); +extern int map_and_check_smb_error(struct TCP_Server_Info *server, + struct smb_message *smb, bool logErr); extern void header_assemble(struct smb_hdr *, char /* command */ , const struct cifs_tcon *, int /* length of fixed section (word count) in two byte units */); @@ -754,12 +753,6 @@ static inline bool dfs_src_pathname_equal(const char *= s1, const char *s2) return true; } =20 -static inline void release_mid(struct smb_message *smb) -{ - if (refcount_dec_and_test(&smb->ref)) - __release_mid(smb); -} - static inline void cifs_free_open_info(struct cifs_open_info_data *data) { kfree(data->symlink_target); diff --git a/fs/smb/client/cifssmb.c b/fs/smb/client/cifssmb.c index a7a9f63f8c21..789ce76e3154 100644 --- a/fs/smb/client/cifssmb.c +++ b/fs/smb/client/cifssmb.c @@ -582,7 +582,6 @@ cifs_echo_callback(struct smb_message *smb) struct TCP_Server_Info *server =3D smb->callback_data; struct cifs_credits credits =3D { .value =3D 1, .instance =3D 0 }; =20 - release_mid(smb); add_credits(server, &credits, CIFS_ECHO_OP); } =20 diff --git a/fs/smb/client/cifstransport.c b/fs/smb/client/cifstransport.c index a2db95faeb17..8cdb9252a37e 100644 --- a/fs/smb/client/cifstransport.c +++ b/fs/smb/client/cifstransport.c @@ -101,8 +101,8 @@ static int allocate_mid(struct cifs_ses *ses, struct sm= b_hdr *in_buf, return 0; } =20 -struct smb_message * -cifs_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *= rqst) +int +cifs_setup_async_request(struct TCP_Server_Info *server, struct smb_messag= e *smb) { int rc; struct smb_hdr *hdr =3D (struct smb_hdr *)rqst->rq_iov[0].iov_base; @@ -181,9 +181,9 @@ cifs_check_receive(struct smb_message *smb, struct TCP_= Server_Info *server, return map_and_check_smb_error(smb, log_error); } =20 -struct smb_message * +int cifs_setup_request(struct cifs_ses *ses, struct TCP_Server_Info *ignored, - struct smb_rqst *rqst) + struct smb_message *smb) { int rc; struct smb_hdr *hdr =3D (struct smb_hdr *)rqst->rq_iov[0].iov_base; diff --git a/fs/smb/client/compress.h b/fs/smb/client/compress.h index f3ed1d3e52fb..472b0e8b2f45 100644 --- a/fs/smb/client/compress.h +++ b/fs/smb/client/compress.h @@ -35,7 +35,7 @@ int smb_compress(struct TCP_Server_Info *server, struct s= mb_rqst *rq, compress_s * should_compress() - Determines if a request (write) or the response to a * request (read) should be compressed. * @tcon: tcon of the request is being sent to - * @rqst: request to evaluate + * @smb: request to evaluate * * Return: true iff: * - compression was successfully negotiated with server @@ -46,7 +46,7 @@ int smb_compress(struct TCP_Server_Info *server, struct s= mb_rqst *rq, compress_s * * Return false otherwise. */ -bool should_compress(const struct cifs_tcon *tcon, const struct smb_rqst *= rq); +bool should_compress(const struct cifs_tcon *tcon, const struct smb_messag= e *smb); =20 /** * smb_compress_alg_valid() - Validate a compression algorithm. @@ -77,7 +77,7 @@ static inline int smb_compress(void *unused1, void *unuse= d2, void *unused3) return -EOPNOTSUPP; } =20 -static inline bool should_compress(void *unused1, void *unused2) +static inline bool should_compress(const struct cifs_tcon *tcon, const str= uct smb_message *smb) { return false; } diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c index d26e2a6d7674..7a64b070f74b 100644 --- a/fs/smb/client/connect.c +++ b/fs/smb/client/connect.c @@ -323,7 +323,6 @@ cifs_abort_connection(struct TCP_Server_Info *server) cifs_dbg(FYI, "%s: moving mids to private list\n", __func__); spin_lock(&server->mid_lock); list_for_each_entry_safe(smb, nsmb, &server->pending_mid_q, qhead) { - smb_get_message(smb); if (smb->mid_state =3D=3D MID_REQUEST_SUBMITTED) smb->mid_state =3D MID_RETRY_NEEDED; list_move(&smb->qhead, &retry_list); @@ -336,7 +335,7 @@ cifs_abort_connection(struct TCP_Server_Info *server) list_for_each_entry_safe(smb, nsmb, &retry_list, qhead) { list_del_init(&smb->qhead); smb->callback(smb); - release_mid(smb); + smb_put_message(smb); } =20 if (cifs_rdma_enabled(server)) { @@ -871,9 +870,9 @@ is_smb_response(struct TCP_Server_Info *server, unsigne= d char type) server->tcpStatus =3D=3D CifsInNegotiate && !server->with_rfc1001 && server->rfc1001_sessinit !=3D 0) { - int rc, mid_rc; struct smb_message *smb, *nsmb; LIST_HEAD(dispose_list); + int rc, mid_rc; =20 cifs_dbg(FYI, "RFC 1002 negative session response during SMB Negotiate,= retrying with NetBIOS session\n"); =20 @@ -886,7 +885,6 @@ is_smb_response(struct TCP_Server_Info *server, unsigne= d char type) */ spin_lock(&server->mid_lock); list_for_each_entry_safe(smb, nsmb, &server->pending_mid_q, qhead) { - smb_get_message(smb); list_move(&smb->qhead, &dispose_list); smb->mid_flags |=3D MID_DELETED; } @@ -920,7 +918,7 @@ is_smb_response(struct TCP_Server_Info *server, unsigne= d char type) smb->mid_rc =3D mid_rc; smb->mid_state =3D MID_RC; smb->callback(smb); - release_mid(smb); + smb_put_message(smb); } =20 /* @@ -1097,15 +1095,12 @@ clean_demultiplex_info(struct TCP_Server_Info *serv= er) } =20 if (!list_empty(&server->pending_mid_q)) { - struct smb_message *smb; - struct list_head *tmp, *tmp2; + struct smb_message *smb, *smb2; LIST_HEAD(dispose_list); =20 spin_lock(&server->mid_lock); - list_for_each_safe(tmp, tmp2, &server->pending_mid_q) { - smb =3D list_entry(tmp, struct smb_message, qhead); + list_for_each_entry_safe(smb, smb2, &server->pending_mid_q, qhead) { cifs_dbg(FYI, "Clearing mid %llu\n", smb->mid); - smb_get_message(smb); smb->mid_state =3D MID_SHUTDOWN; list_move(&smb->qhead, &dispose_list); smb->mid_flags |=3D MID_DELETED; @@ -1113,12 +1108,11 @@ clean_demultiplex_info(struct TCP_Server_Info *serv= er) spin_unlock(&server->mid_lock); =20 /* now walk dispose list and issue callbacks */ - list_for_each_safe(tmp, tmp2, &dispose_list) { - smb =3D list_entry(tmp, struct smb_message, qhead); + list_for_each_entry_safe(smb, smb2, &dispose_list, qhead) { cifs_dbg(FYI, "Callback mid %llu\n", smb->mid); list_del_init(&smb->qhead); smb->callback(smb); - release_mid(smb); + smb_put_message(smb); } /* 1/8th of sec is more than enough time for them to exit */ msleep(125); @@ -1361,7 +1355,7 @@ cifs_demultiplex_thread(void *p) if (length < 0) { for (i =3D 0; i < num_smbs; i++) if (smbs[i]) - release_mid(smbs[i]); + smb_put_message(smbs[i]); continue; } =20 @@ -1396,7 +1390,7 @@ cifs_demultiplex_thread(void *p) if (!smbs[i]->multiRsp || smbs[i]->multiEnd) smbs[i]->callback(smbs[i]); =20 - release_mid(smbs[i]); + smb_put_message(smbs[i]); } else if (server->ops->is_oplock_break && server->ops->is_oplock_break(bufs[i], server)) { diff --git a/fs/smb/client/netmisc.c b/fs/smb/client/netmisc.c index b34d2b91cf5a..89bd1ca9e3ce 100644 --- a/fs/smb/client/netmisc.c +++ b/fs/smb/client/netmisc.c @@ -889,7 +889,8 @@ map_smb_to_linux_error(char *buf, bool logErr) } =20 int -map_and_check_smb_error(struct smb_message *smb, bool logErr) +map_and_check_smb_error(struct TCP_Server_Info *server, + struct smb_message *smb, bool logErr) { int rc; struct smb_hdr *rhdr =3D (struct smb_hdr *)smb->resp_buf; @@ -904,7 +905,7 @@ map_and_check_smb_error(struct smb_message *smb, bool l= ogErr) if (class =3D=3D ERRSRV && code =3D=3D ERRbaduid) { cifs_dbg(FYI, "Server returned 0x%x, reconnecting session...\n", code); - cifs_signal_cifsd_for_reconnect(smb->server, false); + cifs_signal_cifsd_for_reconnect(server, false); } } =20 diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c index 185210b7fd03..f179f1b4c0c1 100644 --- a/fs/smb/client/smb1ops.c +++ b/fs/smb/client/smb1ops.c @@ -29,11 +29,10 @@ */ static int send_nt_cancel(struct cifs_ses *ses, struct TCP_Server_Info *server, - struct smb_rqst *rqst, struct smb_message *smb, - unsigned int xid) + struct smb_message *smb, unsigned int xid) { struct iov_iter iter; - struct smb_hdr *in_buf =3D (struct smb_hdr *)rqst->rq_iov[0].iov_base; + struct smb_hdr *in_buf =3D (struct smb_hdr *)smb->rqst.rq_iov[0].iov_base; struct kvec iov[1]; struct smb_rqst crqst =3D { .rq_iov =3D iov, .rq_nvec =3D 1 }; int rc =3D 0; @@ -80,10 +79,9 @@ send_nt_cancel(struct cifs_ses *ses, struct TCP_Server_I= nfo *server, */ static int send_lock_cancel(struct cifs_ses *ses, struct TCP_Server_Info *server, - struct smb_rqst *rqst, struct smb_message *smb, - unsigned int xid) + struct smb_message *smb, unsigned int xid) { - struct smb_hdr *in_buf =3D (struct smb_hdr *)rqst->rq_iov[0].iov_base; + struct smb_hdr *in_buf =3D (struct smb_hdr *)smb->rqst.rq_iov[0].iov_base; LOCK_REQ *pSMB =3D (LOCK_REQ *)in_buf; int rc; =20 @@ -104,12 +102,11 @@ send_lock_cancel(struct cifs_ses *ses, struct TCP_Ser= ver_Info *server, } =20 static int cifs_send_cancel(struct cifs_ses *ses, struct TCP_Server_Info *= server, - struct smb_rqst *rqst, struct smb_message *smb, - unsigned int xid) + struct smb_message *smb, unsigned int xid) { if (smb->sr_flags & CIFS_WINDOWS_LOCK) - return send_lock_cancel(ses, server, rqst, smb, xid); - return send_nt_cancel(ses, server, rqst, smb, xid); + return send_lock_cancel(ses, server, smb, xid); + return send_nt_cancel(ses, server, smb, xid); } =20 static bool @@ -210,7 +207,7 @@ cifs_get_credits(struct smb_message *smb) * so many threads being in the vfs at one time. */ static __u64 -cifs_get_next_mid(struct TCP_Server_Info *server) +cifs_get_next_mid(struct TCP_Server_Info *server, unsigned int count) { __u64 mid =3D 0; __u16 last_mid, cur_mid; diff --git a/fs/smb/client/smb2misc.c b/fs/smb/client/smb2misc.c index b8e3fe26d658..122e9fe78e23 100644 --- a/fs/smb/client/smb2misc.c +++ b/fs/smb/client/smb2misc.c @@ -866,27 +866,22 @@ smb2_handle_cancelled_mid(struct smb_message *smb, st= ruct TCP_Server_Info *serve } =20 /** - * smb311_update_preauth_hash - update @ses hash with the packet data in @= iov - * - * Assumes @iov does not contain the rfc1002 length and iov[0] has the - * SMB2 header. - * + * smb311_update_preauth_hash - update @ses hash from the message * @ses: server session structure * @server: pointer to server info - * @iov: array containing the SMB request we will send to the server - * @nvec: number of array entries for the iov + * @smb: the SMB request we will send to the server + * @hash_resp: T if we're hashing a response */ int smb311_update_preauth_hash(struct cifs_ses *ses, struct TCP_Server_Info *s= erver, - struct kvec *iov, int nvec) + struct smb_message *smb, bool hash_resp) { - int i, rc; - struct smb2_hdr *hdr; struct shash_desc *sha512 =3D NULL; + struct kvec *iov; + int i, rc, ioc; =20 - hdr =3D (struct smb2_hdr *)iov[0].iov_base; /* neg prot are always taken */ - if (le16_to_cpu(hdr->Command) =3D=3D SMB2_NEGOTIATE) + if (smb->command_id =3D=3D SMB2_NEGOTIATE) goto ok; =20 /* @@ -897,15 +892,16 @@ smb311_update_preauth_hash(struct cifs_ses *ses, stru= ct TCP_Server_Info *server, if (server->dialect !=3D SMB311_PROT_ID) return 0; =20 - if (le16_to_cpu(hdr->Command) !=3D SMB2_SESSION_SETUP) + if (smb->command_id !=3D SMB2_SESSION_SETUP) return 0; =20 /* skip last sess setup response */ - if ((hdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR) - && (hdr->Status =3D=3D NT_STATUS_OK - || (hdr->Status !=3D - cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED)))) - return 0; + if (hash_resp) { + struct smb2_hdr *resp =3D smb->resp_iov->iov_base; + if (resp->Status =3D=3D NT_STATUS_OK || + resp->Status !=3D cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED)) + return 0; + } =20 ok: rc =3D smb311_crypto_shash_allocate(server); @@ -926,8 +922,17 @@ smb311_update_preauth_hash(struct cifs_ses *ses, struc= t TCP_Server_Info *server, return rc; } =20 - for (i =3D 0; i < nvec; i++) { - rc =3D crypto_shash_update(sha512, iov[i].iov_base, iov[i].iov_len); + if (hash_resp) { + ioc =3D 1; + iov =3D smb->resp_iov; + } else { + ioc =3D smb->rqst.rq_nvec; + iov =3D smb->rqst.rq_iov; + } + + for (i =3D 0; i < ioc; i++) { + rc =3D crypto_shash_update(sha512, iov[i].iov_base, + iov[i].iov_len); if (rc) { cifs_dbg(VFS, "%s: Could not update sha512 shash\n", __func__); diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c index 5933757d0170..835a76169d40 100644 --- a/fs/smb/client/smb2ops.c +++ b/fs/smb/client/smb2ops.c @@ -370,12 +370,13 @@ smb2_adjust_credits(struct TCP_Server_Info *server, } =20 static __u64 -smb2_get_next_mid(struct TCP_Server_Info *server) +smb2_get_next_mid(struct TCP_Server_Info *server, unsigned int count) { __u64 mid; /* for SMB2 we need the current value */ spin_lock(&server->mid_lock); - mid =3D server->CurrentMid++; + mid =3D server->CurrentMid; + server->CurrentMid =3D mid + umax(count, 1); spin_unlock(&server->mid_lock); return mid; } @@ -407,7 +408,6 @@ __smb2_find_mid(struct TCP_Server_Info *server, char *b= uf, bool dequeue) if ((smb->mid =3D=3D wire_mid) && (smb->mid_state =3D=3D MID_REQUEST_SUBMITTED) && (smb->command_id =3D=3D command)) { - smb_get_message(smb); if (dequeue) { list_del_init(&smb->qhead); smb->mid_flags |=3D MID_DELETED; @@ -4168,10 +4168,12 @@ smb2_dir_needs_close(struct cifsFileInfo *cfile) } =20 static void -fill_transform_hdr(struct smb2_transform_hdr *tr_hdr, unsigned int orig_le= n, - const struct smb_rqst *old_rq, __le16 cipher_type) +fill_transform_hdr(struct smb2_transform_hdr *tr_hdr, + struct smb_message *head_smb, + unsigned int orig_len, + __le16 cipher_type) { - struct smb2_hdr *shdr =3D (struct smb2_hdr *)old_rq->rq_iov[0].iov_base; + struct smb2_hdr *shdr =3D head_smb->request; =20 *tr_hdr =3D (struct smb2_transform_hdr){ .ProtocolId =3D SMB2_TRANSFORM_PROTO_NUM, @@ -4422,7 +4424,6 @@ decrypt_message(struct TCP_Server_Info *server, aead_request_set_ad(req, assoc_data_len); =20 rc =3D crypto_aead_decrypt(req); - kvfree_sensitive(creq, sensitive_size); return rc; } @@ -4434,13 +4435,14 @@ decrypt_message(struct TCP_Server_Info *server, */ static int smb3_init_transform_rq(struct TCP_Server_Info *server, - int num_rqst, const struct smb_rqst *rqst, + struct smb_message *head_smb, struct smb2_transform_hdr *tr_hdr, struct iov_iter *iter) + { int rc; =20 - fill_transform_hdr(tr_hdr, iov_iter_count(iter), rqst, + fill_transform_hdr(tr_hdr, head_smb, iov_iter_count(iter), server->cipher_type); =20 rc =3D encrypt_message(server, tr_hdr, iter, server->secmech.enc); @@ -4689,9 +4691,9 @@ static void smb2_decrypt_offload(struct work_struct *= work) =20 dw->server->lstrp =3D jiffies; smb =3D smb2_find_dequeue_mid(dw->server, dw->buf); - if (smb =3D=3D NULL) + if (smb =3D=3D NULL) { cifs_dbg(FYI, "mid not found\n"); - else { + } else { smb->decrypted =3D true; rc =3D handle_read_data(dw->server, smb, dw->buf, dw->server->vals->read_rsp_size, @@ -4724,7 +4726,7 @@ static void smb2_decrypt_offload(struct work_struct *= work) spin_unlock(&dw->server->srv_lock); } } - release_mid(smb); + smb_put_message(smb); } =20 free_pages: @@ -4735,9 +4737,12 @@ static void smb2_decrypt_offload(struct work_struct = *work) =20 =20 static int -receive_encrypted_read(struct TCP_Server_Info *server, struct smb_message = **smb, +receive_encrypted_read(struct TCP_Server_Info *server, struct smb_message = **mid, int *num_mids) { + WARN_ON_ONCE(1); + return -ENOANO; // TODO +#if 0 char *buf =3D server->smallbuf; struct smb2_transform_hdr *tr_hdr =3D (struct smb2_transform_hdr *)buf; struct iov_iter iter; @@ -4753,8 +4758,8 @@ receive_encrypted_read(struct TCP_Server_Info *server= , struct smb_message **smb, dw->server =3D server; =20 *num_mids =3D 1; - len =3D min_t(unsigned int, buflen, server->vals->read_rsp_size + - sizeof(struct smb2_transform_hdr)) - HEADER_SIZE(server) + 1; + len =3D umin(buflen, server->vals->read_rsp_size + + sizeof(struct smb2_transform_hdr)) - HEADER_SIZE(server) + 1; =20 rc =3D cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1, len); if (rc < 0) @@ -4836,6 +4841,7 @@ receive_encrypted_read(struct TCP_Server_Info *server= , struct smb_message **smb, discard_data: cifs_discard_remaining_data(server); goto free_pages; +#endif } =20 static int @@ -4893,9 +4899,9 @@ receive_encrypted_standard(struct TCP_Server_Info *se= rver, } =20 smb =3D smb2_find_mid(server, buf); - if (smb =3D=3D NULL) + if (smb =3D=3D NULL) { cifs_dbg(FYI, "mid not found\n"); - else { + } else { cifs_dbg(FYI, "mid found\n"); smb->decrypted =3D true; smb->resp_buf_size =3D server->pdu_size; diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c index 8554a4aa001d..6b94da4c1149 100644 --- a/fs/smb/client/smb2pdu.c +++ b/fs/smb/client/smb2pdu.c @@ -4106,7 +4106,6 @@ smb2_echo_callback(struct smb_message *smb) credits.instance =3D server->reconnect_instance; } =20 - release_mid(smb); add_credits(server, &credits, CIFS_ECHO_OP); } =20 @@ -4262,10 +4261,9 @@ int SMB2_echo(struct TCP_Server_Info *server) { struct smb2_echo_req *req; + struct smb_message *smb; int rc =3D 0; struct kvec iov[1]; - struct smb_rqst rqst =3D { .rq_iov =3D iov, - .rq_nvec =3D 1 }; unsigned int total_len; =20 cifs_dbg(FYI, "In echo request for conn_id %lld\n", server->conn_id); @@ -4280,22 +4278,36 @@ SMB2_echo(struct TCP_Server_Info *server) } spin_unlock(&server->srv_lock); =20 + smb =3D smb_message_alloc(SMB2_ECHO, GFP_NOFS); + if (!smb) + return -ENOMEM; + rc =3D smb2_plain_req_init(SMB2_ECHO, NULL, server, (void **)&req, &total_len); - if (rc) + if (rc) { + mempool_free(smb, &smb_message_pool); return rc; - - req->hdr.CreditRequest =3D cpu_to_le16(1); + } =20 iov[0].iov_len =3D total_len; iov[0].iov_base =3D (char *)req; =20 - rc =3D cifs_call_async(server, &rqst, NULL, smb2_echo_callback, NULL, - server, CIFS_ECHO_OP, NULL); + smb->rqst.rq_iov =3D iov; + smb->rqst.rq_nvec =3D 1; + smb->command_id =3D SMB2_ECHO; + smb->request =3D req; + smb->total_len =3D total_len; + smb->callback =3D smb2_echo_callback; + smb->callback_data =3D server; + + req->hdr.CreditRequest =3D cpu_to_le16(1); + + rc =3D cifs_call_async(server, smb, CIFS_ECHO_OP, NULL); if (rc) cifs_dbg(FYI, "Echo request failed: %d\n", rc); =20 cifs_small_buf_release(req); + smb_put_message(smb); return rc; } =20 @@ -4559,7 +4571,7 @@ smb2_readv_callback(struct smb_message *smb) int rc; =20 iov_iter_truncate(&rqst.rq_iter, rdata->got_bytes); - rc =3D smb2_verify_signature(&rqst, server); + rc =3D smb2_verify_signature(smb, server); if (rc) cifs_tcon_dbg(VFS, "SMB signature verification returned error =3D %d\n= ", rc); @@ -4645,7 +4657,6 @@ smb2_readv_callback(struct smb_message *smb) rdata->subreq.transferred +=3D rdata->got_bytes; trace_netfs_sreq(&rdata->subreq, netfs_sreq_trace_io_progress); netfs_read_subreq_terminated(&rdata->subreq); - release_mid(smb); trace_smb3_rw_credits(rreq_debug_id, subreq_debug_index, 0, server->credits, server->in_flight, credits.value, cifs_trace_rw_credits_read_response_add); @@ -4656,46 +4667,62 @@ smb2_readv_callback(struct smb_message *smb) int smb2_async_readv(struct cifs_io_subrequest *rdata) { - int rc, flags =3D 0; - char *buf; struct netfs_io_subrequest *subreq =3D &rdata->subreq; - struct smb2_hdr *shdr; - struct cifs_io_parms io_parms; - struct smb_rqst rqst =3D { .rq_iov =3D rdata->iov, - .rq_nvec =3D 1 }; struct TCP_Server_Info *server; + struct smb_message *smb; + struct smb2_hdr *shdr; struct cifs_tcon *tcon =3D tlink_tcon(rdata->req->cfile->tlink); unsigned int total_len; + void *buf; int credit_request; + int rc, flags =3D 0; =20 cifs_dbg(FYI, "%s: offset=3D%llu bytes=3D%zu\n", __func__, subreq->start, subreq->len); =20 - if (!rdata->server) - rdata->server =3D cifs_pick_channel(tcon->ses); + server =3D rdata->server; + if (!server) + server =3D rdata->server =3D cifs_pick_channel(tcon->ses); + + struct cifs_io_parms io_parms =3D { + .tcon =3D tlink_tcon(rdata->req->cfile->tlink), + .server =3D server, + .offset =3D subreq->start + subreq->transferred, + .length =3D subreq->len - subreq->transferred, + .persistent_fid =3D rdata->req->cfile->fid.persistent_fid, + .volatile_fid =3D rdata->req->cfile->fid.volatile_fid, + .pid =3D rdata->req->pid, + }; =20 - io_parms.tcon =3D tlink_tcon(rdata->req->cfile->tlink); - io_parms.server =3D server =3D rdata->server; - io_parms.offset =3D subreq->start + subreq->transferred; - io_parms.length =3D subreq->len - subreq->transferred; - io_parms.persistent_fid =3D rdata->req->cfile->fid.persistent_fid; - io_parms.volatile_fid =3D rdata->req->cfile->fid.volatile_fid; - io_parms.pid =3D rdata->req->pid; + smb =3D smb_message_alloc(SMB2_READ, GFP_NOFS); + if (!smb) + return -ENOMEM; =20 - rc =3D smb2_new_read_req( - (void **) &buf, &total_len, &io_parms, rdata, 0, 0); - if (rc) + rc =3D smb2_new_read_req(&buf, &total_len, &io_parms, rdata, 0, 0); + if (rc) { + mempool_free(smb, &smb_message_pool); return rc; + } =20 if (smb3_encryption_required(io_parms.tcon)) flags |=3D CIFS_TRANSFORM_REQ; =20 - rdata->iov[0].iov_base =3D buf; - rdata->iov[0].iov_len =3D total_len; - rdata->got_bytes =3D 0; - rdata->result =3D 0; + rdata->iov[0].iov_base =3D buf; + rdata->iov[0].iov_len =3D total_len; + rdata->got_bytes =3D 0; + rdata->result =3D 0; + + smb->rqst.rq_iov =3D rdata->iov; + smb->rqst.rq_nvec =3D 1; + smb->command_id =3D SMB2_READ; + smb->request =3D buf; + smb->total_len =3D total_len; + smb->receive =3D cifs_readv_receive; + smb->handle =3D smb3_handle_read_data; + smb->callback =3D smb2_readv_callback; + smb->callback_data =3D rdata; =20 - shdr =3D (struct smb2_hdr *)buf; + shdr =3D (struct smb2_hdr *)smb->request; =20 if (rdata->credits.value > 0) { shdr->CreditCharge =3D cpu_to_le16(DIV_ROUND_UP(io_parms.length, @@ -4715,10 +4742,7 @@ smb2_async_readv(struct cifs_io_subrequest *rdata) flags |=3D CIFS_HAS_CREDITS; } =20 - rc =3D cifs_call_async(server, &rqst, - cifs_readv_receive, smb2_readv_callback, - smb3_handle_read_data, rdata, flags, - &rdata->credits); + rc =3D cifs_call_async(server, smb, flags, &rdata->credits); if (rc) { cifs_stats_fail_inc(io_parms.tcon, SMB2_READ); trace_smb3_read_err(rdata->rreq->debug_id, @@ -4732,6 +4756,7 @@ smb2_async_readv(struct cifs_io_subrequest *rdata) =20 async_readv_out: cifs_small_buf_release(buf); + smb_put_message(smb); return rc; } =20 @@ -4931,7 +4956,6 @@ smb2_writev_callback(struct smb_message *smb) 0, cifs_trace_rw_credits_write_response_clear); wdata->credits.value =3D 0; cifs_write_subrequest_terminated(wdata, result ?: written); - release_mid(smb); trace_smb3_rw_credits(rreq_debug_id, subreq_debug_index, 0, server->credits, server->in_flight, credits.value, cifs_trace_rw_credits_write_response_add); @@ -4942,77 +4966,90 @@ smb2_writev_callback(struct smb_message *smb) void smb2_async_writev(struct cifs_io_subrequest *wdata) { - int rc =3D -EACCES, flags =3D 0; struct smb2_write_req *req =3D NULL; + struct smb_message *smb; struct smb2_hdr *shdr; struct cifs_tcon *tcon =3D tlink_tcon(wdata->req->cfile->tlink); struct TCP_Server_Info *server =3D wdata->server; struct kvec iov[1]; - struct smb_rqst rqst =3D { }; unsigned int total_len, xid =3D wdata->xid; - struct cifs_io_parms _io_parms; - struct cifs_io_parms *io_parms =3D NULL; int credit_request; + int rc =3D -EACCES, flags =3D 0; =20 /* * in future we may get cifs_io_parms passed in from the caller, * but for now we construct it here... */ - _io_parms =3D (struct cifs_io_parms) { - .tcon =3D tcon, - .server =3D server, - .offset =3D wdata->subreq.start, - .length =3D wdata->subreq.len, - .persistent_fid =3D wdata->req->cfile->fid.persistent_fid, - .volatile_fid =3D wdata->req->cfile->fid.volatile_fid, - .pid =3D wdata->req->pid, + struct cifs_io_parms io_parms =3D { + .tcon =3D tcon, + .server =3D server, + .offset =3D wdata->subreq.start, + .length =3D wdata->subreq.len, + .persistent_fid =3D wdata->req->cfile->fid.persistent_fid, + .volatile_fid =3D wdata->req->cfile->fid.volatile_fid, + .pid =3D wdata->req->pid, }; - io_parms =3D &_io_parms; + + smb =3D smb_message_alloc(SMB2_WRITE, GFP_NOFS); + if (!smb) { + rc =3D -ENOMEM; + goto out; + } =20 rc =3D smb2_plain_req_init(SMB2_WRITE, tcon, server, (void **) &req, &total_len); - if (rc) + if (rc) { + mempool_free(smb, &smb_message_pool); goto out; + } =20 - rqst.rq_iov =3D iov; - rqst.rq_iter =3D wdata->subreq.io_iter; + smb->rqst.rq_iov =3D iov; + smb->rqst.rq_iter =3D wdata->subreq.io_iter; + + smb->rqst.rq_iov[0].iov_len =3D total_len - 1; + smb->rqst.rq_iov[0].iov_base =3D (char *)req; + smb->rqst.rq_nvec +=3D 1; =20 - rqst.rq_iov[0].iov_len =3D total_len - 1; - rqst.rq_iov[0].iov_base =3D (char *)req; - rqst.rq_nvec +=3D 1; + smb->rqst.rq_iov =3D wdata->iov; + smb->rqst.rq_nvec =3D 1; + smb->command_id =3D SMB2_WRITE; + smb->request =3D req; + smb->total_len =3D total_len; + smb->callback =3D smb2_writev_callback; + smb->callback_data =3D wdata; =20 if (smb3_encryption_required(tcon)) flags |=3D CIFS_TRANSFORM_REQ; =20 shdr =3D (struct smb2_hdr *)req; - shdr->Id.SyncId.ProcessId =3D cpu_to_le32(io_parms->pid); - - req->PersistentFileId =3D io_parms->persistent_fid; - req->VolatileFileId =3D io_parms->volatile_fid; - req->WriteChannelInfoOffset =3D 0; - req->WriteChannelInfoLength =3D 0; - req->Channel =3D SMB2_CHANNEL_NONE; - req->Length =3D cpu_to_le32(io_parms->length); - req->Offset =3D cpu_to_le64(io_parms->offset); - req->DataOffset =3D cpu_to_le16( - offsetof(struct smb2_write_req, Buffer)); - req->RemainingBytes =3D 0; + shdr->Id.SyncId.ProcessId =3D cpu_to_le32(io_parms.pid); + + req->PersistentFileId =3D io_parms.persistent_fid; + req->VolatileFileId =3D io_parms.volatile_fid; + req->WriteChannelInfoOffset =3D 0; + req->WriteChannelInfoLength =3D 0; + req->Channel =3D SMB2_CHANNEL_NONE; + req->Length =3D cpu_to_le32(io_parms.length); + req->Offset =3D cpu_to_le64(io_parms.offset); + req->DataOffset =3D + cpu_to_le16(offsetof(struct smb2_write_req, Buffer)); + req->RemainingBytes =3D 0; =20 trace_smb3_write_enter(wdata->rreq->debug_id, wdata->subreq.debug_index, wdata->xid, - io_parms->persistent_fid, - io_parms->tcon->tid, - io_parms->tcon->ses->Suid, - io_parms->offset, - io_parms->length); + io_parms.persistent_fid, + io_parms.tcon->tid, + io_parms.tcon->ses->Suid, + io_parms.offset, + io_parms.length); =20 #ifdef CONFIG_CIFS_SMB_DIRECT /* * If we want to do a server RDMA read, fill in and append * smbdirect_buffer_descriptor_v1 to the end of write request */ - if (smb3_use_rdma_offload(io_parms)) { + if (smb3_use_rdma_offload(&io_parms)) { struct smbdirect_buffer_descriptor_v1 *v1; bool need_invalidate =3D server->dialect =3D=3D SMB30_PROT_ID; =20 @@ -5038,21 +5075,21 @@ smb2_async_writev(struct cifs_io_subrequest *wdata) v1->token =3D cpu_to_le32(wdata->mr->mr->rkey); v1->length =3D cpu_to_le32(wdata->mr->mr->length); =20 - rqst.rq_iov[0].iov_len +=3D sizeof(*v1); + smb->rqst.rq_iov[0].iov_len +=3D sizeof(*v1); =20 /* * We keep wdata->subreq.io_iter, * but we have to truncate rqst.rq_iter */ - iov_iter_truncate(&rqst.rq_iter, 0); + iov_iter_truncate(&smb->rqst.rq_iter, 0); } #endif =20 if (wdata->subreq.retry_count > 0) - smb2_set_replay(server, &rqst); + smb2_set_replay(server, &smb->rqst); =20 cifs_dbg(FYI, "async write at %llu %u bytes iter=3D%zx\n", - io_parms->offset, io_parms->length, iov_iter_count(&wdata->subreq.io_it= er)); + io_parms.offset, io_parms.length, iov_iter_count(&wdata->subreq.io_iter= )); =20 if (wdata->credits.value > 0) { shdr->CreditCharge =3D cpu_to_le16(DIV_ROUND_UP(wdata->subreq.len, @@ -5073,27 +5110,28 @@ smb2_async_writev(struct cifs_io_subrequest *wdata) } =20 /* XXX: compression + encryption is unsupported for now */ - if (((flags & CIFS_TRANSFORM_REQ) !=3D CIFS_TRANSFORM_REQ) && should_comp= ress(tcon, &rqst)) + if (((flags & CIFS_TRANSFORM_REQ) !=3D CIFS_TRANSFORM_REQ) && + should_compress(tcon, smb)) flags |=3D CIFS_COMPRESS_REQ; =20 - rc =3D cifs_call_async(server, &rqst, NULL, smb2_writev_callback, NULL, - wdata, flags, &wdata->credits); + rc =3D cifs_call_async(server, smb, flags, &wdata->credits); /* Can't touch wdata if rc =3D=3D 0 */ if (rc) { trace_smb3_write_err(wdata->rreq->debug_id, wdata->subreq.debug_index, xid, - io_parms->persistent_fid, - io_parms->tcon->tid, - io_parms->tcon->ses->Suid, - io_parms->offset, - io_parms->length, + io_parms.persistent_fid, + io_parms.tcon->tid, + io_parms.tcon->ses->Suid, + io_parms.offset, + io_parms.length, rc); cifs_stats_fail_inc(tcon, SMB2_WRITE); } =20 async_writev_out: cifs_small_buf_release(req); + smb_put_message(smb); out: if (rc) { trace_smb3_rw_credits(wdata->rreq->debug_id, diff --git a/fs/smb/client/smb2proto.h b/fs/smb/client/smb2proto.h index 6f1ce0399334..3018b171c6de 100644 --- a/fs/smb/client/smb2proto.h +++ b/fs/smb/client/smb2proto.h @@ -29,22 +29,20 @@ extern char *smb2_get_data_area_len(int *off, int *len, extern __le16 *cifs_convert_path_to_utf16(const char *from, struct cifs_sb_info *cifs_sb); =20 -extern int smb2_verify_signature(struct smb_rqst *, struct TCP_Server_Info= *); -extern int smb2_check_receive(struct smb_message *smb, - struct TCP_Server_Info *server, bool log_error); -extern struct smb_message *smb2_setup_request(struct cifs_ses *ses, - struct TCP_Server_Info *, - struct smb_rqst *rqst); -extern struct smb_message *smb2_setup_async_request( - struct TCP_Server_Info *server, struct smb_rqst *rqst); +int smb2_verify_signature(struct smb_message *smb, struct TCP_Server_Info = *server); +int smb2_check_receive(struct smb_message *smb, struct TCP_Server_Info *se= rver, + bool log_error); +int smb2_setup_request(struct cifs_ses *ses, struct TCP_Server_Info *serve= r, + struct smb_message *smb); +int smb2_setup_async_request(struct TCP_Server_Info *server, struct smb_me= ssage *smb); extern struct cifs_tcon *smb2_find_smb_tcon(struct TCP_Server_Info *server, __u64 ses_id, __u32 tid); -extern int smb2_calc_signature(struct smb_rqst *rqst, - struct TCP_Server_Info *server, - bool allocate_crypto); -extern int smb3_calc_signature(struct smb_rqst *rqst, - struct TCP_Server_Info *server, - bool allocate_crypto); +int smb2_calc_signature(struct smb_message *smb, + struct TCP_Server_Info *server, + bool allocate_crypto); +int smb3_calc_signature(struct smb_message *smb, + struct TCP_Server_Info *server, + bool allocate_crypto); extern void smb2_echo_request(struct work_struct *work); extern __le32 smb2_get_lease_state(struct cifsInodeInfo *cinode); extern bool smb2_is_valid_oplock_break(char *buffer, @@ -127,8 +125,7 @@ extern int smb2_unlock_range(struct cifsFileInfo *cfile, extern int smb2_push_mandatory_locks(struct cifsFileInfo *cfile); extern void smb2_reconnect_server(struct work_struct *work); extern int smb3_crypto_aead_allocate(struct TCP_Server_Info *server); -extern unsigned long smb_rqst_len(struct TCP_Server_Info *server, - struct smb_rqst *rqst); +extern unsigned long smb_rqst_len(struct TCP_Server_Info *server, struct s= mb_rqst *rqst); extern void smb2_set_next_command(struct cifs_tcon *tcon, struct smb_rqst *rqst); extern void smb2_set_related(struct smb_rqst *rqst); @@ -298,7 +295,7 @@ extern void smb2_copy_fs_info_to_kstatfs( extern int smb311_crypto_shash_allocate(struct TCP_Server_Info *server); extern int smb311_update_preauth_hash(struct cifs_ses *ses, struct TCP_Server_Info *server, - struct kvec *iov, int nvec); + struct smb_message *smb, bool hash_resp); extern int smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon, const char *path, u32 desired_access, diff --git a/fs/smb/client/smb2transport.c b/fs/smb/client/smb2transport.c index b217bc0e8e5b..b02f458e408a 100644 --- a/fs/smb/client/smb2transport.c +++ b/fs/smb/client/smb2transport.c @@ -252,14 +252,13 @@ smb2_find_smb_tcon(struct TCP_Server_Info *server, __= u64 ses_id, __u32 tid) return tcon; } =20 -int -smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server, +int smb2_calc_signature(struct smb_message *smb, struct TCP_Server_Info *s= erver, bool allocate_crypto) { int rc; unsigned char smb2_signature[SMB2_HMACSHA256_SIZE]; unsigned char *sigptr =3D smb2_signature; - struct kvec *iov =3D rqst->rq_iov; + struct kvec *iov =3D smb->rqst.rq_iov; struct smb2_hdr *shdr =3D (struct smb2_hdr *)iov[0].iov_base; struct shash_desc *shash =3D NULL; struct smb_rqst drqst; @@ -308,7 +307,7 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_S= erver_Info *server, * Sign the rfc1002 length prior to passing the data (iov[1-N]) down to * __cifs_calc_signature(). */ - drqst =3D *rqst; + drqst =3D smb->rqst; if (drqst.rq_nvec >=3D 2 && iov[0].iov_len =3D=3D 4) { rc =3D crypto_shash_update(shash, iov[0].iov_base, iov[0].iov_len); @@ -581,15 +580,14 @@ generate_smb311signingkey(struct cifs_ses *ses, return generate_smb3signingkey(ses, server, &triplet); } =20 -int -smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server, +int smb3_calc_signature(struct smb_message *smb, struct TCP_Server_Info *s= erver, bool allocate_crypto) { int rc; unsigned char smb3_signature[SMB2_CMACAES_SIZE]; unsigned char *sigptr =3D smb3_signature; - struct kvec *iov =3D rqst->rq_iov; - struct smb2_hdr *shdr =3D (struct smb2_hdr *)iov[0].iov_base; + struct kvec *iov =3D smb->rqst.rq_iov; + struct smb2_hdr *shdr =3D smb->request; struct shash_desc *shash =3D NULL; struct smb_rqst drqst; u8 key[SMB3_SIGN_KEY_SIZE]; @@ -635,7 +633,7 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_S= erver_Info *server, * Sign the rfc1002 length prior to passing the data (iov[1-N]) down to * __cifs_calc_signature(). */ - drqst =3D *rqst; + drqst =3D smb->rqst; if (drqst.rq_nvec >=3D 2 && iov[0].iov_len =3D=3D 4) { rc =3D crypto_shash_update(shash, iov[0].iov_base, iov[0].iov_len); @@ -660,23 +658,22 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP= _Server_Info *server, =20 /* must be called with server->srv_mutex held */ static int -smb2_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server) +smb2_sign_rqst(struct smb_message *smb, struct TCP_Server_Info *server) { int rc =3D 0; - struct smb2_hdr *shdr; + struct smb2_hdr *shdr =3D smb->request; struct smb2_sess_setup_req *ssr; bool is_binding; bool is_signed; =20 - shdr =3D (struct smb2_hdr *)rqst->rq_iov[0].iov_base; ssr =3D (struct smb2_sess_setup_req *)shdr; =20 - is_binding =3D le16_to_cpu(shdr->Command) =3D=3D SMB2_SESSION_SETUP && + is_binding =3D smb->command_id =3D=3D SMB2_SESSION_SETUP && (ssr->Flags & SMB2_SESSION_REQ_FLAG_BINDING); is_signed =3D shdr->Flags & SMB2_FLAGS_SIGNED; - if (!is_signed) return 0; + spin_lock(&server->srv_lock); if (server->ops->need_neg && server->ops->need_neg(server)) { @@ -689,24 +686,21 @@ smb2_sign_rqst(struct smb_rqst *rqst, struct TCP_Serv= er_Info *server) return 0; } =20 - rc =3D server->ops->calc_signature(rqst, server, false); - + rc =3D server->ops->calc_signature(smb, server, false); return rc; } =20 -int -smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *serve= r) +int smb2_verify_signature(struct smb_message *smb, struct TCP_Server_Info = *server) { - unsigned int rc; + struct smb2_hdr *shdr =3D smb->request; char server_response_sig[SMB2_SIGNATURE_SIZE]; - struct smb2_hdr *shdr =3D - (struct smb2_hdr *)rqst->rq_iov[0].iov_base; + int rc; =20 - if (le16_to_cpu(shdr->Command) =3D=3D SMB2_NEGOTIATE || - le16_to_cpu(shdr->Command) =3D=3D SMB2_SESSION_SETUP || - le16_to_cpu(shdr->Command) =3D=3D SMB2_OPLOCK_BREAK || + if (smb->command_id =3D=3D SMB2_NEGOTIATE || + smb->command_id =3D=3D SMB2_SESSION_SETUP || + smb->command_id =3D=3D SMB2_OPLOCK_BREAK || server->ignore_signature || - (!server->session_estab)) + !server->session_estab) return 0; =20 /* @@ -727,7 +721,7 @@ smb2_verify_signature(struct smb_rqst *rqst, struct TCP= _Server_Info *server) =20 memset(shdr->Signature, 0, SMB2_SIGNATURE_SIZE); =20 - rc =3D server->ops->calc_signature(rqst, server, true); + rc =3D server->ops->calc_signature(smb, server, true); =20 if (rc) return rc; @@ -736,8 +730,8 @@ smb2_verify_signature(struct smb_rqst *rqst, struct TCP= _Server_Info *server) cifs_dbg(VFS, "sign fail cmd 0x%x message id 0x%llx\n", shdr->Command, shdr->MessageId); return -EACCES; - } else - return 0; + } + return 0; } =20 /* @@ -746,58 +740,40 @@ smb2_verify_signature(struct smb_rqst *rqst, struct T= CP_Server_Info *server) */ static inline void smb2_seq_num_into_buf(struct TCP_Server_Info *server, - struct smb2_hdr *shdr) + struct smb_message *smb) { - unsigned int i, num =3D le16_to_cpu(shdr->CreditCharge); + struct smb2_hdr *shdr =3D smb->request; + unsigned int num =3D le16_to_cpu(shdr->CreditCharge); =20 - shdr->MessageId =3D get_next_mid64(server); /* skip message numbers according to CreditCharge field */ - for (i =3D 1; i < num; i++) - get_next_mid(server); + smb->mid =3D get_next_mid64(server, num); + shdr->MessageId =3D cpu_to_le64(smb->mid); } =20 -static struct smb_message * -smb2_mid_entry_alloc(const struct smb2_hdr *shdr, - struct TCP_Server_Info *server) +static void smb2_init_mid(struct smb_message *smb, + struct TCP_Server_Info *server) { - struct smb_message *smb; + const struct smb2_hdr *shdr =3D smb->request; unsigned int credits =3D le16_to_cpu(shdr->CreditCharge); =20 - if (server =3D=3D NULL) { - cifs_dbg(VFS, "Null TCP session in smb2_mid_entry_alloc\n"); - return NULL; - } - - smb =3D mempool_alloc(&smb_message_pool, GFP_NOFS); - memset(smb, 0, sizeof(*smb)); - refcount_set(&smb->ref, 1); - smb->mid =3D le64_to_cpu(shdr->MessageId); - smb->credits_consumed =3D credits > 0 ? credits : 1; - smb->pid =3D current->pid; - smb->command_id =3D le16_to_cpu(shdr->Command); - smb->when_alloc =3D jiffies; - smb->server =3D server; + smb->credits_consumed =3D credits > 0 ? credits : 1; + smb->server =3D server; =20 /* * The default is for the mid to be synchronous, so the * default callback just wakes up the current task. */ - get_task_struct(current); - smb->creator =3D current; - smb->callback =3D cifs_wake_up_task; - smb->callback_data =3D current; + smb->creator =3D get_task_struct(current); =20 atomic_inc(&mid_count); - smb->mid_state =3D MID_REQUEST_ALLOCATED; trace_smb3_cmd_enter(le32_to_cpu(shdr->Id.SyncId.TreeId), le64_to_cpu(shdr->SessionId), le16_to_cpu(shdr->Command), smb->mid); - return smb; } =20 static int smb2_get_mid_entry(struct cifs_ses *ses, struct TCP_Server_Info *server, - struct smb2_hdr *shdr, struct smb_message **smb) + struct smb_message *smb) { spin_lock(&server->srv_lock); if (server->tcpStatus =3D=3D CifsExiting) { @@ -812,7 +788,7 @@ smb2_get_mid_entry(struct cifs_ses *ses, struct TCP_Ser= ver_Info *server, } =20 if (server->tcpStatus =3D=3D CifsNeedNegotiate && - le16_to_cpu(shdr->Command) !=3D SMB2_NEGOTIATE) { + smb->command_id !=3D SMB2_NEGOTIATE) { spin_unlock(&server->srv_lock); return -EAGAIN; } @@ -820,8 +796,8 @@ smb2_get_mid_entry(struct cifs_ses *ses, struct TCP_Ser= ver_Info *server, =20 spin_lock(&ses->ses_lock); if (ses->ses_status =3D=3D SES_NEW) { - if (le16_to_cpu(shdr->Command) !=3D SMB2_SESSION_SETUP && - le16_to_cpu(shdr->Command) !=3D SMB2_NEGOTIATE) { + if (smb->command_id !=3D SMB2_SESSION_SETUP && + smb->command_id !=3D SMB2_NEGOTIATE) { spin_unlock(&ses->ses_lock); return -EAGAIN; } @@ -829,7 +805,7 @@ smb2_get_mid_entry(struct cifs_ses *ses, struct TCP_Ser= ver_Info *server, } =20 if (ses->ses_status =3D=3D SES_EXITING) { - if (le16_to_cpu(shdr->Command) !=3D SMB2_LOGOFF) { + if (smb->command_id !=3D SMB2_LOGOFF) { spin_unlock(&ses->ses_lock); return -EAGAIN; } @@ -837,101 +813,78 @@ smb2_get_mid_entry(struct cifs_ses *ses, struct TCP_= Server_Info *server, } spin_unlock(&ses->ses_lock); =20 - *smb =3D smb2_mid_entry_alloc(shdr, server); - if (*smb =3D=3D NULL) - return -ENOMEM; + smb2_init_mid(smb, server); + + smb_get_message(smb); spin_lock(&server->mid_lock); - list_add_tail(&(*smb)->qhead, &server->pending_mid_q); + list_add_tail(&smb->qhead, &server->pending_mid_q); spin_unlock(&server->mid_lock); - return 0; } =20 -int -smb2_check_receive(struct smb_message *mid, struct TCP_Server_Info *server, - bool log_error) +int smb2_check_receive(struct smb_message *smb, struct TCP_Server_Info *se= rver, + bool log_error) { - unsigned int len =3D mid->resp_buf_size; - struct kvec iov[1]; - struct smb_rqst rqst =3D { .rq_iov =3D iov, - .rq_nvec =3D 1 }; + unsigned int len =3D smb->resp_buf_size; =20 - iov[0].iov_base =3D (char *)mid->resp_buf; - iov[0].iov_len =3D len; - - dump_smb(mid->resp_buf, min_t(u32, 80, len)); + dump_smb(smb->resp_buf, min_t(u32, 80, len)); /* convert the length into a more usable form */ - if (len > 24 && server->sign && !mid->decrypted) { + if (len > 24 && server->sign && !smb->decrypted) { int rc; =20 - rc =3D smb2_verify_signature(&rqst, server); + rc =3D smb2_verify_signature(smb, server); if (rc) cifs_server_dbg(VFS, "SMB signature verification returned error =3D %d\= n", rc); } =20 - return map_smb2_to_linux_error(mid->resp_buf, log_error); + return map_smb2_to_linux_error(smb->resp_buf, log_error); } =20 -struct smb_message * -smb2_setup_request(struct cifs_ses *ses, struct TCP_Server_Info *server, - struct smb_rqst *rqst) +int smb2_setup_request(struct cifs_ses *ses, struct TCP_Server_Info *serve= r, + struct smb_message *smb) { + struct smb2_hdr *shdr =3D smb->request; int rc; - struct smb2_hdr *shdr =3D - (struct smb2_hdr *)rqst->rq_iov[0].iov_base; - struct smb_message *mid; =20 - smb2_seq_num_into_buf(server, shdr); + smb2_seq_num_into_buf(server, smb); =20 - rc =3D smb2_get_mid_entry(ses, server, shdr, &mid); + rc =3D smb2_get_mid_entry(ses, server, smb); if (rc) { revert_current_mid_from_hdr(server, shdr); - return ERR_PTR(rc); + return rc; } =20 - rc =3D smb2_sign_rqst(rqst, server); - if (rc) { + rc =3D smb2_sign_rqst(smb, server); + if (rc) revert_current_mid_from_hdr(server, shdr); - delete_mid(mid); - return ERR_PTR(rc); - } - - return mid; + return rc; } =20 -struct smb_message * -smb2_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *= rqst) +int +smb2_setup_async_request(struct TCP_Server_Info *server, struct smb_messag= e *smb) { + struct smb2_hdr *shdr =3D smb->request; int rc; - struct smb2_hdr *shdr =3D - (struct smb2_hdr *)rqst->rq_iov[0].iov_base; - struct smb_message *smb; =20 spin_lock(&server->srv_lock); if (server->tcpStatus =3D=3D CifsNeedNegotiate && - le16_to_cpu(shdr->Command) !=3D SMB2_NEGOTIATE) { + smb->command_id !=3D SMB2_NEGOTIATE) { spin_unlock(&server->srv_lock); - return ERR_PTR(-EAGAIN); + return -EAGAIN; } spin_unlock(&server->srv_lock); =20 - smb2_seq_num_into_buf(server, shdr); - - smb =3D smb2_mid_entry_alloc(shdr, server); - if (smb =3D=3D NULL) { - revert_current_mid_from_hdr(server, shdr); - return ERR_PTR(-ENOMEM); - } + smb2_seq_num_into_buf(server, smb); + smb2_init_mid(smb, server); =20 - rc =3D smb2_sign_rqst(rqst, server); + rc =3D smb2_sign_rqst(smb, server); if (rc) { revert_current_mid_from_hdr(server, shdr); - release_mid(smb); - return ERR_PTR(rc); + return rc; } =20 - return smb; + return 0; } =20 int diff --git a/fs/smb/client/transport.c b/fs/smb/client/transport.c index 6459acf959f3..042f689bbf52 100644 --- a/fs/smb/client/transport.c +++ b/fs/smb/client/transport.c @@ -40,7 +40,17 @@ struct smb_message *smb_message_alloc(enum smb2_command = cmd, gfp_t gfp) if (smb) { memset(smb, 0, sizeof(*smb)); refcount_set(&smb->ref, 1); - smb->command_id =3D cmd; + smb->command_id =3D cmd; + smb->when_alloc =3D jiffies; + smb->pid =3D current->pid; + + /* + * The default is for the mid to be synchronous, so the default + * callback just wakes up the current task. + */ + smb->callback =3D cifs_wake_up_task; + smb->callback_data =3D current; + smb->mid_state =3D MID_REQUEST_ALLOCATED; } return smb; } @@ -60,7 +70,8 @@ void smb_put_message(struct smb_message *smb) } =20 /* - * Dispose of a chain of compound messages. + * Dispose of a chain of compound messages. This should only be called by= the + * caller of smb_send_recv_messages(). */ void smb_put_messages(struct smb_message *smb) { @@ -80,7 +91,7 @@ cifs_wake_up_task(struct smb_message *smb) wake_up_process(smb->callback_data); } =20 -void __release_mid(struct smb_message *smb) +static void smb_clear_mid(struct smb_message *smb, struct TCP_Server_Info = *server) { #ifdef CONFIG_CIFS_STATS2 enum smb2_command command =3D smb->server->vals->lock_cmd; @@ -88,7 +99,6 @@ void __release_mid(struct smb_message *smb) unsigned long now; unsigned long roundtrip_time; #endif - struct TCP_Server_Info *server =3D smb->server; =20 if (smb->resp_buf && (smb->mid_flags & MID_WAIT_CANCELLED) && (smb->mid_state =3D=3D MID_RESPONSE_RECEIVED || @@ -154,22 +164,33 @@ void __release_mid(struct smb_message *smb) } #endif put_task_struct(smb->creator); - - mempool_free(smb, &smb_message_pool); } =20 -void -delete_mid(struct smb_message *smb) +static bool discard_message(struct TCP_Server_Info *server, struct smb_mes= sage *smb) { - spin_lock(&smb->server->mid_lock); + bool got_ref =3D false; + + spin_lock(&server->mid_lock); =20 if (!(smb->mid_flags & MID_DELETED)) { list_del_init(&smb->qhead); smb->mid_flags |=3D MID_DELETED; + got_ref =3D true; } - spin_unlock(&smb->server->mid_lock); =20 - release_mid(smb); + spin_unlock(&server->mid_lock); + return got_ref; +} + +static void smb_discard_messages(struct TCP_Server_Info *server, struct sm= b_message *head_smb) +{ + struct smb_message *smb, *next; + + for (smb =3D head_smb; smb; smb =3D next) { + next =3D smb->next; + if (discard_message(server, smb)) + smb_put_message(smb); + } } =20 /* @@ -456,20 +477,16 @@ static size_t smb3_copy_data_iter(void *iter_from, si= ze_t progress, size_t len, * at the front for the header(s). */ static int smb_copy_data_into_buffer(struct TCP_Server_Info *server, - int num_rqst, struct smb_rqst *rqst, + struct smb_message *head_smb, struct iov_iter *iter, struct bvecq **_bq) { + struct smb_message *smb; struct bvecq *bq; size_t total_len =3D 0, offset =3D 0; =20 - for (int i =3D 0; i < num_rqst; i++) { - struct smb_rqst *req =3D &rqst[i]; - size_t size =3D iov_iter_count(&req->rq_iter); - - for (int j =3D 0; j < req->rq_nvec; j++) - size +=3D req->rq_iov[j].iov_len; + for (smb =3D head_smb; smb; smb =3D smb->next) { total_len =3D ALIGN8(total_len); - total_len +=3D size; + total_len +=3D smb->total_len; } =20 bq =3D netfs_alloc_bvecq_buffer(total_len, 1, GFP_NOFS); @@ -478,9 +495,8 @@ static int smb_copy_data_into_buffer(struct TCP_Server_= Info *server, =20 iov_iter_bvec_queue(iter, ITER_DEST, bq, 1, 0, total_len); =20 - for (int i =3D 0; i < num_rqst; i++) { - struct smb_rqst *req =3D &rqst[i]; - size_t size =3D iov_iter_count(&req->rq_iter); + for (smb =3D head_smb; smb; smb =3D smb->next) { + size_t size =3D iov_iter_count(&smb->rqst.rq_iter); =20 if (offset & 7) { unsigned int tmp =3D offset; @@ -488,14 +504,15 @@ static int smb_copy_data_into_buffer(struct TCP_Serve= r_Info *server, iov_iter_zero(offset - tmp, iter); } =20 - for (int j =3D 0; j < req->rq_nvec; j++) { - size_t len =3D req->rq_iov[j].iov_len; - if (copy_to_iter(req->rq_iov[j].iov_base, len, iter) !=3D len) + for (int i =3D 0; i < smb->rqst.rq_nvec; i++) { + size_t len =3D smb->rqst.rq_iov[i].iov_len; + if (copy_to_iter(smb->rqst.rq_iov[i].iov_base, + len, iter) !=3D len) goto error; offset +=3D len; } =20 - if (iterate_and_advance_kernel(&req->rq_iter, + if (iterate_and_advance_kernel(&smb->rqst.rq_iter, size, iter, NULL, smb3_copy_data_iter) !=3D size) goto error; @@ -517,8 +534,7 @@ static int smb_copy_data_into_buffer(struct TCP_Server_= Info *server, } =20 static int -smb_send_rqst(struct TCP_Server_Info *server, int num_rqst, - struct smb_rqst *rqst, int flags) +smb_send_rqst(struct TCP_Server_Info *server, struct smb_message *head_smb= , int flags) { struct smb2_transform_hdr *tr_hdr; struct iov_iter iter; @@ -532,7 +548,7 @@ smb_send_rqst(struct TCP_Server_Info *server, int num_r= qst, return -EIO; } =20 - rc =3D smb_copy_data_into_buffer(server, num_rqst, rqst, &iter, &bq); + rc =3D smb_copy_data_into_buffer(server, head_smb, &iter, &bq); if (rc) return rc; content_len =3D iov_iter_count(&iter); @@ -562,7 +578,7 @@ smb_send_rqst(struct TCP_Server_Info *server, int num_r= qst, hdr_len +=3D sizeof(*tr_hdr); iov_iter_bvec_queue(&iter, ITER_SOURCE, bq, 1, 0, content_len); =20 - rc =3D server->ops->init_transform_rq(server, num_rqst, rqst, tr_hdr, &= iter); + rc =3D server->ops->init_transform_rq(server, head_smb, tr_hdr, &iter); if (rc) goto error; } @@ -816,16 +832,16 @@ int wait_for_response(struct TCP_Server_Info *server,= struct smb_message *smb) * the result. Caller is responsible for dealing with timeouts. */ int -cifs_call_async(struct TCP_Server_Info *server, struct smb_rqst *rqst, - mid_receive_t receive, mid_callback_t callback, - mid_handle_t handle, void *cbdata, const int flags, - const struct cifs_credits *exist_credits) +cifs_call_async(struct TCP_Server_Info *server, struct smb_message *smb, + const int flags, const struct cifs_credits *exist_credits) { - int rc; - struct smb_message *smb; struct cifs_credits credits =3D { .value =3D 0, .instance =3D 0 }; unsigned int instance; int optype; + int rc; + + if (WARN_ON_ONCE(smb->next)) + return -EIO; =20 optype =3D flags & CIFS_OP_MASK; =20 @@ -851,21 +867,17 @@ cifs_call_async(struct TCP_Server_Info *server, struc= t smb_rqst *rqst, return -EAGAIN; } =20 - smb =3D server->ops->setup_async_request(server, rqst); - if (IS_ERR(smb)) { + rc =3D server->ops->setup_async_request(server, smb); + if (rc) { cifs_server_unlock(server); add_credits_and_wake_if(server, &credits, optype); - return PTR_ERR(smb); + return rc; } =20 - smb->sr_flags =3D flags; - smb->receive =3D receive; - smb->callback =3D callback; - smb->callback_data =3D cbdata; - smb->handle =3D handle; smb->mid_state =3D MID_REQUEST_SUBMITTED; =20 /* put it on the pending_mid_q */ + smb_get_message(smb); spin_lock(&server->mid_lock); list_add_tail(&smb->qhead, &server->pending_mid_q); spin_unlock(&server->mid_lock); @@ -875,12 +887,13 @@ cifs_call_async(struct TCP_Server_Info *server, struc= t smb_rqst *rqst, * I/O response may come back and free the mid entry on another thread. */ cifs_save_when_sent(smb); - rc =3D smb_send_rqst(server, 1, rqst, flags); + rc =3D smb_send_rqst(server, smb, flags); =20 if (rc < 0) { revert_current_mid(server, smb->credits_consumed); server->sequence_number -=3D 2; - delete_mid(smb); + if (discard_message(server, smb)) + smb_put_message(smb); } =20 cifs_server_unlock(server); @@ -930,7 +943,7 @@ int cifs_sync_mid_result(struct smb_message *smb, struc= t TCP_Server_Info *server spin_unlock(&server->mid_lock); =20 sync_mid_done: - release_mid(smb); + smb_clear_mid(smb, server); return rc; } =20 @@ -960,7 +973,6 @@ static void cifs_cancelled_callback(struct smb_message *smb) { cifs_compound_callback(smb); - release_mid(smb); } =20 /* @@ -1017,31 +1029,29 @@ struct TCP_Server_Info *cifs_pick_channel(struct ci= fs_ses *ses) return server; } =20 -int -compound_send_recv(const unsigned int xid, struct cifs_ses *ses, - struct TCP_Server_Info *server, - const int flags, const int num_rqst, struct smb_rqst *rqst, - int *resp_buf_type, struct kvec *resp_iov) +/* + * Send a single message or a string of messages as a compound. + */ +int smb_send_recv_messages(const unsigned int xid, struct cifs_ses *ses, + struct TCP_Server_Info *server, + struct smb_message *head_smb, const int flags) { - int i, j, optype, rc =3D 0; - struct smb_message *smb[MAX_COMPOUND]; - bool cancelled_mid[MAX_COMPOUND] =3D {false}; - struct cifs_credits credits[MAX_COMPOUND] =3D { - { .value =3D 0, .instance =3D 0 } - }; unsigned int instance; + int nr_reqs, i, optype, rc =3D 0; char *buf; =20 - optype =3D flags & CIFS_OP_MASK; - - for (i =3D 0; i < num_rqst; i++) - resp_buf_type[i] =3D CIFS_NO_BUFFER; /* no response buf yet */ - if (!ses || !ses->server || !server) { cifs_dbg(VFS, "Null session\n"); return -EIO; } =20 + optype =3D flags & CIFS_OP_MASK; + + /* TODO: Stitch together the messages in a compound. */ + nr_reqs =3D 0; + for (struct smb_message *smb =3D head_smb; smb; smb =3D smb->next) + nr_reqs++; + spin_lock(&server->srv_lock); if (server->tcpStatus =3D=3D CifsExiting) { spin_unlock(&server->srv_lock); @@ -1057,14 +1067,13 @@ compound_send_recv(const unsigned int xid, struct c= ifs_ses *ses, * other requests. * This can be handled by the eventual session reconnect. */ - rc =3D wait_for_compound_request(server, num_rqst, flags, - &instance); + rc =3D wait_for_compound_request(server, nr_reqs, flags, &instance); if (rc) return rc; =20 - for (i =3D 0; i < num_rqst; i++) { - credits[i].value =3D 1; - credits[i].instance =3D instance; + for (struct smb_message *smb =3D head_smb; smb; smb =3D smb->next) { + smb->credits.value =3D 1; + smb->credits.instance =3D instance; } =20 /* @@ -1084,45 +1093,46 @@ compound_send_recv(const unsigned int xid, struct c= ifs_ses *ses, */ if (instance !=3D server->reconnect_instance) { cifs_server_unlock(server); - for (j =3D 0; j < num_rqst; j++) - add_credits(server, &credits[j], optype); + for (struct smb_message *smb =3D head_smb; smb; smb =3D smb->next) + add_credits(server, &smb->credits, optype); return -EAGAIN; } =20 - for (i =3D 0; i < num_rqst; i++) { - smb[i] =3D server->ops->setup_request(ses, server, &rqst[i]); - if (IS_ERR(smb[i])) { - revert_current_mid(server, i); - for (j =3D 0; j < i; j++) - delete_mid(smb[j]); - cifs_server_unlock(server); - - /* Update # of requests on wire to server */ - for (j =3D 0; j < num_rqst; j++) - add_credits(server, &credits[j], optype); - return PTR_ERR(smb[i]); - } - - smb[i]->sr_flags =3D flags; - smb[i]->mid_state =3D MID_REQUEST_SUBMITTED; - smb[i]->optype =3D optype; + i =3D 0; + for (struct smb_message *smb =3D head_smb; smb; smb =3D smb->next) { + smb->optype =3D optype; /* * Invoke callback for every part of the compound chain * to calculate credits properly. Wake up this thread only when * the last element is received. */ - if (i < num_rqst - 1) - smb[i]->callback =3D cifs_compound_callback; + if (smb->next) + smb->callback =3D cifs_compound_callback; else - smb[i]->callback =3D cifs_compound_last_callback; + smb->callback =3D cifs_compound_last_callback; + + rc =3D server->ops->setup_request(ses, server, smb); + if (rc) { + revert_current_mid(server, i); + smb_discard_messages(server, head_smb); + cifs_server_unlock(server); + + /* Update # of requests on wire to server */ + for (struct smb_message *smb =3D head_smb; smb; smb =3D smb->next) + add_credits(server, &smb->credits, optype); + return rc; + } + + smb->mid_state =3D MID_REQUEST_SUBMITTED; } - rc =3D smb_send_rqst(server, num_rqst, rqst, flags); =20 - for (i =3D 0; i < num_rqst; i++) - cifs_save_when_sent(smb[i]); + rc =3D smb_send_rqst(server, head_smb, flags); + + for (struct smb_message *smb =3D head_smb; smb; smb =3D smb->next) + cifs_save_when_sent(smb); =20 if (rc < 0) { - revert_current_mid(server, num_rqst); + revert_current_mid(server, nr_reqs); server->sequence_number -=3D 2; } =20 @@ -1133,8 +1143,8 @@ compound_send_recv(const unsigned int xid, struct cif= s_ses *ses, * will not receive a response to - return credits back */ if (rc < 0 || (flags & CIFS_NO_SRV_RSP)) { - for (i =3D 0; i < num_rqst; i++) - add_credits(server, &credits[i], optype); + for (struct smb_message *smb =3D head_smb; smb; smb =3D smb->next) + add_credits(server, &smb->credits, optype); goto out; } =20 @@ -1154,70 +1164,71 @@ compound_send_recv(const unsigned int xid, struct c= ifs_ses *ses, spin_unlock(&ses->ses_lock); =20 cifs_server_lock(server); - smb311_update_preauth_hash(ses, server, rqst[0].rq_iov, rqst[0].rq_nvec); + smb311_update_preauth_hash(ses, server, head_smb, false); cifs_server_unlock(server); - - spin_lock(&ses->ses_lock); + } else { + spin_unlock(&ses->ses_lock); } - spin_unlock(&ses->ses_lock); =20 - for (i =3D 0; i < num_rqst; i++) { - rc =3D wait_for_response(server, smb[i]); - if (rc !=3D 0) - break; + for (struct smb_message *smb =3D head_smb; smb; smb =3D smb->next) { + if (!smb->next) { + rc =3D wait_for_response(server, smb); + if (rc !=3D 0) + break; + } } if (rc !=3D 0) { - for (; i < num_rqst; i++) { + for (struct smb_message *smb =3D head_smb; smb; smb =3D smb->next) { cifs_server_dbg(FYI, "Cancelling wait for mid %llu cmd: %d\n", - smb[i]->mid, smb[i]->command_id); - send_cancel(ses, server, &rqst[i], smb[i], xid); + smb->mid, smb->command_id); + send_cancel(ses, server, smb, xid); spin_lock(&server->mid_lock); - smb[i]->mid_flags |=3D MID_WAIT_CANCELLED; - if (smb[i]->mid_state =3D=3D MID_REQUEST_SUBMITTED || - smb[i]->mid_state =3D=3D MID_RESPONSE_RECEIVED) { - smb[i]->callback =3D cifs_cancelled_callback; - cancelled_mid[i] =3D true; - credits[i].value =3D 0; + smb->mid_flags |=3D MID_WAIT_CANCELLED; + if (smb->mid_state =3D=3D MID_REQUEST_SUBMITTED || + smb->mid_state =3D=3D MID_RESPONSE_RECEIVED) { + smb->callback =3D cifs_cancelled_callback; + smb->cancelled =3D true; + smb->credits.value =3D 0; } spin_unlock(&server->mid_lock); } } =20 - for (i =3D 0; i < num_rqst; i++) { + for (struct smb_message *smb =3D head_smb; smb; smb =3D smb->next) { if (rc < 0) goto out; =20 - rc =3D cifs_sync_mid_result(smb[i], server); + rc =3D cifs_sync_mid_result(smb, server); if (rc !=3D 0) { /* mark this mid as cancelled to not free it below */ - cancelled_mid[i] =3D true; + smb->cancelled =3D true; goto out; } =20 - if (!smb[i]->resp_buf || - smb[i]->mid_state !=3D MID_RESPONSE_READY) { + if (!smb->resp_buf || + smb->mid_state !=3D MID_RESPONSE_READY) { rc =3D -EIO; cifs_dbg(FYI, "Bad MID state?\n"); goto out; } =20 - rc =3D server->ops->check_receive(smb[i], server, - flags & CIFS_LOG_ERROR); + rc =3D server->ops->check_receive(smb, server, + flags & CIFS_LOG_ERROR); =20 - if (resp_iov) { - buf =3D (char *)smb[i]->resp_buf; - resp_iov[i].iov_base =3D buf; - resp_iov[i].iov_len =3D smb[i]->resp_buf_size + + if (smb->resp_iov) { + buf =3D (char *)smb->resp_buf; + smb->resp_iov->iov_base =3D buf; + smb->resp_iov->iov_len =3D smb->resp_buf_size + HEADER_PREAMBLE_SIZE(server); =20 - if (smb[i]->large_buf) - resp_buf_type[i] =3D CIFS_LARGE_BUFFER; + if (smb->large_buf) + *smb->resp_buf_type =3D CIFS_LARGE_BUFFER; else - resp_buf_type[i] =3D CIFS_SMALL_BUFFER; + *smb->resp_buf_type =3D CIFS_SMALL_BUFFER; =20 /* mark it so buf will not be freed by delete_mid */ if ((flags & CIFS_NO_RSP_BUF) =3D=3D 0) - smb[i]->resp_buf =3D NULL; + smb->resp_buf =3D NULL; } } =20 @@ -1226,17 +1237,13 @@ compound_send_recv(const unsigned int xid, struct c= ifs_ses *ses, */ spin_lock(&ses->ses_lock); if ((ses->ses_status =3D=3D SES_NEW) || (optype & CIFS_NEG_OP) || (optype= & CIFS_SESS_OP)) { - struct kvec iov =3D { - .iov_base =3D resp_iov[0].iov_base, - .iov_len =3D resp_iov[0].iov_len - }; spin_unlock(&ses->ses_lock); cifs_server_lock(server); - smb311_update_preauth_hash(ses, server, &iov, 1); + smb311_update_preauth_hash(ses, server, head_smb, true); cifs_server_unlock(server); - spin_lock(&ses->ses_lock); + } else { + spin_unlock(&ses->ses_lock); } - spin_unlock(&ses->ses_lock); =20 out: /* @@ -1245,11 +1252,51 @@ compound_send_recv(const unsigned int xid, struct c= ifs_ses *ses, * This is prevented above by using a noop callback that will not * wake this thread except for the very last PDU. */ - for (i =3D 0; i < num_rqst; i++) { - if (!cancelled_mid[i]) - delete_mid(smb[i]); + for (struct smb_message *smb =3D head_smb; smb; smb =3D smb->next) + if (!smb->cancelled) + discard_message(server, smb); + + return rc; +} + +int +compound_send_recv(const unsigned int xid, struct cifs_ses *ses, + struct TCP_Server_Info *server, + const int flags, const int num_rqst, struct smb_rqst *rqst, + int *resp_buf_type, struct kvec *resp_iov) +{ + struct smb_message *head_smb =3D NULL, **ppsmb =3D &head_smb, *smb; + int rc =3D -ENOMEM; + + if (!ses || !ses->server || !server) { + cifs_dbg(VFS, "Null session\n"); + return -EIO; + } + + for (int i =3D 0; i < num_rqst; i++) { + void *request =3D rqst[i].rq_iov[0].iov_base; + struct smb2_hdr *hdr =3D request; + enum smb2_command cmd =3D le16_to_cpu(hdr->Command); + + smb =3D smb_message_alloc(cmd, GFP_NOFS); + if (!smb) + goto error; + + *ppsmb =3D smb; + ppsmb =3D &smb->next; + smb->request =3D request; + smb->rqst =3D rqst[i]; + smb->sr_flags =3D flags; + smb->total_len =3D smb_rqst_len(server, &smb->rqst); + smb->resp_buf_type =3D &resp_buf_type[i]; + smb->resp_iov =3D &resp_iov[i]; + resp_buf_type[i] =3D CIFS_NO_BUFFER; /* no response buf yet */ } =20 + rc =3D smb_send_recv_messages(xid, ses, server, head_smb, flags); + +error: + smb_put_messages(smb); return rc; } From nobody Thu Dec 18 03:20:29 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BB8772BD5B9 for ; Wed, 6 Aug 2025 20:38:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512736; cv=none; b=rdWPWMYMAO48+npwl8TbmLCZWONYMmOtZw3a6WXYQTcpmeJEffyKFI99nG74IJNRDST89GCFBqaQOVN0zMrMS46xGIoy9NC9Vg3XIf6Vcx5KC8VGaFsDPPjIollI0U97Og79AZmlP/Yp1CnENZRI4SfRMHRgRCsNeNoPN4dHF8k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512736; c=relaxed/simple; bh=OKHhptfB5jwBXD5+u7zjUFMyyR/hvX8j2hEbb+AAvg4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=pjO7zyKTVoxI0GIrjtpN7jxGZCbCdUOa6exbkSTGvgFNQxz2ao4UkI8K5mEyv5Y5OssE0D7VnjaLxBDMK3SRyL7xhaFLnE5K4q3n49d76bHvluyD1cR/MslyKy6f1KMtzVoeBO3HPXc9EkHDULZN6m8/CDauMR2Ysf0KMGs0IZQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=R1OuXtZ8; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="R1OuXtZ8" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1754512732; h=from:from:reply-to:subject:subject: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=/433jhOde1F9jr30af40wOYw9SgoaERWUX8VrFSUDNQ=; b=R1OuXtZ88i2QCsJzaAbU9eABDSx5BAwoeld2Kr5jhazEakIsdLiK61FJ1DZBVFr6WcrhV5 +o+SaFrphfYjIOMCWp352KhPu9P8QorSnI6HKDer0uloS8R9mFdKi3Kw5q1Wg7ZiTzT5CV GGr5vzExYrAkACY1dcvgpBANGHDV4fo= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-614-b59P-9Y-O_uOT4o7D0Qcog-1; Wed, 06 Aug 2025 16:38:49 -0400 X-MC-Unique: b59P-9Y-O_uOT4o7D0Qcog-1 X-Mimecast-MFC-AGG-ID: b59P-9Y-O_uOT4o7D0Qcog_1754512727 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 97CA61800446; Wed, 6 Aug 2025 20:38:47 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.17]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 871AB1800280; Wed, 6 Aug 2025 20:38:44 +0000 (UTC) From: David Howells To: Steve French Cc: David Howells , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Wang Zhaolong , Stefan Metzmacher , Mina Almasry , linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org, netfs@lists.linux.dev, linux-fsdevel@vger.kernel.org Subject: [RFC PATCH 19/31] cifs: Clean up mid->callback_data and kill off mid->creator Date: Wed, 6 Aug 2025 21:36:40 +0100 Message-ID: <20250806203705.2560493-20-dhowells@redhat.com> In-Reply-To: <20250806203705.2560493-1-dhowells@redhat.com> References: <20250806203705.2560493-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Content-Type: text/plain; charset="utf-8" We shouldn't really be pinning a task_struct on the mid_q_struct. Better to provide a wait queue there and have the waiter wait on it. For synchronous operations, this allows them to remove themselves from it once this is absorbed into smb_message and smb_message is generated higher up the stack. This also gets rid of one of the uses of mid->callback_data. We can also get rid of the need for callback_data for the Echo command callback by passing a server pointer down into ->callback() from the callers (all of which have it available). This can also be used in the Read and Write callbacks. We then only need the callback_data for the Read and Write commands - and in both cases, it points to a cifs_io_subrequest struct. So replace callback_data with a specifically typed pointer in a union that other users can be added to as the need arises. Signed-off-by: David Howells cc: Steve French cc: Paulo Alcantara cc: Shyam Prasad N cc: Tom Talpey cc: linux-cifs@vger.kernel.org cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/smb/client/cifs_debug.c | 3 +-- fs/smb/client/cifsglob.h | 11 ++++++++--- fs/smb/client/cifsproto.h | 2 +- fs/smb/client/cifstransport.c | 1 - fs/smb/client/connect.c | 8 ++++---- fs/smb/client/smb2ops.c | 6 +++--- fs/smb/client/smb2pdu.c | 18 +++++++----------- fs/smb/client/smb2transport.c | 6 ------ fs/smb/client/transport.c | 27 +++++++++++++-------------- 9 files changed, 37 insertions(+), 45 deletions(-) diff --git a/fs/smb/client/cifs_debug.c b/fs/smb/client/cifs_debug.c index cba30f339d6b..13c569ab3417 100644 --- a/fs/smb/client/cifs_debug.c +++ b/fs/smb/client/cifs_debug.c @@ -625,11 +625,10 @@ static int cifs_debug_data_proc_show(struct seq_file = *m, void *v) chan_server->conn_id); spin_lock(&chan_server->mid_lock); list_for_each_entry(smb, &chan_server->pending_mid_q, qhead) { - seq_printf(m, "\n\t\tState: %d com: %d pid: %d cbdata: %p mid %llu", + seq_printf(m, "\n\t\tState: %d com: %d pid: %d mid %llu", smb->mid_state, smb->command_id, smb->pid, - smb->callback_data, smb->mid); } spin_unlock(&chan_server->mid_lock); diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index 4173b87bdf0f..14b132fb14e0 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h @@ -1692,7 +1692,8 @@ typedef int (*mid_receive_t)(struct TCP_Server_Info *= server, * - it will be called by cifsd, with no locks held * - the mid will be removed from any lists */ -typedef void (*mid_callback_t)(struct smb_message *smb); +typedef void (*mid_callback_t)(struct TCP_Server_Info *server, + struct smb_message *smb); =20 /* * This is the protopyte for mid handle function. This is called once the = mid @@ -1731,11 +1732,17 @@ struct smb_message { struct smb_message *next; /* Next message in compound */ struct cifs_credits credits; /* Credit requirements for this message */ void *request; /* Pointer to request message body */ + wait_queue_head_t waitq; /* Wait queue for message events */ refcount_t ref; bool sensitive; /* Request contains sensitive data */ bool cancelled; /* T if cancelled */ unsigned int sr_flags; /* Flags passed to send_recv() */ =20 + /* PDU-type specific data */ + union { + struct cifs_io_subrequest *subreq; /* Read/write subrequest */ + }; + /* Queue state */ struct list_head qhead; /* mids waiting on reply from this server */ struct TCP_Server_Info *server; /* server corresponding to this mid */ @@ -1752,8 +1759,6 @@ struct smb_message { mid_receive_t receive; /* call receive callback */ mid_callback_t callback; /* call completion callback */ mid_handle_t handle; /* call handle mid callback */ - void *callback_data; /* general purpose pointer for callback */ - struct task_struct *creator; void *resp_buf; /* pointer to received SMB header */ unsigned int resp_buf_size; int mid_state; /* wish this were enum but can not pass to wait_event */ diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h index fd5fe2723b4a..abae67d83499 100644 --- a/fs/smb/client/cifsproto.h +++ b/fs/smb/client/cifsproto.h @@ -83,7 +83,7 @@ extern char *cifs_build_path_to_root(struct smb3_fs_conte= xt *ctx, int add_treename); extern char *build_wildcard_path_from_dentry(struct dentry *direntry); char *cifs_build_devname(char *nodename, const char *prepath); -extern void cifs_wake_up_task(struct smb_message *smb); +extern void cifs_wake_up_task( struct TCP_Server_Info *server, struct smb_= message *smb); extern int cifs_handle_standard(struct TCP_Server_Info *server, struct smb_message *smb); extern char *smb3_fs_context_fullpath(const struct smb3_fs_context *ctx, diff --git a/fs/smb/client/cifstransport.c b/fs/smb/client/cifstransport.c index 8cdb9252a37e..1e2a8839d742 100644 --- a/fs/smb/client/cifstransport.c +++ b/fs/smb/client/cifstransport.c @@ -60,7 +60,6 @@ alloc_mid(const struct smb_hdr *smb_buffer, struct TCP_Se= rver_Info *server) * default callback just wakes up the current task. */ get_task_struct(current); - smb->creator =3D current; smb->callback =3D cifs_wake_up_task; smb->callback_data =3D current; =20 diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c index 7a64b070f74b..9bd19dd91d35 100644 --- a/fs/smb/client/connect.c +++ b/fs/smb/client/connect.c @@ -334,7 +334,7 @@ cifs_abort_connection(struct TCP_Server_Info *server) cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__); list_for_each_entry_safe(smb, nsmb, &retry_list, qhead) { list_del_init(&smb->qhead); - smb->callback(smb); + smb->callback(server, smb); smb_put_message(smb); } =20 @@ -917,7 +917,7 @@ is_smb_response(struct TCP_Server_Info *server, unsigne= d char type) list_del_init(&smb->qhead); smb->mid_rc =3D mid_rc; smb->mid_state =3D MID_RC; - smb->callback(smb); + smb->callback(server, smb); smb_put_message(smb); } =20 @@ -1111,7 +1111,7 @@ clean_demultiplex_info(struct TCP_Server_Info *server) list_for_each_entry_safe(smb, smb2, &dispose_list, qhead) { cifs_dbg(FYI, "Callback mid %llu\n", smb->mid); list_del_init(&smb->qhead); - smb->callback(smb); + smb->callback(server, smb); smb_put_message(smb); } /* 1/8th of sec is more than enough time for them to exit */ @@ -1388,7 +1388,7 @@ cifs_demultiplex_thread(void *p) } =20 if (!smbs[i]->multiRsp || smbs[i]->multiEnd) - smbs[i]->callback(smbs[i]); + smbs[i]->callback(server, smbs[i]); =20 smb_put_message(smbs[i]); } else if (server->ops->is_oplock_break && diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c index 835a76169d40..63226bbba3d1 100644 --- a/fs/smb/client/smb2ops.c +++ b/fs/smb/client/smb2ops.c @@ -4527,7 +4527,7 @@ handle_read_data(struct TCP_Server_Info *server, stru= ct smb_message *smb, unsigned int cur_off; unsigned int cur_page_idx; unsigned int pad_len; - struct cifs_io_subrequest *rdata =3D smb->callback_data; + struct cifs_io_subrequest *rdata =3D smb->subreq; struct smb2_hdr *shdr =3D (struct smb2_hdr *)buf; int length; bool use_rdma_mr =3D false; @@ -4707,7 +4707,7 @@ static void smb2_decrypt_offload(struct work_struct *= work) dw->server->ops->is_network_name_deleted(dw->buf, dw->server); =20 - smb->callback(smb); + smb->callback(dw->server, smb); } else { spin_lock(&dw->server->srv_lock); if (dw->server->tcpStatus =3D=3D CifsNeedReconnect) { @@ -4715,7 +4715,7 @@ static void smb2_decrypt_offload(struct work_struct *= work) smb->mid_state =3D MID_RETRY_NEEDED; spin_unlock(&dw->server->mid_lock); spin_unlock(&dw->server->srv_lock); - smb->callback(smb); + smb->callback(dw->server, smb); } else { spin_lock(&dw->server->mid_lock); smb->mid_state =3D MID_REQUEST_SUBMITTED; diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c index 6b94da4c1149..8d50036fd028 100644 --- a/fs/smb/client/smb2pdu.c +++ b/fs/smb/client/smb2pdu.c @@ -4094,9 +4094,8 @@ SMB2_change_notify(const unsigned int xid, struct cif= s_tcon *tcon, * FIXME: maybe we should consider checking that the reply matches request? */ static void -smb2_echo_callback(struct smb_message *smb) +smb2_echo_callback(struct TCP_Server_Info *server, struct smb_message *smb) { - struct TCP_Server_Info *server =3D smb->callback_data; struct smb2_echo_rsp *rsp =3D (struct smb2_echo_rsp *)smb->resp_buf; struct cifs_credits credits =3D { .value =3D 0, .instance =3D 0 }; =20 @@ -4298,7 +4297,6 @@ SMB2_echo(struct TCP_Server_Info *server) smb->request =3D req; smb->total_len =3D total_len; smb->callback =3D smb2_echo_callback; - smb->callback_data =3D server; =20 req->hdr.CreditRequest =3D cpu_to_le16(1); =20 @@ -4533,12 +4531,11 @@ smb2_new_read_req(void **buf, unsigned int *total_l= en, } =20 static void -smb2_readv_callback(struct smb_message *smb) +smb2_readv_callback(struct TCP_Server_Info *server, struct smb_message *sm= b) { - struct cifs_io_subrequest *rdata =3D smb->callback_data; + struct cifs_io_subrequest *rdata =3D smb->subreq; struct netfs_inode *ictx =3D netfs_inode(rdata->rreq->inode); struct cifs_tcon *tcon =3D tlink_tcon(rdata->req->cfile->tlink); - struct TCP_Server_Info *server =3D rdata->server; struct smb2_hdr *shdr =3D (struct smb2_hdr *)rdata->iov[0].iov_base; struct cifs_credits credits =3D { .value =3D 0, @@ -4720,7 +4717,7 @@ smb2_async_readv(struct cifs_io_subrequest *rdata) smb->receive =3D cifs_readv_receive; smb->handle =3D smb3_handle_read_data; smb->callback =3D smb2_readv_callback; - smb->callback_data =3D rdata; + smb->subreq =3D rdata; =20 shdr =3D (struct smb2_hdr *)smb->request; =20 @@ -4847,11 +4844,10 @@ SMB2_read(const unsigned int xid, struct cifs_io_pa= rms *io_parms, * workqueue completion task. */ static void -smb2_writev_callback(struct smb_message *smb) +smb2_writev_callback(struct TCP_Server_Info *server, struct smb_message *s= mb) { - struct cifs_io_subrequest *wdata =3D smb->callback_data; + struct cifs_io_subrequest *wdata =3D smb->subreq; struct cifs_tcon *tcon =3D tlink_tcon(wdata->req->cfile->tlink); - struct TCP_Server_Info *server =3D wdata->server; struct smb2_write_rsp *rsp =3D (struct smb2_write_rsp *)smb->resp_buf; struct cifs_credits credits =3D { .value =3D 0, @@ -5016,7 +5012,7 @@ smb2_async_writev(struct cifs_io_subrequest *wdata) smb->request =3D req; smb->total_len =3D total_len; smb->callback =3D smb2_writev_callback; - smb->callback_data =3D wdata; + smb->subreq =3D wdata; =20 if (smb3_encryption_required(tcon)) flags |=3D CIFS_TRANSFORM_REQ; diff --git a/fs/smb/client/smb2transport.c b/fs/smb/client/smb2transport.c index b02f458e408a..7c60584a8544 100644 --- a/fs/smb/client/smb2transport.c +++ b/fs/smb/client/smb2transport.c @@ -759,12 +759,6 @@ static void smb2_init_mid(struct smb_message *smb, smb->credits_consumed =3D credits > 0 ? credits : 1; smb->server =3D server; =20 - /* - * The default is for the mid to be synchronous, so the - * default callback just wakes up the current task. - */ - smb->creator =3D get_task_struct(current); - atomic_inc(&mid_count); trace_smb3_cmd_enter(le32_to_cpu(shdr->Id.SyncId.TreeId), le64_to_cpu(shdr->SessionId), diff --git a/fs/smb/client/transport.c b/fs/smb/client/transport.c index 042f689bbf52..7a4788b54a07 100644 --- a/fs/smb/client/transport.c +++ b/fs/smb/client/transport.c @@ -49,8 +49,9 @@ struct smb_message *smb_message_alloc(enum smb2_command c= md, gfp_t gfp) * callback just wakes up the current task. */ smb->callback =3D cifs_wake_up_task; - smb->callback_data =3D current; smb->mid_state =3D MID_REQUEST_ALLOCATED; + + init_waitqueue_head(&smb->waitq); } return smb; } @@ -84,11 +85,11 @@ void smb_put_messages(struct smb_message *smb) } =20 void -cifs_wake_up_task(struct smb_message *smb) +cifs_wake_up_task(struct TCP_Server_Info *server, struct smb_message *smb) { if (smb->mid_state =3D=3D MID_RESPONSE_RECEIVED) smb->mid_state =3D MID_RESPONSE_READY; - wake_up_process(smb->callback_data); + wake_up_all(&smb->waitq); } =20 static void smb_clear_mid(struct smb_message *smb, struct TCP_Server_Info = *server) @@ -163,7 +164,6 @@ static void smb_clear_mid(struct smb_message *smb, stru= ct TCP_Server_Info *serve } } #endif - put_task_struct(smb->creator); } =20 static bool discard_message(struct TCP_Server_Info *server, struct smb_mes= sage *smb) @@ -817,7 +817,7 @@ int wait_for_response(struct TCP_Server_Info *server, s= truct smb_message *smb) if (smb->sr_flags & CIFS_INTERRUPTIBLE_WAIT) sleep_state =3D TASK_INTERRUPTIBLE; =20 - error =3D wait_event_state(server->response_q, + error =3D wait_event_state(smb->waitq, smb->mid_state !=3D MID_REQUEST_SUBMITTED && smb->mid_state !=3D MID_RESPONSE_RECEIVED, (sleep_state | TASK_FREEZABLE_UNSAFE)); @@ -948,9 +948,8 @@ int cifs_sync_mid_result(struct smb_message *smb, struc= t TCP_Server_Info *server } =20 static void -cifs_compound_callback(struct smb_message *smb) +cifs_compound_callback(struct TCP_Server_Info *server, struct smb_message = *smb) { - struct TCP_Server_Info *server =3D smb->server; struct cifs_credits credits =3D { .value =3D server->ops->get_credits(smb), .instance =3D server->reconnect_instance, @@ -963,16 +962,16 @@ cifs_compound_callback(struct smb_message *smb) } =20 static void -cifs_compound_last_callback(struct smb_message *smb) +cifs_compound_last_callback(struct TCP_Server_Info *server, struct smb_mes= sage *smb) { - cifs_compound_callback(smb); - cifs_wake_up_task(smb); + cifs_compound_callback(server, smb); + cifs_wake_up_task(server, smb); } =20 static void -cifs_cancelled_callback(struct smb_message *smb) +cifs_cancelled_callback(struct TCP_Server_Info *server, struct smb_message= *smb) { - cifs_compound_callback(smb); + cifs_compound_callback(server, smb); } =20 /* @@ -1352,7 +1351,7 @@ __cifs_readv_discard(struct TCP_Server_Info *server, = struct smb_message *smb, static int cifs_readv_discard(struct TCP_Server_Info *server, struct smb_message *smb) { - struct cifs_io_subrequest *rdata =3D smb->callback_data; + struct cifs_io_subrequest *rdata =3D smb->subreq; =20 return __cifs_readv_discard(server, smb, rdata->result); } @@ -1362,7 +1361,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, st= ruct smb_message *smb) { int length, len; unsigned int data_offset, data_len; - struct cifs_io_subrequest *rdata =3D smb->callback_data; + struct cifs_io_subrequest *rdata =3D smb->subreq; char *buf =3D server->smallbuf; unsigned int buflen =3D server->pdu_size + HEADER_PREAMBLE_SIZE(server); bool use_rdma_mr =3D false; From nobody Thu Dec 18 03:20:29 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 690882D130C for ; Wed, 6 Aug 2025 20:38:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512741; cv=none; b=Qt9c/zp3uKCS3QGTjHMxN6P+BCKDrya5q0Z6dhPcYuSluaeYSkRIIroqUcNTSwh0kzVN4eiQ8Vt0AGjT4oixkNr5lxHZH1stRNRkbJyzCbEsdUen1Fc/7NgNnQbeELUVpKG50r/l9wR7bGGCfnQWlDkMdvGrLAgKjik2r7EMfGA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512741; c=relaxed/simple; bh=sGkIqwI4kKVf31IFHCvik9vYPq7stY3n3/q2f/ete+w=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=kIJOZIzdyqrcZBwcYQH8644/sPDDwz/dqgTd/240zd5JJeJ8FYLtYmtJef9ujNYkeM7pn4dpfD/Z9Hsl6IsegdKbQpZLa4ofL6Og5IHxFMuTRJMDMVa+SVzoWf99/YYR22+SEDabPOTRrZ6qbs59MuRc1/CTeSE2MUpCLBxij/M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=N0WMvR/P; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="N0WMvR/P" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1754512738; h=from:from:reply-to:subject:subject: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=fWFEygVcswswekGUvxP15RMRYsPo7UmyYBIY6DSNdhI=; b=N0WMvR/P4fZOLmBe/Ae2ROMzxejihQtZXBGDesy98QF2nyNECHg7vNuvVvIxJ7HvKH5qjR AGkHDzoohx9jhRrLgu6jPMhTkXkPlT1ayz009kg7Zbn7FVeiQY3upGtNCV6CZKjuhQKCF2 vOP2k4QefDLU5sfpBBnGtJXj1Kkv6zU= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-329-qk4wtJRiN2m4hgjIOSmZxw-1; Wed, 06 Aug 2025 16:38:54 -0400 X-MC-Unique: qk4wtJRiN2m4hgjIOSmZxw-1 X-Mimecast-MFC-AGG-ID: qk4wtJRiN2m4hgjIOSmZxw_1754512732 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 24DA2195608C; Wed, 6 Aug 2025 20:38:52 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.17]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 130C91800447; Wed, 6 Aug 2025 20:38:48 +0000 (UTC) From: David Howells To: Steve French Cc: David Howells , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Wang Zhaolong , Stefan Metzmacher , Mina Almasry , linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org, netfs@lists.linux.dev, linux-fsdevel@vger.kernel.org Subject: [RFC PATCH 20/31] cifs: Don't need state locking in smb2_get_mid_entry() Date: Wed, 6 Aug 2025 21:36:41 +0100 Message-ID: <20250806203705.2560493-21-dhowells@redhat.com> In-Reply-To: <20250806203705.2560493-1-dhowells@redhat.com> References: <20250806203705.2560493-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Content-Type: text/plain; charset="utf-8" There's no need to get ->srv_lock or ->ses_lock in smb2_get_mid_entry() as all that happens of relevance (to the lock) inside the locked sections is the reading of one status value in each. Replace the locking with READ_ONCE() and use a switch instead of a chain of if-statements. Signed-off-by: David Howells cc: Steve French cc: Paulo Alcantara cc: Shyam Prasad N cc: Tom Talpey cc: linux-cifs@vger.kernel.org cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/smb/client/smb2transport.c | 46 +++++++++++++++-------------------- 1 file changed, 19 insertions(+), 27 deletions(-) diff --git a/fs/smb/client/smb2transport.c b/fs/smb/client/smb2transport.c index 7c60584a8544..7194082bb5ac 100644 --- a/fs/smb/client/smb2transport.c +++ b/fs/smb/client/smb2transport.c @@ -769,43 +769,35 @@ static int smb2_get_mid_entry(struct cifs_ses *ses, struct TCP_Server_Info *server, struct smb_message *smb) { - spin_lock(&server->srv_lock); - if (server->tcpStatus =3D=3D CifsExiting) { - spin_unlock(&server->srv_lock); + switch (READ_ONCE(server->tcpStatus)) { + case CifsExiting: return -ENOENT; - } - - if (server->tcpStatus =3D=3D CifsNeedReconnect) { - spin_unlock(&server->srv_lock); + case CifsNeedReconnect: cifs_dbg(FYI, "tcp session dead - return to caller to retry\n"); return -EAGAIN; + case CifsNeedNegotiate: + if (smb->command_id !=3D SMB2_NEGOTIATE) + return -EAGAIN; + break; + default: + break; } =20 - if (server->tcpStatus =3D=3D CifsNeedNegotiate && - smb->command_id !=3D SMB2_NEGOTIATE) { - spin_unlock(&server->srv_lock); - return -EAGAIN; - } - spin_unlock(&server->srv_lock); - - spin_lock(&ses->ses_lock); - if (ses->ses_status =3D=3D SES_NEW) { + switch (READ_ONCE(ses->ses_status)) { + case SES_NEW: if (smb->command_id !=3D SMB2_SESSION_SETUP && - smb->command_id !=3D SMB2_NEGOTIATE) { - spin_unlock(&ses->ses_lock); + smb->command_id !=3D SMB2_NEGOTIATE) return -EAGAIN; - } - /* else ok - we are setting up session */ - } - - if (ses->ses_status =3D=3D SES_EXITING) { - if (smb->command_id !=3D SMB2_LOGOFF) { - spin_unlock(&ses->ses_lock); + /* else ok - we are setting up session */ + break; + case SES_EXITING: + if (smb->command_id !=3D SMB2_LOGOFF) return -EAGAIN; - } /* else ok - we are shutting down the session */ + break; + default: + break; } - spin_unlock(&ses->ses_lock); =20 smb2_init_mid(smb, server); From nobody Thu Dec 18 03:20:29 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1DB622D23A9 for ; Wed, 6 Aug 2025 20:39:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512744; cv=none; b=AqnD0vuKHTww4EojM0KIoriEl+o1F7NOqY4LPdt8HO2ve56f7fxx9XwbtDOib6jlfP+93yho0ksFUIGsepU+mDb97yUH4Uo1mfwazk/cWGnFCYW+mVXV4bM2ZxzY0RvIfA/I0L/nvw9QV+agnonGMHeeeRrmTar5yZkciAHl4BM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512744; c=relaxed/simple; bh=+eD/sWwxdshenZdDpW9TG7B9UxtTfSihNBWd+vNRfyY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=YXDtihL8xd98oAoipapw7W/2297ZPO6dhVWAVnHpLIjw0I7XlXBNwU5f7YziQt7CJNbKWJpJiKyGhSxAswEXL1UrmzHJdBzGoFVmYLc/i5Y4w2A4gQ3EmM46PHMJafrFP/LrWgHbyZ+iN1TtTrEIseHovDE4TyyOH0UggAASXsU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=MO5ZfvQY; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="MO5ZfvQY" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1754512741; h=from:from:reply-to:subject:subject: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=dst57bsI11GjKrysipjfUIND5eWare7oQxyJC8LbWC4=; b=MO5ZfvQYl4MzgtyDI6Hqz5934ldUnhaTt7GBDk8aDY+c/UPHS+Isg7sHEFgWx4sEUPOIVh 0ohszVHlmyFYeM1aDTnLnQofIzd6zevFYYh8QatDecLPJutEcta67EYDWEDTHmhh7Jg34A vjZbdzD0NlFxvHvz24s4A0SReO+yT58= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-606-aUjvRjiSPrW4rVH7nx40lQ-1; Wed, 06 Aug 2025 16:38:58 -0400 X-MC-Unique: aUjvRjiSPrW4rVH7nx40lQ-1 X-Mimecast-MFC-AGG-ID: aUjvRjiSPrW4rVH7nx40lQ_1754512737 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id E596A1800359; Wed, 6 Aug 2025 20:38:56 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.17]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id C486A180035C; Wed, 6 Aug 2025 20:38:53 +0000 (UTC) From: David Howells To: Steve French Cc: David Howells , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Wang Zhaolong , Stefan Metzmacher , Mina Almasry , linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org, netfs@lists.linux.dev, linux-fsdevel@vger.kernel.org Subject: [RFC PATCH 21/31] cifs: [DEBUG] smb_message refcounting Date: Wed, 6 Aug 2025 21:36:42 +0100 Message-ID: <20250806203705.2560493-22-dhowells@redhat.com> In-Reply-To: <20250806203705.2560493-1-dhowells@redhat.com> References: <20250806203705.2560493-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Howells cc: Steve French cc: Paulo Alcantara cc: Shyam Prasad N cc: Tom Talpey cc: linux-cifs@vger.kernel.org cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/smb/client/cifsglob.h | 1 + fs/smb/client/cifsproto.h | 5 +-- fs/smb/client/connect.c | 14 +++++--- fs/smb/client/smb2ops.c | 3 +- fs/smb/client/smb2pdu.c | 6 ++-- fs/smb/client/smb2transport.c | 2 +- fs/smb/client/trace.h | 61 +++++++++++++++++++++++++++++++++++ fs/smb/client/transport.c | 57 ++++++++++++++++++++++++++------ 8 files changed, 127 insertions(+), 22 deletions(-) diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index 14b132fb14e0..045a29cedf0e 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h @@ -1734,6 +1734,7 @@ struct smb_message { void *request; /* Pointer to request message body */ wait_queue_head_t waitq; /* Wait queue for message events */ refcount_t ref; + unsigned int debug_id; /* Debugging ID for tracing */ bool sensitive; /* Request contains sensitive data */ bool cancelled; /* T if cancelled */ unsigned int sr_flags; /* Flags passed to send_recv() */ diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h index abae67d83499..074b65bb57a5 100644 --- a/fs/smb/client/cifsproto.h +++ b/fs/smb/client/cifsproto.h @@ -761,8 +761,9 @@ static inline void cifs_free_open_info(struct cifs_open= _info_data *data) } =20 struct smb_message *smb_message_alloc(enum smb2_command cmd, gfp_t gfp); -void smb_get_message(struct smb_message *smb); -void smb_put_message(struct smb_message *smb); +void smb_see_message(struct smb_message *smb, enum smb_message_trace trace= ); +void smb_get_message(struct smb_message *smb, enum smb_message_trace trace= ); +void smb_put_message(struct smb_message *smb, enum smb_message_trace trace= ); void smb_put_messages(struct smb_message *smb); =20 #endif /* _CIFSPROTO_H */ diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c index 9bd19dd91d35..74b88304a782 100644 --- a/fs/smb/client/connect.c +++ b/fs/smb/client/connect.c @@ -323,6 +323,7 @@ cifs_abort_connection(struct TCP_Server_Info *server) cifs_dbg(FYI, "%s: moving mids to private list\n", __func__); spin_lock(&server->mid_lock); list_for_each_entry_safe(smb, nsmb, &server->pending_mid_q, qhead) { + smb_see_message(smb, smb_message_trace_see_abort_conn); if (smb->mid_state =3D=3D MID_REQUEST_SUBMITTED) smb->mid_state =3D MID_RETRY_NEEDED; list_move(&smb->qhead, &retry_list); @@ -335,7 +336,7 @@ cifs_abort_connection(struct TCP_Server_Info *server) list_for_each_entry_safe(smb, nsmb, &retry_list, qhead) { list_del_init(&smb->qhead); smb->callback(server, smb); - smb_put_message(smb); + smb_put_message(smb, smb_message_trace_put_abort_conn); } =20 if (cifs_rdma_enabled(server)) { @@ -885,6 +886,7 @@ is_smb_response(struct TCP_Server_Info *server, unsigne= d char type) */ spin_lock(&server->mid_lock); list_for_each_entry_safe(smb, nsmb, &server->pending_mid_q, qhead) { + smb_see_message(smb, smb_message_trace_see_is_smb_resp); list_move(&smb->qhead, &dispose_list); smb->mid_flags |=3D MID_DELETED; } @@ -918,7 +920,7 @@ is_smb_response(struct TCP_Server_Info *server, unsigne= d char type) smb->mid_rc =3D mid_rc; smb->mid_state =3D MID_RC; smb->callback(server, smb); - smb_put_message(smb); + smb_put_message(smb, smb_message_trace_put_is_smb_resp); } =20 /* @@ -968,6 +970,7 @@ dequeue_mid(struct smb_message *smb, bool malformed) spin_unlock(&smb->server->mid_lock); pr_warn_once("trying to dequeue a deleted mid\n"); } else { + smb_see_message(smb, smb_message_trace_see_dequeue_mid); list_del_init(&smb->qhead); smb->mid_flags |=3D MID_DELETED; spin_unlock(&smb->server->mid_lock); @@ -1101,6 +1104,7 @@ clean_demultiplex_info(struct TCP_Server_Info *server) spin_lock(&server->mid_lock); list_for_each_entry_safe(smb, smb2, &server->pending_mid_q, qhead) { cifs_dbg(FYI, "Clearing mid %llu\n", smb->mid); + smb_see_message(smb, smb_message_trace_see_clean_demux); smb->mid_state =3D MID_SHUTDOWN; list_move(&smb->qhead, &dispose_list); smb->mid_flags |=3D MID_DELETED; @@ -1112,7 +1116,7 @@ clean_demultiplex_info(struct TCP_Server_Info *server) cifs_dbg(FYI, "Callback mid %llu\n", smb->mid); list_del_init(&smb->qhead); smb->callback(server, smb); - smb_put_message(smb); + smb_put_message(smb, smb_message_trace_put_clean_demux); } /* 1/8th of sec is more than enough time for them to exit */ msleep(125); @@ -1355,7 +1359,7 @@ cifs_demultiplex_thread(void *p) if (length < 0) { for (i =3D 0; i < num_smbs; i++) if (smbs[i]) - smb_put_message(smbs[i]); + smb_put_message(smbs[i], smb_message_trace_put_demux); continue; } =20 @@ -1390,7 +1394,7 @@ cifs_demultiplex_thread(void *p) if (!smbs[i]->multiRsp || smbs[i]->multiEnd) smbs[i]->callback(server, smbs[i]); =20 - smb_put_message(smbs[i]); + smb_put_message(smbs[i], smb_message_trace_put_demux_cb); } else if (server->ops->is_oplock_break && server->ops->is_oplock_break(bufs[i], server)) { diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c index 63226bbba3d1..1e24489b55e3 100644 --- a/fs/smb/client/smb2ops.c +++ b/fs/smb/client/smb2ops.c @@ -408,6 +408,7 @@ __smb2_find_mid(struct TCP_Server_Info *server, char *b= uf, bool dequeue) if ((smb->mid =3D=3D wire_mid) && (smb->mid_state =3D=3D MID_REQUEST_SUBMITTED) && (smb->command_id =3D=3D command)) { + smb_see_message(smb, smb_message_trace_see_find_mid); if (dequeue) { list_del_init(&smb->qhead); smb->mid_flags |=3D MID_DELETED; @@ -4726,7 +4727,7 @@ static void smb2_decrypt_offload(struct work_struct *= work) spin_unlock(&dw->server->srv_lock); } } - smb_put_message(smb); + smb_put_message(smb, smb_message_trace_put_decrypt_offload); } =20 free_pages: diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c index 8d50036fd028..3009acf0d884 100644 --- a/fs/smb/client/smb2pdu.c +++ b/fs/smb/client/smb2pdu.c @@ -4305,7 +4305,7 @@ SMB2_echo(struct TCP_Server_Info *server) cifs_dbg(FYI, "Echo request failed: %d\n", rc); =20 cifs_small_buf_release(req); - smb_put_message(smb); + smb_put_messages(smb); return rc; } =20 @@ -4753,7 +4753,7 @@ smb2_async_readv(struct cifs_io_subrequest *rdata) =20 async_readv_out: cifs_small_buf_release(buf); - smb_put_message(smb); + smb_put_messages(smb); return rc; } =20 @@ -5127,7 +5127,7 @@ smb2_async_writev(struct cifs_io_subrequest *wdata) =20 async_writev_out: cifs_small_buf_release(req); - smb_put_message(smb); + smb_put_messages(smb); out: if (rc) { trace_smb3_rw_credits(wdata->rreq->debug_id, diff --git a/fs/smb/client/smb2transport.c b/fs/smb/client/smb2transport.c index 7194082bb5ac..da6377521fe9 100644 --- a/fs/smb/client/smb2transport.c +++ b/fs/smb/client/smb2transport.c @@ -801,7 +801,7 @@ smb2_get_mid_entry(struct cifs_ses *ses, struct TCP_Ser= ver_Info *server, =20 smb2_init_mid(smb, server); =20 - smb_get_message(smb); + smb_get_message(smb, smb_message_trace_get_enqueue_sync); spin_lock(&server->mid_lock); list_add_tail(&smb->qhead, &server->pending_mid_q); spin_unlock(&server->mid_lock); diff --git a/fs/smb/client/trace.h b/fs/smb/client/trace.h index 93e5b2bb9f28..5cee63960419 100644 --- a/fs/smb/client/trace.h +++ b/fs/smb/client/trace.h @@ -20,6 +20,45 @@ /* * Specify enums for tracing information. */ +#define smb_message_traces \ + EM(smb_message_trace_alloc_cancel, "AL Cancel ") \ + EM(smb_message_trace_alloc_change_notify, "AL Change-Nfy") \ + EM(smb_message_trace_alloc_close, "AL Close ") \ + EM(smb_message_trace_alloc_create, "AL Create ") \ + EM(smb_message_trace_alloc_echo, "AL Echo ") \ + EM(smb_message_trace_alloc_flush, "AL Flush ") \ + EM(smb_message_trace_alloc_ioctl, "AL Ioctl ") \ + EM(smb_message_trace_alloc_lock, "AL Lock ") \ + EM(smb_message_trace_alloc_logoff, "AL Logoff ") \ + EM(smb_message_trace_alloc_negotiate, "AL Negotiate ") \ + EM(smb_message_trace_alloc_oplock_break, "AL Oplock-Brk") \ + EM(smb_message_trace_alloc_query_directory, "AL Query-Dir ") \ + EM(smb_message_trace_alloc_query_info, "AL Query-Info") \ + EM(smb_message_trace_alloc_read, "AL Read ") \ + EM(smb_message_trace_alloc_session_setup, "AL Sess-setup") \ + EM(smb_message_trace_alloc_set_info, "AL Set-Info ") \ + EM(smb_message_trace_alloc_srv_to_cln_notif, "AL s2c-Notify") \ + EM(smb_message_trace_alloc_tree_connect, "AL Tree-conn ") \ + EM(smb_message_trace_alloc_tree_disconnect, "AL Tree-disc ") \ + EM(smb_message_trace_alloc_write, "AL Write ") \ + EM(smb_message_trace_free, "FREE ") \ + EM(smb_message_trace_get_call_async, "GET call-asyn") \ + EM(smb_message_trace_get_enqueue_sync, "GET enq-sync ") \ + EM(smb_message_trace_put_abort_conn, "PUT abrt-conn") \ + EM(smb_message_trace_put_clean_demux, "PUT cln-demux") \ + EM(smb_message_trace_put_decrypt_offload, "PUT decrypt-o") \ + EM(smb_message_trace_put_demux, "PUT demux ") \ + EM(smb_message_trace_put_demux_cb, "PUT demux-cb ") \ + EM(smb_message_trace_put_discard_message, "PUT disc-msg ") \ + EM(smb_message_trace_put_is_smb_resp, "PUT is-s-resp") \ + EM(smb_message_trace_put_messages, "PUT messages ") \ + EM(smb_message_trace_see_abort_conn, "SEE abrt-conn") \ + EM(smb_message_trace_see_clean_demux, "SEE cln-demux") \ + EM(smb_message_trace_see_dequeue_mid, "SEE deque-mid") \ + EM(smb_message_trace_see_find_mid, "SEE find-mid ") \ + EM(smb_message_trace_see_is_smb_resp, "SEE is-s-resp") \ + E_(smb_message_trace_see_wake_up_task, "SEE wake-task") + #define smb3_rw_credits_traces \ EM(cifs_trace_rw_credits_call_readv_adjust, "rd-call-adj") \ EM(cifs_trace_rw_credits_call_writev_adjust, "wr-call-adj") \ @@ -79,6 +118,7 @@ #define EM(a, b) a, #define E_(a, b) a =20 +enum smb_message_trace { smb_message_traces } __mode(byte); enum smb3_rw_credits_trace { smb3_rw_credits_traces } __mode(byte); enum smb3_tcon_ref_trace { smb3_tcon_ref_traces } __mode(byte); =20 @@ -92,6 +132,7 @@ enum smb3_tcon_ref_trace { smb3_tcon_ref_traces } __mode= (byte); #define EM(a, b) TRACE_DEFINE_ENUM(a); #define E_(a, b) TRACE_DEFINE_ENUM(a); =20 +smb_message_traces; smb3_rw_credits_traces; smb3_tcon_ref_traces; =20 @@ -1573,6 +1614,26 @@ TRACE_EVENT(smb3_rw_credits, __entry->server_credits, __entry->in_flight) ); =20 +TRACE_EVENT(smb3_message, + TP_PROTO(unsigned int smb_message_debug_id, int ref, + enum smb_message_trace trace), + TP_ARGS(smb_message_debug_id, ref, trace), + TP_STRUCT__entry( + __field(unsigned int, smb_message) + __field(int, ref) + __field(enum smb_message_trace, trace) + ), + TP_fast_assign( + __entry->smb_message =3D smb_message_debug_id; + __entry->ref =3D ref; + __entry->trace =3D trace; + ), + TP_printk("SMB=3D%08x %s r=3D%d", + __entry->smb_message, + __print_symbolic(__entry->trace, smb_message_traces), + __entry->ref) + ); + =20 #undef EM #undef E_ diff --git a/fs/smb/client/transport.c b/fs/smb/client/transport.c index 7a4788b54a07..2ccfdd6b958b 100644 --- a/fs/smb/client/transport.c +++ b/fs/smb/client/transport.c @@ -34,12 +34,14 @@ =20 struct smb_message *smb_message_alloc(enum smb2_command cmd, gfp_t gfp) { + static atomic_t debug_ids; struct smb_message *smb; =20 smb =3D mempool_alloc(&smb_message_pool, gfp); if (smb) { memset(smb, 0, sizeof(*smb)); refcount_set(&smb->ref, 1); + smb->debug_id =3D atomic_inc_return(&debug_ids); smb->command_id =3D cmd; smb->when_alloc =3D jiffies; smb->pid =3D current->pid; @@ -52,22 +54,47 @@ struct smb_message *smb_message_alloc(enum smb2_command= cmd, gfp_t gfp) smb->mid_state =3D MID_REQUEST_ALLOCATED; =20 init_waitqueue_head(&smb->waitq); + trace_smb3_message(smb->debug_id, 1, (enum smb_message_trace)cmd); } return smb; } =20 -void smb_get_message(struct smb_message *smb) +void smb_see_message(struct smb_message *smb, enum smb_message_trace trace) { - refcount_inc(&smb->ref); + trace_smb3_message(smb->debug_id, refcount_read(&smb->ref), trace); +} + +void smb_get_message(struct smb_message *smb, enum smb_message_trace trace) +{ + int r; + + __refcount_inc(&smb->ref, &r); + trace_smb3_message(smb->debug_id, r + 1, trace); + printk("GET SMB=3D%08x{%d} %pSR\n", + smb->debug_id, r + 1, __builtin_return_address(0)); +} + +static void smb_free_message(struct smb_message *smb) +{ + trace_smb3_message(smb->debug_id, refcount_read(&smb->ref), + smb_message_trace_free); + mempool_free(smb, &smb_message_pool); } =20 /* * Drop a ref on a message. This does not touch the chained messages. */ -void smb_put_message(struct smb_message *smb) +void smb_put_message(struct smb_message *smb, enum smb_message_trace trace) { - if (refcount_dec_and_test(&smb->ref)) - mempool_free(smb, &smb_message_pool); + unsigned int debug_id =3D smb->debug_id; + bool dead; + int r; + + dead =3D __refcount_dec_and_test(&smb->ref, &r); + trace_smb3_message(debug_id, r - 1, trace); + printk("PUT SMB=3D%08x{%d} %pSR\n", debug_id, r - 1, __builtin_return_add= ress(0)); + if (dead) + smb_free_message(smb); } =20 /* @@ -79,8 +106,17 @@ void smb_put_messages(struct smb_message *smb) struct smb_message *next; =20 for (; smb; smb =3D next) { + unsigned int debug_id =3D smb->debug_id; + bool dead; + int r; + next =3D smb->next; - smb_put_message(smb); + dead =3D __refcount_dec_and_test(&smb->ref, &r); + trace_smb3_message(debug_id, r - 1, smb_message_trace_put_messages); + printk("PUTS SMB=3D%08x{%d} %pSR\n", + debug_id, r - 1, __builtin_return_address(0)); + if (dead) + smb_free_message(smb); } } =20 @@ -89,6 +125,7 @@ cifs_wake_up_task(struct TCP_Server_Info *server, struct= smb_message *smb) { if (smb->mid_state =3D=3D MID_RESPONSE_RECEIVED) smb->mid_state =3D MID_RESPONSE_READY; + smb_see_message(smb, smb_message_trace_see_wake_up_task); wake_up_all(&smb->waitq); } =20 @@ -189,7 +226,7 @@ static void smb_discard_messages(struct TCP_Server_Info= *server, struct smb_mess for (smb =3D head_smb; smb; smb =3D next) { next =3D smb->next; if (discard_message(server, smb)) - smb_put_message(smb); + smb_put_message(smb, smb_message_trace_put_discard_message); } } =20 @@ -877,7 +914,7 @@ cifs_call_async(struct TCP_Server_Info *server, struct = smb_message *smb, smb->mid_state =3D MID_REQUEST_SUBMITTED; =20 /* put it on the pending_mid_q */ - smb_get_message(smb); + smb_get_message(smb, smb_message_trace_get_call_async); spin_lock(&server->mid_lock); list_add_tail(&smb->qhead, &server->pending_mid_q); spin_unlock(&server->mid_lock); @@ -893,7 +930,7 @@ cifs_call_async(struct TCP_Server_Info *server, struct = smb_message *smb, revert_current_mid(server, smb->credits_consumed); server->sequence_number -=3D 2; if (discard_message(server, smb)) - smb_put_message(smb); + smb_put_message(smb, smb_message_trace_put_discard_message); } =20 cifs_server_unlock(server); @@ -1295,7 +1332,7 @@ compound_send_recv(const unsigned int xid, struct cif= s_ses *ses, rc =3D smb_send_recv_messages(xid, ses, server, head_smb, flags); =20 error: - smb_put_messages(smb); + smb_put_messages(head_smb); return rc; } From nobody Thu Dec 18 03:20:29 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7FAFE2D321F for ; Wed, 6 Aug 2025 20:39:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512752; cv=none; b=IiHtAG1osDhyup2j6p1E/KHR29B7apLqT5P1Xa+k5ovIKTpgTxbGgnrBBpqR1yQ7vNQrro5ZoRCoNqRjr+0L6O2YwwlP/uOL1vHI1GeX/jA+yA0m02iT+tctg4p3n35op0i5w/oYzTfVPR1Ry7bGGY+k1LeJWRgwqoPa7b3iV6A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512752; c=relaxed/simple; bh=AJLngiDp+3TtTnh1fTCD7p/AYJk2JTeigIpEMuDSEhM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=RApVJ+FeQQpDVk2rtSnNBtqd+pCn2eJdhgIL8eQisduNoX8T16g1Sb9PD4TZU/zurx9rOTieKqhwBeRrCDL388Cnkw+N3jh3CvkEh+l0KVcjK7dWi4/8p7dZI6xTLQMSzyF4/M4/dOIgEHlm/pJT/Y83ta79RVVi9BQVUkY26xA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=LpT37pgd; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="LpT37pgd" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1754512749; h=from:from:reply-to:subject:subject: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=WgbTabH9yiA1Rp25sUyMqeAC4tSFlKtGr5byFk5yf4o=; b=LpT37pgdXdngZ2SCXFIAhaQ3k4AzwkUPETWY59aIksNzH9zsNthsz0aDhVQdqGxvLlrJJI XhIvQRxReBjerdfq07r0iyXnIwYqZuZASBZlJlrGkEouuO29eRflbhrIQdMNsAlKUiMH+7 sQoPXyksMzKQ7A91lF7he4C9OowBaMw= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-496-UdAZH3cFPrOCSlnjHNSJeA-1; Wed, 06 Aug 2025 16:39:03 -0400 X-MC-Unique: UdAZH3cFPrOCSlnjHNSJeA-1 X-Mimecast-MFC-AGG-ID: UdAZH3cFPrOCSlnjHNSJeA_1754512741 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 71A371800352; Wed, 6 Aug 2025 20:39:01 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.17]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 63E8F1956086; Wed, 6 Aug 2025 20:38:58 +0000 (UTC) From: David Howells To: Steve French Cc: David Howells , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Wang Zhaolong , Stefan Metzmacher , Mina Almasry , linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org, netfs@lists.linux.dev, linux-fsdevel@vger.kernel.org Subject: [RFC PATCH 22/31] cifs: Add netmem allocation functions Date: Wed, 6 Aug 2025 21:36:43 +0100 Message-ID: <20250806203705.2560493-23-dhowells@redhat.com> In-Reply-To: <20250806203705.2560493-1-dhowells@redhat.com> References: <20250806203705.2560493-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Content-Type: text/plain; charset="utf-8" Add (stub) functions for doing netmem allocations. We want to allocate memory from the netmem buffering as that does bulk DMA and IOMMU management. Signed-off-by: David Howells cc: Steve French cc: Paulo Alcantara cc: Shyam Prasad N cc: Tom Talpey cc: linux-cifs@vger.kernel.org cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/smb/client/cifsproto.h | 3 +++ fs/smb/client/transport.c | 15 +++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h index 074b65bb57a5..ccd70a402567 100644 --- a/fs/smb/client/cifsproto.h +++ b/fs/smb/client/cifsproto.h @@ -766,4 +766,7 @@ void smb_get_message(struct smb_message *smb, enum smb_= message_trace trace); void smb_put_message(struct smb_message *smb, enum smb_message_trace trace= ); void smb_put_messages(struct smb_message *smb); =20 +void *cifs_allocate_tx_buf(struct TCP_Server_Info *server, size_t size); +void cifs_free_tx_buf(void *p); + #endif /* _CIFSPROTO_H */ diff --git a/fs/smb/client/transport.c b/fs/smb/client/transport.c index 2ccfdd6b958b..b497bf319a7e 100644 --- a/fs/smb/client/transport.c +++ b/fs/smb/client/transport.c @@ -32,6 +32,21 @@ #include "smbdirect.h" #include "compress.h" =20 +/* + * Allocate transmission buffers for a socket. This memory will be alloca= ted + * from the netmem buffers. It comes with a page ref that we need to drop. + * The networking layer can pin it by getting its own ref. + */ +void *cifs_allocate_tx_buf(struct TCP_Server_Info *server, size_t size) +{ + return NULL; /* TODO */ +} + +void cifs_free_tx_buf(void *p) +{ + /* TODO */ +} + struct smb_message *smb_message_alloc(enum smb2_command cmd, gfp_t gfp) { static atomic_t debug_ids; From nobody Thu Dec 18 03:20:29 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5BA262D3729 for ; Wed, 6 Aug 2025 20:39:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512758; cv=none; b=TL6g/oW1j2KW96PecFYzo5NNhaQOS1aMklZ4tkRDo4IUmd2a4YXHuYY3JmbNz7wo/Eo7hFj0XIZt6HmCtJAXJvpTXwkRVdeL0JUw/MEDISpC6txk2LX91JmPlzjjWyDqb0bWR8HuY7dBNGAffkOdSuB87fK9C86KeCctgQOBnI8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512758; c=relaxed/simple; bh=QntpqNUVgYTVtBSXzFZ+NxT/K9ws0ueULFx/abmOvis=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=SeZoxPXDD6nqO8a3u8EABejZTif/qYp2nIgw5BYODwO8Ssc0MtDIbxnC/6eLuovo2f90CP4SseLdveh9nWAfcEpz1dgxgKqDsKu6oYMtIUzac3UBCtNk7uSXEF5qOPj+20ikSbqcJHLOBM+AsP+R1RbVvtG1glTU8gnn4Cp7tng= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=CF4zmUw2; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="CF4zmUw2" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1754512755; h=from:from:reply-to:subject:subject: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=5TWFDe3ULvHcZ6pORsVwekyETTBpEwWps6j7AzyH0q4=; b=CF4zmUw271b6R1xtXdZdfi2JCjeO/FMQfjmAIlmz2Oho5HxIzyx+yISwuX90guXtQEr67j X11X0VTxyP+Fz041V7QVkuh4Msz7churgT/yuz+xmvIxn1KO5DBaNor1uS96C2RqtvDaXD NhNXE0kX26qQAa26YlH6bFHCoSgpSaA= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-136-Ck5Pq_d0NlmzUyZCqg53_Q-1; Wed, 06 Aug 2025 16:39:07 -0400 X-MC-Unique: Ck5Pq_d0NlmzUyZCqg53_Q-1 X-Mimecast-MFC-AGG-ID: Ck5Pq_d0NlmzUyZCqg53_Q_1754512746 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 1582E1956094; Wed, 6 Aug 2025 20:39:06 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.17]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 00A471956094; Wed, 6 Aug 2025 20:39:02 +0000 (UTC) From: David Howells To: Steve French Cc: David Howells , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Wang Zhaolong , Stefan Metzmacher , Mina Almasry , linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org, netfs@lists.linux.dev, linux-fsdevel@vger.kernel.org Subject: [RFC PATCH 23/31] cifs: Add more pieces to smb_message Date: Wed, 6 Aug 2025 21:36:44 +0100 Message-ID: <20250806203705.2560493-24-dhowells@redhat.com> In-Reply-To: <20250806203705.2560493-1-dhowells@redhat.com> References: <20250806203705.2560493-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Content-Type: text/plain; charset="utf-8" Add more pieces to the smb_message struct to facilitate future changes. Also move towards not needing the server pointer in smb_message. Signed-off-by: David Howells cc: Steve French cc: Paulo Alcantara cc: Shyam Prasad N cc: Tom Talpey cc: linux-cifs@vger.kernel.org cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/smb/client/cifsglob.h | 7 ++ fs/smb/client/cifsproto.h | 15 +++ fs/smb/client/cifstransport.c | 2 +- fs/smb/client/smb2ops.c | 10 ++ fs/smb/client/smb2pdu.c | 198 ++++++++++++++++++++++++++++++++++ fs/smb/client/smb2proto.h | 1 + fs/smb/client/transport.c | 28 ++++- 7 files changed, 259 insertions(+), 2 deletions(-) diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index 045a29cedf0e..0cc71f504c68 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h @@ -1774,7 +1774,12 @@ struct smb_message { /* Request details */ enum smb2_command command_id; /* Command ID */ s16 pre_offset; /* Offset of pre-headers from ->body (negative) */ + u16 ext_offset; /* Offset of extensions from ->body */ + u16 latest_record; /* Offset of latest context record (or 0) */ + u16 offset; /* Running offset during assembly */ + u16 data_offset; /* Offset of data in message (maybe in ->body) */ unsigned int total_len; /* Total length of from hdr_offset onwards */ + struct iov_iter iter; /* Data iterator */ /* Response */ void *response; /* Protocol part of response */ u32 response_len; /* Size of response */ @@ -1782,6 +1787,8 @@ struct smb_message { struct smb_rqst rqst; int *resp_buf_type; struct kvec *resp_iov; + /* Variable-length request fragment list - must be last! */ + struct bvecq bvecq; /* List of request frags (passed to socket) */ }; =20 struct close_cancelled_open { diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h index ccd70a402567..60a0c9b64d98 100644 --- a/fs/smb/client/cifsproto.h +++ b/fs/smb/client/cifsproto.h @@ -765,8 +765,23 @@ void smb_see_message(struct smb_message *smb, enum smb= _message_trace trace); void smb_get_message(struct smb_message *smb, enum smb_message_trace trace= ); void smb_put_message(struct smb_message *smb, enum smb_message_trace trace= ); void smb_put_messages(struct smb_message *smb); +void smb_clear_request(struct smb_message *smb); =20 void *cifs_allocate_tx_buf(struct TCP_Server_Info *server, size_t size); void cifs_free_tx_buf(void *p); =20 +/* + * Add a segment to a message. This should be allocated with + * cifs_allocate_tx_buf() so that it can be used with MSG_SPLICE_PAGES. + */ +static inline void smb_add_segment_to_tx_buf(struct smb_message *smb, + void *key_buf, size_t size) +{ + unsigned int nr =3D smb->bvecq.nr_segs; + + bvec_set_virt(&smb->bvecq.bv[nr], key_buf, size); + smb->bvecq.nr_segs =3D nr++; + smb->total_len +=3D size; +} + #endif /* _CIFSPROTO_H */ diff --git a/fs/smb/client/cifstransport.c b/fs/smb/client/cifstransport.c index 1e2a8839d742..b93dd2be68e1 100644 --- a/fs/smb/client/cifstransport.c +++ b/fs/smb/client/cifstransport.c @@ -177,7 +177,7 @@ cifs_check_receive(struct smb_message *smb, struct TCP_= Server_Info *server, } =20 /* BB special case reconnect tid and uid here? */ - return map_and_check_smb_error(smb, log_error); + return map_and_check_smb_error(server, smb, log_error); } =20 int diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c index 1e24489b55e3..9db383ec22e8 100644 --- a/fs/smb/client/smb2ops.c +++ b/fs/smb/client/smb2ops.c @@ -2602,6 +2602,16 @@ smb2_set_replay(struct TCP_Server_Info *server, stru= ct smb_rqst *rqst) shdr->Flags |=3D SMB2_FLAGS_REPLAY_OPERATION; } =20 +void smb2_set_replay_smb(struct TCP_Server_Info *server, struct smb_messag= e *smb) +{ + struct smb2_hdr *shdr =3D smb->request; + + if (server->dialect < SMB30_PROT_ID) + return; + + shdr->Flags |=3D SMB2_FLAGS_REPLAY_OPERATION; +} + void smb2_set_related(struct smb_rqst *rqst) { diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c index 3009acf0d884..58a2a4ff3368 100644 --- a/fs/smb/client/smb2pdu.c +++ b/fs/smb/client/smb2pdu.c @@ -91,6 +91,204 @@ int smb3_encryption_required(const struct cifs_tcon *tc= on) return 0; } =20 +static void smb2_enc_header(struct smb_message *smb, + const struct cifs_tcon *tcon, + struct TCP_Server_Info *server) +{ + struct smb2_hdr *shdr =3D smb->request; + struct smb3_hdr_req *smb3_hdr =3D (struct smb3_hdr_req *)shdr; + + shdr->ProtocolId =3D SMB2_PROTO_NUMBER; + shdr->StructureSize =3D cpu_to_le16(64); + shdr->CreditCharge =3D 0; + shdr->Status =3D 0; /* ChanSeq for smb3 */ + shdr->Command =3D cpu_to_le16(smb->command_id); + shdr->CreditRequest =3D cpu_to_le16(2); + shdr->Flags =3D 0; + shdr->NextCommand =3D 0; + shdr->MessageId =3D 0; + shdr->Id.SyncId.ProcessId =3D cpu_to_le32((__u16)current->tgid); + shdr->SessionId =3D 0; + + if (server) { + /* After reconnect SMB3 must set ChannelSequence on subsequent reqs */ + if (server->dialect >=3D SMB30_PROT_ID) { + /* + * if primary channel is not set yet, use default + * channel for chan sequence num + */ + if (SERVER_IS_CHAN(server)) + smb3_hdr->ChannelSequence =3D + cpu_to_le16(server->primary_server->channel_sequence_num); + else + smb3_hdr->ChannelSequence =3D + cpu_to_le16(server->channel_sequence_num); + } + spin_lock(&server->req_lock); + /* Request up to 10 credits but don't go over the limit. */ + if (server->credits >=3D server->max_credits) + shdr->CreditRequest =3D cpu_to_le16(0); + else + shdr->CreditRequest =3D cpu_to_le16( + min_t(int, server->max_credits - + server->credits, 10)); + spin_unlock(&server->req_lock); + } + + if (tcon) { + /* GLOBAL_CAP_LARGE_MTU will only be set if dialect > SMB2.02 */ + /* See sections 2.2.4 and 3.2.4.1.5 of MS-SMB2 */ + if (server && (server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU)) + shdr->CreditCharge =3D cpu_to_le16(1); + /* else CreditCharge MBZ */ + + shdr->Id.SyncId.TreeId =3D cpu_to_le32(tcon->tid); + /* Uid is not converted */ + if (tcon->ses) + shdr->SessionId =3D cpu_to_le64(tcon->ses->Suid); + + /* + * If we would set SMB2_FLAGS_DFS_OPERATIONS on open we also + * would have to pass the path on the Open SMB prefixed by + * \\server\share. Not sure when we would need to do the + * augmented path (if ever) and setting this flag breaks the + * SMB2 open operation since it is illegal to send an empty + * path name (without \\server\share prefix) when the DFS flag + * is set in the SMB open header. We could consider setting the + * flag on all operations other than open but it is safer to + * net set it for now. + */ +/* if (tcon->share_flags & SHI1005_FLAGS_DFS) + shdr->Flags |=3D SMB2_FLAGS_DFS_OPERATIONS; */ + + if (server && server->sign && !smb3_encryption_required(tcon)) + shdr->Flags |=3D SMB2_FLAGS_SIGNED; + } +} + +/* Flags for smb2_create_request() */ +#define SMB2_REQ_DYNAMIC 0x01 /* Dynamic request */ +#define SMB2_REQ_HEAD 0x02 /* Head of compound */ +#define SMB2_REQ_SENSITIVE 0x04 /* May contain sensitive crypto data */ + +/* + * smb2_create_request: Allocate and set up a request + * @command: The command type we're going to issue + * @server: The server the command is going to go to + * @header_size: The size of the base protocol structure + * @protocol_size: The size of the header plus extensions + * @data_size: The size of the data payload + * @head: If this is the head of a compound + * @flags: Mask of SMB2_REQ_* flags + * + * Create a request and allocate netmem memory to hold the netbios header = (if + * appropriate) and the protocol part of the message. Memory will also be + * allocated for the data part of the message if this is to be encrypted b= y the + * CPU. The allocated buffers will be attached to a bvec-queue struct so = that + * they can be chained together and passed to the socket. + */ +static struct smb_message *smb2_create_request(enum smb2_command command, + struct TCP_Server_Info *server, + struct cifs_tcon *tcon, + size_t header_size, + size_t protocol_size, + size_t data_size, + unsigned int flags) +{ + struct smb_message *smb; + const size_t max_segs =3D 3; /* We preallocate 3 segment slots in the mes= sage */ + size_t pre_size; + void *body; + bool encrypted =3D false; //, rdma =3D false; + u16 ssize; + + smb =3D kzalloc(struct_size(smb, bvecq.bv, max_segs), GFP_NOFS); + if (!smb) + return NULL; + + smb->command_id =3D command; + smb->sensitive =3D flags & SMB2_REQ_SENSITIVE; + + /* We allocate space for inter-SMB padding or rfc1002 header plus + * transform headers (as needed), but don't add them in at this time. + */ + pre_size =3D 8; + if (encrypted) + pre_size +=3D sizeof(struct smb2_transform_hdr); + smb->pre_offset =3D -pre_size; + + if (encrypted) + /* We want the encrypted blob to be correctly aligned. */ + pre_size =3D round_up(pre_size, 16); + + /* Allocate space for the SMB header, the request struct (both in + * header_size) plus any extension bits, bearing in mind that some bits + * may follow the header directly (header_added_size) and some may have + * to be padded to an 8-byte alignment first (extension_size). The + * Negotiate Request has both. + */ + smb->ext_offset =3D header_size; + smb->offset =3D header_size; + smb->data_offset =3D protocol_size; + smb->total_len =3D protocol_size; + + body =3D cifs_allocate_tx_buf(server, pre_size + protocol_size); + if (!body) { + kfree(smb); + return NULL; + } + + smb_add_segment_to_tx_buf(smb, body + pre_size, protocol_size); + smb->request =3D body + pre_size; + smb->bvecq.max_segs =3D max_segs; + + struct smb2_pdu *spdu =3D body; + + smb2_enc_header(smb, tcon, server); + ssize =3D header_size - sizeof(spdu->hdr); + if (flags & SMB2_REQ_DYNAMIC) + ssize |=3D SMB2_STRUCT_HAS_DYNAMIC_PART; + spdu->StructureSize2 =3D cpu_to_le16(ssize); + + if (tcon) { + cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_sent[command]); + cifs_stats_inc(&tcon->num_smbs_sent); + } + + /* Include the buffer from the start of the RFC1002 header in the + * iterator, but may need to adjust it later. + */ + iov_iter_bvec_queue(&smb->iter, ITER_SOURCE, &smb->bvecq, 0, + pre_size, protocol_size); + + return smb; +} + +static void cifs_pad_to_8(struct smb_message *smb) +{ + size_t offset =3D smb->offset; + u8 *p =3D smb->request; + + while (offset & 7) + p[offset++] =3D 0; + smb->offset =3D offset; +} + +/* + * Begin adding an extension to a message. The offset is padded to an 8-b= yte + * alignment; + */ +static void *cifs_begin_extension(struct smb_message *smb) +{ + cifs_pad_to_8(smb); + return smb->request + smb->offset; +} + +static void cifs_end_extension(struct smb_message *smb, size_t size) +{ + smb->offset +=3D size; +} + static void smb2_hdr_assemble(struct smb2_hdr *shdr, enum smb2_command smb2_cmd, const struct cifs_tcon *tcon, diff --git a/fs/smb/client/smb2proto.h b/fs/smb/client/smb2proto.h index 3018b171c6de..22284a52f300 100644 --- a/fs/smb/client/smb2proto.h +++ b/fs/smb/client/smb2proto.h @@ -131,6 +131,7 @@ extern void smb2_set_next_command(struct cifs_tcon *tco= n, extern void smb2_set_related(struct smb_rqst *rqst); extern void smb2_set_replay(struct TCP_Server_Info *server, struct smb_rqst *rqst); +void smb2_set_replay_smb(struct TCP_Server_Info *server, struct smb_messag= e *smb); extern bool smb2_should_replay(struct cifs_tcon *tcon, int *pretries, int *pcur_sleep); diff --git a/fs/smb/client/transport.c b/fs/smb/client/transport.c index b497bf319a7e..1d732953a90b 100644 --- a/fs/smb/client/transport.c +++ b/fs/smb/client/transport.c @@ -93,9 +93,31 @@ static void smb_free_message(struct smb_message *smb) { trace_smb3_message(smb->debug_id, refcount_read(&smb->ref), smb_message_trace_free); + cifs_free_tx_buf(smb->request); mempool_free(smb, &smb_message_pool); } =20 +/* + * Clear the request parts of a message. + */ +void smb_clear_request(struct smb_message *smb) +{ + for (; smb; smb =3D smb->next) { + if (smb->request) { + if (smb->sensitive) { + iov_iter_bvec_queue(&smb->iter, ITER_SOURCE, + &smb->bvecq, 3, + -smb->pre_offset, + smb->ext_offset - -smb->pre_offset); + iov_iter_zero(smb->ext_offset - -smb->pre_offset, + &smb->iter); + } + cifs_free_tx_buf(smb->request); + smb->request =3D NULL; + } + } +} + /* * Drop a ref on a message. This does not touch the chained messages. */ @@ -120,6 +142,8 @@ void smb_put_messages(struct smb_message *smb) { struct smb_message *next; =20 + smb_clear_request(smb); + for (; smb; smb =3D next) { unsigned int debug_id =3D smb->debug_id; bool dead; @@ -1099,9 +1123,11 @@ int smb_send_recv_messages(const unsigned int xid, s= truct cifs_ses *ses, optype =3D flags & CIFS_OP_MASK; =20 /* TODO: Stitch together the messages in a compound. */ + //u32 last_next =3D 0; nr_reqs =3D 0; - for (struct smb_message *smb =3D head_smb; smb; smb =3D smb->next) + for (struct smb_message *smb =3D head_smb; smb; smb =3D smb->next) { nr_reqs++; + } =20 spin_lock(&server->srv_lock); if (server->tcpStatus =3D=3D CifsExiting) { From nobody Thu Dec 18 03:20:29 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 16B212D3233 for ; Wed, 6 Aug 2025 20:39:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512761; cv=none; b=YxEJBmxfyylvG0YgoTaGW8hr/oQB8+G72rr9ttUA6dZ8DAakFWUcN4PP7VMJhXXJj0SY5x/D2x7GDT+bBBvEdIBKuWDQaLzkR8Asz7SSH4jrZ2eRkUnqoI4UkRI7Z/YOrHfhVc2EPdj3lijbWt8MwzmaYjoP0BoVtL64tuqx89c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512761; c=relaxed/simple; bh=T2bSoxrSwOGDQ+OPDN6pZ89/dtL2KAnQ+Cou834QaRs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=koic+83NWch+R0XLoOnvlCA7cpJkszcNz1vbS0Fwwfp8XKQ7lgTE3NAXauNq2HFDmopQb2ZepO7vDoRUR+lxUKfrsmIH2g3ZnhEDovBzvoG+HrvxQZ4rHx1NlRWlK4avfLQECarR3OiNzhGdUXWynjSPEy6dPCGP6sz5Ez7vCgc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=Kn/QR/b9; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="Kn/QR/b9" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1754512757; h=from:from:reply-to:subject:subject: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=HjeSK8GjGxfDr1EtNwWgacqn2lDSd3SKB7IJ3INJ84c=; b=Kn/QR/b9JzzuKjcCpBUOLe5stefCKtGiSvLkPRdX3xSI/MB+oF0z4C61qYCDPYLs2zkQN1 WSqMhFr5nWFzL5okklm6G5h25nen3h827XfAAtfBVVuR1iEy5WUKjJy58bIoHT8OIIXoGr 0fLnlD9ZP4/TjkIRQY0bmgzEQPrdZFs= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-671-qbmsm-QuPm2cVbAzIxy3XA-1; Wed, 06 Aug 2025 16:39:12 -0400 X-MC-Unique: qbmsm-QuPm2cVbAzIxy3XA-1 X-Mimecast-MFC-AGG-ID: qbmsm-QuPm2cVbAzIxy3XA_1754512750 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id CB54F1956094; Wed, 6 Aug 2025 20:39:10 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.17]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 8238019560AD; Wed, 6 Aug 2025 20:39:07 +0000 (UTC) From: David Howells To: Steve French Cc: David Howells , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Wang Zhaolong , Stefan Metzmacher , Mina Almasry , linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org, netfs@lists.linux.dev, linux-fsdevel@vger.kernel.org Subject: [RFC PATCH 24/31] cifs: Convert SMB2 Negotiate Protocol request Date: Wed, 6 Aug 2025 21:36:45 +0100 Message-ID: <20250806203705.2560493-25-dhowells@redhat.com> In-Reply-To: <20250806203705.2560493-1-dhowells@redhat.com> References: <20250806203705.2560493-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Howells cc: Steve French cc: Paulo Alcantara cc: Shyam Prasad N cc: Tom Talpey cc: linux-cifs@vger.kernel.org cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/smb/client/smb2pdu.c | 509 ++++++++++++++++++++++++---------------- fs/smb/common/smb2pdu.h | 24 +- fs/smb/server/smb2pdu.c | 22 +- 3 files changed, 319 insertions(+), 236 deletions(-) diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c index 58a2a4ff3368..f1b6d36fe7cd 100644 --- a/fs/smb/client/smb2pdu.c +++ b/fs/smb/client/smb2pdu.c @@ -788,144 +788,200 @@ static int smb2_ioctl_req_init(u32 opcode, struct c= ifs_tcon *tcon, =20 /* For explanation of negotiate contexts see MS-SMB2 section 2.2.3.1 */ =20 -static void -build_preauth_ctxt(struct smb2_preauth_neg_context *pneg_ctxt) +static void *cifs_begin_neg_context(struct smb_message *smb, + __le16 context_type) { - pneg_ctxt->ContextType =3D SMB2_PREAUTH_INTEGRITY_CAPABILITIES; - pneg_ctxt->DataLength =3D cpu_to_le16(38); - pneg_ctxt->HashAlgorithmCount =3D cpu_to_le16(1); - pneg_ctxt->SaltLength =3D cpu_to_le16(SMB311_SALT_SIZE); - get_random_bytes(pneg_ctxt->Salt, SMB311_SALT_SIZE); - pneg_ctxt->HashAlgorithms =3D SMB2_PREAUTH_INTEGRITY_SHA512; + struct smb2_neg_context *neg; + + neg =3D cifs_begin_extension(smb); + neg->ContextType =3D context_type; + neg->Reserved =3D 0; + return (void *)neg; } =20 -static void -build_compression_ctxt(struct smb2_compression_capabilities_context *pneg_= ctxt) +static void cifs_end_neg_context(struct smb_message *smb, void *p, size_t = size) +{ + struct smb2_neg_context *neg =3D p; + + neg->DataLength =3D cpu_to_le16(size - sizeof(*neg)); + cifs_end_extension(smb, size); +} + +static void build_preauth_ctxt(struct smb_message *smb) { - pneg_ctxt->ContextType =3D SMB2_COMPRESSION_CAPABILITIES; - pneg_ctxt->DataLength =3D - cpu_to_le16(sizeof(struct smb2_compression_capabilities_context) - - sizeof(struct smb2_neg_context)); - pneg_ctxt->CompressionAlgorithmCount =3D cpu_to_le16(3); - pneg_ctxt->CompressionAlgorithms[0] =3D SMB3_COMPRESS_LZ77; - pneg_ctxt->CompressionAlgorithms[1] =3D SMB3_COMPRESS_LZ77_HUFF; - pneg_ctxt->CompressionAlgorithms[2] =3D SMB3_COMPRESS_LZNT1; + struct smb2_preauth_neg_context *preauth; + + preauth =3D cifs_begin_neg_context(smb, SMB2_PREAUTH_INTEGRITY_CAPABILITI= ES); + preauth->HashAlgorithmCount =3D cpu_to_le16(1); + preauth->SaltLength =3D cpu_to_le16(SMB311_SALT_SIZE); + preauth->HashAlgorithms =3D SMB2_PREAUTH_INTEGRITY_SHA512; + get_random_bytes(preauth->Salt, SMB311_SALT_SIZE); + cifs_end_neg_context(smb, preauth, sizeof(*preauth)); } =20 -static unsigned int -build_signing_ctxt(struct smb2_signing_capabilities *pneg_ctxt) +static void build_compression_ctxt(struct smb_message *smb) +{ + struct smb2_compression_capabilities_context *compr; + + compr =3D cifs_begin_neg_context(smb, SMB2_COMPRESSION_CAPABILITIES); + compr->CompressionAlgorithmCount =3D cpu_to_le16(3); + compr->CompressionAlgorithms[0] =3D SMB3_COMPRESS_LZ77; + compr->CompressionAlgorithms[1] =3D SMB3_COMPRESS_LZ77_HUFF; + compr->CompressionAlgorithms[2] =3D SMB3_COMPRESS_LZNT1; + cifs_end_neg_context(smb, compr, sizeof(*compr)); +} + +static size_t smb2_size_signing_ctxt(void) +{ + size_t ctxt_len =3D sizeof(struct smb2_signing_capabilities); + unsigned short num_algs =3D 1; /* number of signing algorithms sent */ + + ctxt_len +=3D sizeof(__le16) * num_algs; + return ALIGN8(ctxt_len); +} + +static void build_signing_ctxt(struct smb_message *smb) { - unsigned int ctxt_len =3D sizeof(struct smb2_signing_capabilities); + struct smb2_signing_capabilities *scap; unsigned short num_algs =3D 1; /* number of signing algorithms sent */ =20 - pneg_ctxt->ContextType =3D SMB2_SIGNING_CAPABILITIES; + scap =3D cifs_begin_neg_context(smb, SMB2_SIGNING_CAPABILITIES); + scap->SigningAlgorithmCount =3D cpu_to_le16(num_algs); + scap->SigningAlgorithms[0] =3D cpu_to_le16(SIGNING_ALG_AES_CMAC); + /* TBD add SIGNING_ALG_AES_GMAC and/or SIGNING_ALG_HMAC_SHA256 */ + /* * Context Data length must be rounded to multiple of 8 for some servers */ - pneg_ctxt->DataLength =3D cpu_to_le16(ALIGN8(sizeof(struct smb2_signing_c= apabilities) - - sizeof(struct smb2_neg_context) + - (num_algs * sizeof(u16)))); - pneg_ctxt->SigningAlgorithmCount =3D cpu_to_le16(num_algs); - pneg_ctxt->SigningAlgorithms[0] =3D cpu_to_le16(SIGNING_ALG_AES_CMAC); - - ctxt_len +=3D sizeof(__le16) * num_algs; - ctxt_len =3D ALIGN8(ctxt_len); - return ctxt_len; - /* TBD add SIGNING_ALG_AES_GMAC and/or SIGNING_ALG_HMAC_SHA256 */ + cifs_end_neg_context(smb, scap, + ALIGN8(struct_size(scap, SigningAlgorithms, num_algs))); } =20 -static void -build_encrypt_ctxt(struct smb2_encryption_neg_context *pneg_ctxt) +static void build_encrypt_ctxt(struct smb_message *smb) { - pneg_ctxt->ContextType =3D SMB2_ENCRYPTION_CAPABILITIES; - if (require_gcm_256) { - pneg_ctxt->DataLength =3D cpu_to_le16(4); /* Cipher Count + 1 cipher */ - pneg_ctxt->CipherCount =3D cpu_to_le16(1); - pneg_ctxt->Ciphers[0] =3D SMB2_ENCRYPTION_AES256_GCM; - } else if (enable_gcm_256) { - pneg_ctxt->DataLength =3D cpu_to_le16(8); /* Cipher Count + 3 ciphers */ - pneg_ctxt->CipherCount =3D cpu_to_le16(3); - pneg_ctxt->Ciphers[0] =3D SMB2_ENCRYPTION_AES128_GCM; - pneg_ctxt->Ciphers[1] =3D SMB2_ENCRYPTION_AES256_GCM; - pneg_ctxt->Ciphers[2] =3D SMB2_ENCRYPTION_AES128_CCM; + struct smb2_encryption_neg_context *ecap; + size_t count; + + ecap =3D cifs_begin_neg_context(smb, SMB2_ENCRYPTION_CAPABILITIES); + + if (READ_ONCE(require_gcm_256)) { + ecap->Ciphers[0] =3D SMB2_ENCRYPTION_AES256_GCM; + count =3D 1; + } else if (READ_ONCE(enable_gcm_256)) { + ecap->Ciphers[0] =3D SMB2_ENCRYPTION_AES128_GCM; + ecap->Ciphers[1] =3D SMB2_ENCRYPTION_AES256_GCM; + ecap->Ciphers[2] =3D SMB2_ENCRYPTION_AES128_CCM; + count =3D 3; } else { - pneg_ctxt->DataLength =3D cpu_to_le16(6); /* Cipher Count + 2 ciphers */ - pneg_ctxt->CipherCount =3D cpu_to_le16(2); - pneg_ctxt->Ciphers[0] =3D SMB2_ENCRYPTION_AES128_GCM; - pneg_ctxt->Ciphers[1] =3D SMB2_ENCRYPTION_AES128_CCM; + ecap->Ciphers[0] =3D SMB2_ENCRYPTION_AES128_GCM; + ecap->Ciphers[1] =3D SMB2_ENCRYPTION_AES128_CCM; + count =3D 2; } + ecap->CipherCount =3D cpu_to_le16(count); + cifs_end_neg_context(smb, ecap, struct_size(ecap, Ciphers, count)); } =20 -static unsigned int -build_netname_ctxt(struct smb2_netname_neg_context *pneg_ctxt, char *hostn= ame) +static size_t smb2_size_netname_ctxt(struct TCP_Server_Info *server) { + size_t data_len; + +#if 0 struct nls_table *cp =3D load_nls_default(); + const char *hostname; =20 - pneg_ctxt->ContextType =3D SMB2_NETNAME_NEGOTIATE_CONTEXT_ID; + /* Only include up to first 100 bytes of server name in the NetName + * field. + */ + cifs_server_lock(pserver); + hostname =3D pserver->hostname; + if (hostname && hostname[0]) + data_len =3D cifs_size_strtoUTF16(hostname, 100, cp); + cifs_server_unlock(pserver); +#else + /* Now, we can't just measure the length of hostname as, unless we hold + * the lock, it may change under us, so allow maximum space for it. + */ + data_len =3D 400; +#endif + return ALIGN8(sizeof(struct smb2_neg_context) + data_len); +} + +static void build_netname_ctxt(struct smb_message *smb, const char *hostna= me) +{ + struct smb2_netname_neg_context *name; + struct nls_table *cp =3D load_nls_default(); + size_t count; + + name =3D cifs_begin_neg_context(smb, SMB2_NETNAME_NEGOTIATE_CONTEXT_ID); =20 /* copy up to max of first 100 bytes of server name to NetName field */ - pneg_ctxt->DataLength =3D cpu_to_le16(2 * cifs_strtoUTF16(pneg_ctxt->NetN= ame, hostname, 100, cp)); - /* context size is DataLength + minimal smb2_neg_context */ - return ALIGN8(le16_to_cpu(pneg_ctxt->DataLength) + sizeof(struct smb2_neg= _context)); + count =3D cifs_strtoUTF16(name->NetName, hostname, 100, cp); + cifs_end_neg_context(smb, name, struct_size(name, NetName, count)); } =20 -static void -build_posix_ctxt(struct smb2_posix_neg_context *pneg_ctxt) +static void build_posix_ctxt(struct smb_message *smb) { - pneg_ctxt->ContextType =3D SMB2_POSIX_EXTENSIONS_AVAILABLE; - pneg_ctxt->DataLength =3D cpu_to_le16(POSIX_CTXT_DATA_LEN); + struct smb2_posix_neg_context *posix; + + posix =3D cifs_begin_neg_context(smb, SMB2_POSIX_EXTENSIONS_AVAILABLE); /* SMB2_CREATE_TAG_POSIX is "0x93AD25509CB411E7B42383DE968BCD7C" */ - pneg_ctxt->Name[0] =3D 0x93; - pneg_ctxt->Name[1] =3D 0xAD; - pneg_ctxt->Name[2] =3D 0x25; - pneg_ctxt->Name[3] =3D 0x50; - pneg_ctxt->Name[4] =3D 0x9C; - pneg_ctxt->Name[5] =3D 0xB4; - pneg_ctxt->Name[6] =3D 0x11; - pneg_ctxt->Name[7] =3D 0xE7; - pneg_ctxt->Name[8] =3D 0xB4; - pneg_ctxt->Name[9] =3D 0x23; - pneg_ctxt->Name[10] =3D 0x83; - pneg_ctxt->Name[11] =3D 0xDE; - pneg_ctxt->Name[12] =3D 0x96; - pneg_ctxt->Name[13] =3D 0x8B; - pneg_ctxt->Name[14] =3D 0xCD; - pneg_ctxt->Name[15] =3D 0x7C; + posix->Name[0] =3D 0x93; + posix->Name[1] =3D 0xAD; + posix->Name[2] =3D 0x25; + posix->Name[3] =3D 0x50; + posix->Name[4] =3D 0x9C; + posix->Name[5] =3D 0xB4; + posix->Name[6] =3D 0x11; + posix->Name[7] =3D 0xE7; + posix->Name[8] =3D 0xB4; + posix->Name[9] =3D 0x23; + posix->Name[10] =3D 0x83; + posix->Name[11] =3D 0xDE; + posix->Name[12] =3D 0x96; + posix->Name[13] =3D 0x8B; + posix->Name[14] =3D 0xCD; + posix->Name[15] =3D 0x7C; + cifs_end_neg_context(smb, posix, sizeof(posix)); } =20 -static void -assemble_neg_contexts(struct smb2_negotiate_req *req, - struct TCP_Server_Info *server, unsigned int *total_len) +static size_t smb2_size_neg_contexts(struct TCP_Server_Info *server, + size_t offset) { - unsigned int ctxt_len, neg_context_count; struct TCP_Server_Info *pserver; - char *pneg_ctxt; - char *hostname; - - if (*total_len > 200) { - /* In case length corrupted don't want to overrun smb buffer */ - cifs_server_dbg(VFS, "Bad frame length assembling neg contexts\n"); - return; - } =20 /* * round up total_len of fixed part of SMB3 negotiate request to 8 * byte boundary before adding negotiate contexts */ - *total_len =3D ALIGN8(*total_len); + offset =3D ALIGN8(offset); + offset +=3D ALIGN8(sizeof(struct smb2_preauth_neg_context)); + offset +=3D ALIGN8(sizeof(struct smb2_encryption_neg_context)); =20 - pneg_ctxt =3D (*total_len) + (char *)req; - req->NegotiateContextOffset =3D cpu_to_le32(*total_len); + /* + * secondary channels don't have the hostname field populated + * use the hostname field in the primary channel instead + */ + pserver =3D SERVER_IS_CHAN(server) ? server->primary_server : server; + offset +=3D smb2_size_netname_ctxt(pserver); + + offset +=3D ALIGN8(sizeof(struct smb2_posix_neg_context)); + if (server->compression.requested) + offset +=3D ALIGN8(sizeof(struct smb2_compression_capabilities_context)); + if (enable_negotiate_signing) + offset +=3D smb2_size_signing_ctxt(); + return offset; +} =20 - build_preauth_ctxt((struct smb2_preauth_neg_context *)pneg_ctxt); - ctxt_len =3D ALIGN8(sizeof(struct smb2_preauth_neg_context)); - *total_len +=3D ctxt_len; - pneg_ctxt +=3D ctxt_len; +static void +assemble_neg_contexts(struct smb_message *smb, struct TCP_Server_Info *ser= ver) +{ + struct smb2_negotiate_req *req; + struct TCP_Server_Info *pserver; + const char *hostname; + unsigned int neg_context_count =3D 2; =20 - build_encrypt_ctxt((struct smb2_encryption_neg_context *)pneg_ctxt); - ctxt_len =3D ALIGN8(sizeof(struct smb2_encryption_neg_context)); - *total_len +=3D ctxt_len; - pneg_ctxt +=3D ctxt_len; + build_preauth_ctxt(smb); + build_encrypt_ctxt(smb); =20 /* * secondary channels don't have the hostname field populated @@ -934,47 +990,36 @@ assemble_neg_contexts(struct smb2_negotiate_req *req, pserver =3D SERVER_IS_CHAN(server) ? server->primary_server : server; cifs_server_lock(pserver); hostname =3D pserver->hostname; - if (hostname && (hostname[0] !=3D 0)) { - ctxt_len =3D build_netname_ctxt((struct smb2_netname_neg_context *)pneg_= ctxt, - hostname); - *total_len +=3D ctxt_len; - pneg_ctxt +=3D ctxt_len; - neg_context_count =3D 3; - } else - neg_context_count =3D 2; + if (hostname && hostname[0]) { + build_netname_ctxt(smb, hostname); + neg_context_count++; + } cifs_server_unlock(pserver); =20 - build_posix_ctxt((struct smb2_posix_neg_context *)pneg_ctxt); - *total_len +=3D sizeof(struct smb2_posix_neg_context); - pneg_ctxt +=3D sizeof(struct smb2_posix_neg_context); + build_posix_ctxt(smb); neg_context_count++; =20 if (server->compression.requested) { - build_compression_ctxt((struct smb2_compression_capabilities_context *) - pneg_ctxt); - ctxt_len =3D ALIGN8(sizeof(struct smb2_compression_capabilities_context)= ); - *total_len +=3D ctxt_len; - pneg_ctxt +=3D ctxt_len; + build_compression_ctxt(smb); neg_context_count++; } =20 if (enable_negotiate_signing) { - ctxt_len =3D build_signing_ctxt((struct smb2_signing_capabilities *) - pneg_ctxt); - *total_len +=3D ctxt_len; - pneg_ctxt +=3D ctxt_len; + build_signing_ctxt(smb); neg_context_count++; } =20 /* check for and add transport_capabilities and signing capabilities */ + req =3D smb->request; req->NegotiateContextCount =3D cpu_to_le16(neg_context_count); - } =20 /* If invalid preauth context warn but use what we requested, SHA-512 */ -static void decode_preauth_context(struct smb2_preauth_neg_context *ctxt) +static void decode_preauth_context(struct smb2_neg_context *neg) { - unsigned int len =3D le16_to_cpu(ctxt->DataLength); + struct smb2_preauth_neg_context *ctxt =3D + container_of(neg, struct smb2_preauth_neg_context, neg); + unsigned int len =3D le16_to_cpu(ctxt->neg.DataLength); =20 /* * Caller checked that DataLength remains within SMB boundary. We still @@ -994,9 +1039,11 @@ static void decode_preauth_context(struct smb2_preaut= h_neg_context *ctxt) } =20 static void decode_compress_ctx(struct TCP_Server_Info *server, - struct smb2_compression_capabilities_context *ctxt) + struct smb2_neg_context *neg) { - unsigned int len =3D le16_to_cpu(ctxt->DataLength); + struct smb2_compression_capabilities_context *ctxt =3D + container_of(neg, struct smb2_compression_capabilities_context, neg); + unsigned int len =3D le16_to_cpu(ctxt->neg.DataLength); __le16 alg; =20 server->compression.enabled =3D false; @@ -1029,9 +1076,11 @@ static void decode_compress_ctx(struct TCP_Server_In= fo *server, } =20 static int decode_encrypt_ctx(struct TCP_Server_Info *server, - struct smb2_encryption_neg_context *ctxt) + struct smb2_neg_context *neg) { - unsigned int len =3D le16_to_cpu(ctxt->DataLength); + struct smb2_encryption_neg_context *ctxt =3D + container_of(neg, struct smb2_encryption_neg_context, neg); + unsigned int len =3D le16_to_cpu(ctxt->neg.DataLength); =20 cifs_dbg(FYI, "decode SMB3.11 encryption neg context of len %d\n", len); /* @@ -1081,9 +1130,11 @@ static int decode_encrypt_ctx(struct TCP_Server_Info= *server, } =20 static void decode_signing_ctx(struct TCP_Server_Info *server, - struct smb2_signing_capabilities *pctxt) + struct smb2_neg_context *neg) { - unsigned int len =3D le16_to_cpu(pctxt->DataLength); + struct smb2_signing_capabilities *pctxt =3D + container_of(neg, struct smb2_signing_capabilities, neg); + unsigned int len =3D le16_to_cpu(pctxt->neg.DataLength); =20 /* * Caller checked that DataLength remains within SMB boundary. We still @@ -1110,11 +1161,12 @@ static void decode_signing_ctx(struct TCP_Server_In= fo *server, } =20 =20 -static int smb311_decode_neg_context(struct smb2_negotiate_rsp *rsp, - struct TCP_Server_Info *server, - unsigned int len_of_smb) +static int smb311_decode_neg_context(struct smb_message *smb, + struct TCP_Server_Info *server) { + struct smb2_negotiate_rsp *rsp =3D smb->response; struct smb2_neg_context *pctx; + unsigned int len_of_smb =3D smb->response_len; unsigned int offset =3D le32_to_cpu(rsp->NegotiateContextOffset); unsigned int ctxt_cnt =3D le16_to_cpu(rsp->NegotiateContextCount); unsigned int len_of_ctxts, i; @@ -1147,23 +1199,26 @@ static int smb311_decode_neg_context(struct smb2_ne= gotiate_rsp *rsp, if (clen > len_of_ctxts) break; =20 - if (pctx->ContextType =3D=3D SMB2_PREAUTH_INTEGRITY_CAPABILITIES) - decode_preauth_context( - (struct smb2_preauth_neg_context *)pctx); - else if (pctx->ContextType =3D=3D SMB2_ENCRYPTION_CAPABILITIES) - rc =3D decode_encrypt_ctx(server, - (struct smb2_encryption_neg_context *)pctx); - else if (pctx->ContextType =3D=3D SMB2_COMPRESSION_CAPABILITIES) - decode_compress_ctx(server, - (struct smb2_compression_capabilities_context *)pctx); - else if (pctx->ContextType =3D=3D SMB2_POSIX_EXTENSIONS_AVAILABLE) + switch (pctx->ContextType) { + case SMB2_PREAUTH_INTEGRITY_CAPABILITIES: + decode_preauth_context(pctx); + break; + case SMB2_ENCRYPTION_CAPABILITIES: + rc =3D decode_encrypt_ctx(server, pctx); + break; + case SMB2_COMPRESSION_CAPABILITIES: + decode_compress_ctx(server, pctx); + break; + case SMB2_POSIX_EXTENSIONS_AVAILABLE: server->posix_ext_supported =3D true; - else if (pctx->ContextType =3D=3D SMB2_SIGNING_CAPABILITIES) - decode_signing_ctx(server, - (struct smb2_signing_capabilities *)pctx); - else + break; + case SMB2_SIGNING_CAPABILITIES: + decode_signing_ctx(server, pctx); + break; + default: cifs_server_dbg(VFS, "unknown negcontext of type %d ignored\n", le16_to_cpu(pctx->ContextType)); + } if (rc) break; =20 @@ -1248,17 +1303,16 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses, struct TCP_Server_Info *server) { - struct smb_rqst rqst; struct smb2_negotiate_req *req; struct smb2_negotiate_rsp *rsp; - struct kvec iov[1]; - struct kvec rsp_iov; + struct smb_message *smb; + const char *vs; + size_t offset, num_dialects; int rc; - int resp_buftype; int blob_offset, blob_length; char *security_blob; int flags =3D CIFS_NEG_OP; - unsigned int total_len; + enum { DEF, ANY3, SPEC } version; =20 cifs_dbg(FYI, "Negotiate protocol\n"); =20 @@ -1267,36 +1321,67 @@ SMB2_negotiate(const unsigned int xid, return -EIO; } =20 - rc =3D smb2_plain_req_init(SMB2_NEGOTIATE, NULL, server, - (void **) &req, &total_len); + rc =3D smb2_reconnect(SMB2_SESSION_SETUP, NULL, server, false); if (rc) return rc; =20 + /* Calculate how much space we need for a Negotiate Request message. + * We can't do this exactly as the hostname might change, but we don't + * want to hold the lock across the allocation. + */ + vs =3D server->vals->version_string; + if (strcmp(vs, SMB3ANY_VERSION_STRING) =3D=3D 0) { + version =3D ANY3; + num_dialects =3D 3; + } else if (strcmp(vs, SMBDEFAULT_VERSION_STRING) =3D=3D 0) { + version =3D DEF; + num_dialects =3D 4; + } else { + version =3D SPEC; + num_dialects =3D 1; + } + + offset =3D sizeof(struct smb2_negotiate_req); + offset +=3D sizeof(req->Dialects[0]) * num_dialects; + + if ((server->vals->protocol_id =3D=3D SMB311_PROT_ID) || + (version =3D=3D ANY3) || + (version =3D=3D DEF)) + offset =3D smb2_size_neg_contexts(server, offset); + + smb =3D smb2_create_request(SMB2_NEGOTIATE, server, NULL, + sizeof(*req), offset, 0, + SMB2_REQ_HEAD); + if (!smb) + return -ENOMEM; + + /* Fill in the message. */ + req =3D smb->request; req->hdr.SessionId =3D 0; + req->NegotiateContextOffset =3D cpu_to_be32(smb->ext_offset); =20 memset(server->preauth_sha_hash, 0, SMB2_PREAUTH_HASH_SIZE); memset(ses->preauth_sha_hash, 0, SMB2_PREAUTH_HASH_SIZE); =20 - if (strcmp(server->vals->version_string, - SMB3ANY_VERSION_STRING) =3D=3D 0) { + switch (version) { + case ANY3: req->Dialects[0] =3D cpu_to_le16(SMB30_PROT_ID); req->Dialects[1] =3D cpu_to_le16(SMB302_PROT_ID); req->Dialects[2] =3D cpu_to_le16(SMB311_PROT_ID); req->DialectCount =3D cpu_to_le16(3); - total_len +=3D 6; - } else if (strcmp(server->vals->version_string, - SMBDEFAULT_VERSION_STRING) =3D=3D 0) { + break; + case DEF: req->Dialects[0] =3D cpu_to_le16(SMB21_PROT_ID); req->Dialects[1] =3D cpu_to_le16(SMB30_PROT_ID); req->Dialects[2] =3D cpu_to_le16(SMB302_PROT_ID); req->Dialects[3] =3D cpu_to_le16(SMB311_PROT_ID); req->DialectCount =3D cpu_to_le16(4); - total_len +=3D 8; - } else { + break; + case SPEC: /* otherwise send specific dialect */ req->Dialects[0] =3D cpu_to_le16(server->vals->protocol_id); req->DialectCount =3D cpu_to_le16(1); - total_len +=3D 2; + break; } =20 /* only one of SMB2 signing flags may be set in SMB2 request */ @@ -1312,97 +1397,108 @@ SMB2_negotiate(const unsigned int xid, req->Capabilities |=3D cpu_to_le32(SMB2_GLOBAL_CAP_MULTI_CHANNEL); =20 /* ClientGUID must be zero for SMB2.02 dialect */ - if (server->vals->protocol_id =3D=3D SMB20_PROT_ID) + if (server->vals->protocol_id =3D=3D SMB20_PROT_ID) { memset(req->ClientGUID, 0, SMB2_CLIENT_GUID_SIZE); - else { + } else { memcpy(req->ClientGUID, server->client_guid, SMB2_CLIENT_GUID_SIZE); if ((server->vals->protocol_id =3D=3D SMB311_PROT_ID) || - (strcmp(server->vals->version_string, - SMB3ANY_VERSION_STRING) =3D=3D 0) || - (strcmp(server->vals->version_string, - SMBDEFAULT_VERSION_STRING) =3D=3D 0)) - assemble_neg_contexts(req, server, &total_len); + (version =3D=3D ANY3) || + (version =3D=3D DEF)) + assemble_neg_contexts(smb, server); } - iov[0].iov_base =3D (char *)req; - iov[0].iov_len =3D total_len; =20 - memset(&rqst, 0, sizeof(struct smb_rqst)); - rqst.rq_iov =3D iov; - rqst.rq_nvec =3D 1; + rc =3D smb_send_recv_messages(xid, ses, server, smb, flags); + smb_clear_request(smb); =20 - rc =3D cifs_send_recv(xid, ses, server, - &rqst, &resp_buftype, flags, &rsp_iov); - cifs_small_buf_release(req); - rsp =3D (struct smb2_negotiate_rsp *)rsp_iov.iov_base; /* * No tcon so can't do * cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]); */ - if (rc =3D=3D -EOPNOTSUPP) { - cifs_server_dbg(VFS, "Dialect not supported by server. Consider specify= ing vers=3D1.0 or vers=3D2.0 on mount for accessing older servers\n"); - goto neg_exit; - } else if (rc !=3D 0) + if (rc !=3D 0) { + if (rc =3D=3D -EOPNOTSUPP) + cifs_server_dbg(VFS, "Dialect not supported by server. Consider specif= ying vers=3D1.0 or vers=3D2.0 on mount for accessing older servers\n"); goto neg_exit; + } =20 + /* ________________________________________ + * Decode the response. + */ + rsp =3D (struct smb2_negotiate_rsp *)smb->response; + + int dialect_revision =3D le16_to_cpu(rsp->DialectRevision); rc =3D -EIO; - if (strcmp(server->vals->version_string, - SMB3ANY_VERSION_STRING) =3D=3D 0) { - if (rsp->DialectRevision =3D=3D cpu_to_le16(SMB20_PROT_ID)) { + switch (version) { + case ANY3: + switch (dialect_revision) { + case SMB20_PROT_ID: cifs_server_dbg(VFS, "SMB2 dialect returned but not requested\n"); goto neg_exit; - } else if (rsp->DialectRevision =3D=3D cpu_to_le16(SMB21_PROT_ID)) { + case SMB21_PROT_ID: cifs_server_dbg(VFS, "SMB2.1 dialect returned but not requested\n"); goto neg_exit; - } else if (rsp->DialectRevision =3D=3D cpu_to_le16(SMB311_PROT_ID)) { + case SMB311_PROT_ID: /* ops set to 3.0 by default for default so update */ server->ops =3D &smb311_operations; server->vals =3D &smb311_values; + break; } - } else if (strcmp(server->vals->version_string, - SMBDEFAULT_VERSION_STRING) =3D=3D 0) { - if (rsp->DialectRevision =3D=3D cpu_to_le16(SMB20_PROT_ID)) { + break; + case DEF: + switch (dialect_revision) { + case SMB20_PROT_ID: cifs_server_dbg(VFS, "SMB2 dialect returned but not requested\n"); goto neg_exit; - } else if (rsp->DialectRevision =3D=3D cpu_to_le16(SMB21_PROT_ID)) { + case SMB21_PROT_ID: /* ops set to 3.0 by default for default so update */ server->ops =3D &smb21_operations; server->vals =3D &smb21_values; - } else if (rsp->DialectRevision =3D=3D cpu_to_le16(SMB311_PROT_ID)) { + break; + case SMB311_PROT_ID: server->ops =3D &smb311_operations; server->vals =3D &smb311_values; + break; } - } else if (le16_to_cpu(rsp->DialectRevision) !=3D - server->vals->protocol_id) { - /* if requested single dialect ensure returned dialect matched */ - cifs_server_dbg(VFS, "Invalid 0x%x dialect returned: not requested\n", - le16_to_cpu(rsp->DialectRevision)); - goto neg_exit; + break; + default: + if (dialect_revision !=3D server->vals->protocol_id) { + /* if requested single dialect ensure returned dialect matched */ + cifs_server_dbg(VFS, "Invalid 0x%x dialect returned: not requested\n", + dialect_revision); + goto neg_exit; + } + break; } =20 cifs_dbg(FYI, "mode 0x%x\n", rsp->SecurityMode); =20 - if (rsp->DialectRevision =3D=3D cpu_to_le16(SMB20_PROT_ID)) + switch (dialect_revision) { + case SMB20_PROT_ID: cifs_dbg(FYI, "negotiated smb2.0 dialect\n"); - else if (rsp->DialectRevision =3D=3D cpu_to_le16(SMB21_PROT_ID)) + break; + case SMB21_PROT_ID: cifs_dbg(FYI, "negotiated smb2.1 dialect\n"); - else if (rsp->DialectRevision =3D=3D cpu_to_le16(SMB30_PROT_ID)) + break; + case SMB30_PROT_ID: cifs_dbg(FYI, "negotiated smb3.0 dialect\n"); - else if (rsp->DialectRevision =3D=3D cpu_to_le16(SMB302_PROT_ID)) + break; + case SMB302_PROT_ID: cifs_dbg(FYI, "negotiated smb3.02 dialect\n"); - else if (rsp->DialectRevision =3D=3D cpu_to_le16(SMB311_PROT_ID)) + break; + case SMB311_PROT_ID: cifs_dbg(FYI, "negotiated smb3.1.1 dialect\n"); - else { + break; + default: cifs_server_dbg(VFS, "Invalid dialect returned by server 0x%x\n", - le16_to_cpu(rsp->DialectRevision)); + dialect_revision); goto neg_exit; } =20 rc =3D 0; - server->dialect =3D le16_to_cpu(rsp->DialectRevision); + server->dialect =3D dialect_revision; =20 /* * Keep a copy of the hash after negprot. This hash will be @@ -1461,10 +1557,9 @@ SMB2_negotiate(const unsigned int xid, rc =3D -EIO; } =20 - if (rsp->DialectRevision =3D=3D cpu_to_le16(SMB311_PROT_ID)) { + if (server->dialect =3D=3D SMB311_PROT_ID) { if (rsp->NegotiateContextCount) - rc =3D smb311_decode_neg_context(rsp, server, - rsp_iov.iov_len); + rc =3D smb311_decode_neg_context(smb, server); else cifs_server_dbg(VFS, "Missing expected negotiate contexts\n"); } @@ -1472,7 +1567,7 @@ SMB2_negotiate(const unsigned int xid, if (server->cipher_type && !rc) rc =3D smb3_crypto_aead_allocate(server); neg_exit: - free_rsp_buf(resp_buftype, rsp); + smb_put_messages(smb); return rc; } =20 diff --git a/fs/smb/common/smb2pdu.h b/fs/smb/common/smb2pdu.h index 7da40d229ab5..e3b888140b59 100644 --- a/fs/smb/common/smb2pdu.h +++ b/fs/smb/common/smb2pdu.h @@ -455,9 +455,7 @@ struct smb2_neg_context { #define MIN_PREAUTH_CTXT_DATA_LEN 6 =20 struct smb2_preauth_neg_context { - __le16 ContextType; /* 1 */ - __le16 DataLength; - __le32 Reserved; + struct smb2_neg_context neg; __le16 HashAlgorithmCount; /* 1 */ __le16 SaltLength; __le16 HashAlgorithms; /* HashAlgorithms[0] since only one defined */ @@ -473,9 +471,7 @@ struct smb2_preauth_neg_context { /* Min encrypt context data is one cipher so 2 bytes + 2 byte count field = */ #define MIN_ENCRYPT_CTXT_DATA_LEN 4 struct smb2_encryption_neg_context { - __le16 ContextType; /* 2 */ - __le16 DataLength; - __le32 Reserved; + struct smb2_neg_context neg; /* CipherCount usually 2, but can be 3 when AES256-GCM enabled */ __le16 CipherCount; /* AES128-GCM and AES128-CCM by default */ __le16 Ciphers[]; @@ -495,9 +491,7 @@ struct smb2_encryption_neg_context { #define SMB2_COMPRESSION_CAPABILITIES_FLAG_CHAINED cpu_to_le32(0x00000001) =20 struct smb2_compression_capabilities_context { - __le16 ContextType; /* 3 */ - __le16 DataLength; - __le32 Reserved; + struct smb2_neg_context neg; __le16 CompressionAlgorithmCount; __le16 Padding; __le32 Flags; @@ -511,9 +505,7 @@ struct smb2_compression_capabilities_context { * Its struct simply contains NetName, an array of Unicode characters */ struct smb2_netname_neg_context { - __le16 ContextType; /* 5 */ - __le16 DataLength; - __le32 Reserved; + struct smb2_neg_context neg; __le16 NetName[]; /* hostname of target converted to UCS-2 */ } __packed; =20 @@ -567,9 +559,7 @@ struct smb2_rdma_transform_capabilities_context { #define SIGNING_ALG_AES_GMAC_LE cpu_to_le16(2) =20 struct smb2_signing_capabilities { - __le16 ContextType; /* 8 */ - __le16 DataLength; - __le32 Reserved; + struct smb2_neg_context neg; __le16 SigningAlgorithmCount; __le16 SigningAlgorithms[]; /* Followed by padding to 8 byte boundary (required by some servers) */ @@ -577,9 +567,7 @@ struct smb2_signing_capabilities { =20 #define POSIX_CTXT_DATA_LEN 16 struct smb2_posix_neg_context { - __le16 ContextType; /* 0x100 */ - __le16 DataLength; - __le32 Reserved; + struct smb2_neg_context neg; __u8 Name[16]; /* POSIX ctxt GUID 93AD25509CB411E7B42383DE968BCD7C */ } __packed; =20 diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c index 1ed2bcba649f..af5187d1101e 100644 --- a/fs/smb/server/smb2pdu.c +++ b/fs/smb/server/smb2pdu.c @@ -774,10 +774,10 @@ static int smb2_get_dos_mode(struct kstat *stat, int = attribute) static void build_preauth_ctxt(struct smb2_preauth_neg_context *pneg_ctxt, __le16 hash_id) { - pneg_ctxt->ContextType =3D SMB2_PREAUTH_INTEGRITY_CAPABILITIES; - pneg_ctxt->DataLength =3D cpu_to_le16(38); + pneg_ctxt->neg.ContextType =3D SMB2_PREAUTH_INTEGRITY_CAPABILITIES; + pneg_ctxt->neg.DataLength =3D cpu_to_le16(38); + pneg_ctxt->neg.Reserved =3D cpu_to_le32(0); pneg_ctxt->HashAlgorithmCount =3D cpu_to_le16(1); - pneg_ctxt->Reserved =3D cpu_to_le32(0); pneg_ctxt->SaltLength =3D cpu_to_le16(SMB311_SALT_SIZE); get_random_bytes(pneg_ctxt->Salt, SMB311_SALT_SIZE); pneg_ctxt->HashAlgorithms =3D hash_id; @@ -786,9 +786,9 @@ static void build_preauth_ctxt(struct smb2_preauth_neg_= context *pneg_ctxt, static void build_encrypt_ctxt(struct smb2_encryption_neg_context *pneg_ct= xt, __le16 cipher_type) { - pneg_ctxt->ContextType =3D SMB2_ENCRYPTION_CAPABILITIES; - pneg_ctxt->DataLength =3D cpu_to_le16(4); - pneg_ctxt->Reserved =3D cpu_to_le32(0); + pneg_ctxt->neg.ContextType =3D SMB2_ENCRYPTION_CAPABILITIES; + pneg_ctxt->neg.DataLength =3D cpu_to_le16(4); + pneg_ctxt->neg.Reserved =3D cpu_to_le32(0); pneg_ctxt->CipherCount =3D cpu_to_le16(1); pneg_ctxt->Ciphers[0] =3D cipher_type; } @@ -796,19 +796,19 @@ static void build_encrypt_ctxt(struct smb2_encryption= _neg_context *pneg_ctxt, static void build_sign_cap_ctxt(struct smb2_signing_capabilities *pneg_ctx= t, __le16 sign_algo) { - pneg_ctxt->ContextType =3D SMB2_SIGNING_CAPABILITIES; - pneg_ctxt->DataLength =3D + pneg_ctxt->neg.ContextType =3D SMB2_SIGNING_CAPABILITIES; + pneg_ctxt->neg.DataLength =3D cpu_to_le16((sizeof(struct smb2_signing_capabilities) + 2) - sizeof(struct smb2_neg_context)); - pneg_ctxt->Reserved =3D cpu_to_le32(0); + pneg_ctxt->neg.Reserved =3D cpu_to_le32(0); pneg_ctxt->SigningAlgorithmCount =3D cpu_to_le16(1); pneg_ctxt->SigningAlgorithms[0] =3D sign_algo; } =20 static void build_posix_ctxt(struct smb2_posix_neg_context *pneg_ctxt) { - pneg_ctxt->ContextType =3D SMB2_POSIX_EXTENSIONS_AVAILABLE; - pneg_ctxt->DataLength =3D cpu_to_le16(POSIX_CTXT_DATA_LEN); + pneg_ctxt->neg.ContextType =3D SMB2_POSIX_EXTENSIONS_AVAILABLE; + pneg_ctxt->neg.DataLength =3D cpu_to_le16(POSIX_CTXT_DATA_LEN); /* SMB2_CREATE_TAG_POSIX is "0x93AD25509CB411E7B42383DE968BCD7C" */ pneg_ctxt->Name[0] =3D 0x93; pneg_ctxt->Name[1] =3D 0xAD; From nobody Thu Dec 18 03:20:29 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8DE432D375A for ; Wed, 6 Aug 2025 20:39:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512766; cv=none; b=P/3D6nLI93Br3QwyVGCQ2DSOWYp+ocI9SgS16dhKEOvMKrOXasxMtgVhZn6gZgD3gpVLgdMNMPl4IL2CbMiJSZ2WYgiYdM4a0wn0tr14xYSmJz8R49hCFjDuWugQBoEb3NYykdoEmws/j1PvPX+t2SCMQDkL/C3/g5SF1bAsaE8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512766; c=relaxed/simple; bh=FgZs7FlbxxcfYWLEAv9uHBpudQGIcMZzepwa8tZo2os=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=tYeBdoDG8l7SGm6WInGgmkOvg6Tg6ql5/9csTr/UEazf+YH25CKPHiMglCIOeRrbN0cI0xyrS4dkox9dv64F16wSYbSwx/Yp0pkODE8UmBbF9OaY5MNnO5PlLWkkXDKHy/7zz5cB9bVzsiYJAqV1+SnhiwqzLs1jln1tO6M1kL0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=DyUJm5er; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="DyUJm5er" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1754512762; h=from:from:reply-to:subject:subject: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=7Y38Kg6xeMPfdlB6BUDECDD4woV1aeL7i1JxW9bLzAY=; b=DyUJm5erNL8zY8rSyOffUuM8Md2D9jtEohjaUjPq7JhePAHkVbV5iTNxe9SDidXZas/IWx /NlwBaSARp1++5dLqaWkCzQcC19STRm14G2VipF1Wx3KNTLTIBi2bqkFVikuGz94dJOCf3 pIexnNW0n8WbADdfIY6OBl4/XaYBx9Q= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-116-1-WtZdDROiK-vqhqVrthnw-1; Wed, 06 Aug 2025 16:39:17 -0400 X-MC-Unique: 1-WtZdDROiK-vqhqVrthnw-1 X-Mimecast-MFC-AGG-ID: 1-WtZdDROiK-vqhqVrthnw_1754512755 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id AAF0D1800561; Wed, 6 Aug 2025 20:39:15 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.17]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 634881800280; Wed, 6 Aug 2025 20:39:12 +0000 (UTC) From: David Howells To: Steve French Cc: David Howells , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Wang Zhaolong , Stefan Metzmacher , Mina Almasry , linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org, netfs@lists.linux.dev, linux-fsdevel@vger.kernel.org Subject: [RFC PATCH 25/31] cifs: Convert SMB2 Session Setup request Date: Wed, 6 Aug 2025 21:36:46 +0100 Message-ID: <20250806203705.2560493-26-dhowells@redhat.com> In-Reply-To: <20250806203705.2560493-1-dhowells@redhat.com> References: <20250806203705.2560493-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Howells cc: Steve French cc: Paulo Alcantara cc: Shyam Prasad N cc: Tom Talpey cc: linux-cifs@vger.kernel.org cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/smb/client/ntlmssp.h | 20 +-- fs/smb/client/sess.c | 271 ++++++++++++++++++++++------------------ fs/smb/client/smb2pdu.c | 172 ++++++++++--------------- 3 files changed, 226 insertions(+), 237 deletions(-) diff --git a/fs/smb/client/ntlmssp.h b/fs/smb/client/ntlmssp.h index 875de43b72de..5ca249f1c51c 100644 --- a/fs/smb/client/ntlmssp.h +++ b/fs/smb/client/ntlmssp.h @@ -123,7 +123,7 @@ typedef struct _CHALLENGE_MESSAGE { do not set the version is present flag */ } __attribute__((packed)) CHALLENGE_MESSAGE, *PCHALLENGE_MESSAGE; =20 -typedef struct _AUTHENTICATE_MESSAGE { +struct ntlmssp_authenticate_message { __u8 Signature[sizeof(NTLMSSP_SIGNATURE)]; __le32 MessageType; /* NtLmsAuthenticate =3D 3 */ SECURITY_BUFFER LmChallengeResponse; @@ -136,7 +136,7 @@ typedef struct _AUTHENTICATE_MESSAGE { struct ntlmssp_version Version; /* SECURITY_BUFFER */ char UserString[]; -} __attribute__((packed)) AUTHENTICATE_MESSAGE, *PAUTHENTICATE_MESSAGE; +} __attribute__((packed)); =20 /* * Size of the session key (crypto key encrypted with the password @@ -147,11 +147,11 @@ int build_ntlmssp_negotiate_blob(unsigned char **pbuf= fer, u16 *buflen, struct cifs_ses *ses, struct TCP_Server_Info *server, const struct nls_table *nls_cp); -int build_ntlmssp_smb3_negotiate_blob(unsigned char **pbuffer, u16 *buflen, - struct cifs_ses *ses, - struct TCP_Server_Info *server, - const struct nls_table *nls_cp); -int build_ntlmssp_auth_blob(unsigned char **pbuffer, u16 *buflen, - struct cifs_ses *ses, - struct TCP_Server_Info *server, - const struct nls_table *nls_cp); +int build_ntlmssp_smb3_negotiate_blob(struct smb_message *smb, + struct cifs_ses *ses, + struct TCP_Server_Info *server, + const struct nls_table *nls_cp); +int build_ntlmssp_auth_blob(struct smb_message *smb, + struct cifs_ses *ses, + struct TCP_Server_Info *server, + const struct nls_table *nls_cp); diff --git a/fs/smb/client/sess.c b/fs/smb/client/sess.c index 330bc3d25bad..8063cf06ea9f 100644 --- a/fs/smb/client/sess.c +++ b/fs/smb/client/sess.c @@ -966,32 +966,86 @@ int decode_ntlmssp_challenge(char *bcc_ptr, int blob_= len, return 0; } =20 -static int size_of_ntlmssp_blob(struct cifs_ses *ses, int base_size) +static int size_of_ntlmssp_blob(struct cifs_ses *ses, int base_size, + const struct nls_table *nls_cp) { int sz =3D base_size + ses->auth_key.len - CIFS_SESS_KEY_SIZE + CIFS_CPHTXT_SIZE + 2; =20 if (ses->domainName) - sz +=3D sizeof(__le16) * strnlen(ses->domainName, CIFS_MAX_DOMAINNAME_LE= N); + sz +=3D cifs_size_strtoUTF16(ses->domainName, CIFS_MAX_DOMAINNAME_LEN, + nls_cp); else sz +=3D sizeof(__le16); =20 if (ses->user_name) - sz +=3D sizeof(__le16) * strnlen(ses->user_name, CIFS_MAX_USERNAME_LEN); + sz +=3D cifs_size_strtoUTF16(ses->user_name, CIFS_MAX_USERNAME_LEN, + nls_cp); else sz +=3D sizeof(__le16); =20 if (ses->workstation_name[0]) - sz +=3D sizeof(__le16) * strnlen(ses->workstation_name, - ntlmssp_workstation_name_size(ses)); + sz +=3D cifs_size_strtoUTF16(ses->workstation_name, + ntlmssp_workstation_name_size(ses), + nls_cp); else sz +=3D sizeof(__le16); =20 return sz; } =20 +static void cifs_append_security_string(struct smb_message *smb, + SECURITY_BUFFER *pbuf, + const char *str_value, + int str_length, + unsigned char **pcur, + const struct nls_table *nls_cp) +{ + int len; + + if (!str_value) { + pbuf->BufferOffset =3D cpu_to_le32(smb->offset); + pbuf->Length =3D 0; + pbuf->MaximumLength =3D 0; + *(__le16 *)*pcur =3D 0; + smb->offset +=3D 2; + pcur +=3D 2; + } else { + len =3D cifs_strtoUTF16((__le16 *)*pcur, + str_value, + str_length, + nls_cp); + len *=3D sizeof(__le16); + pbuf->BufferOffset =3D cpu_to_le32(smb->offset); + pbuf->Length =3D cpu_to_le16(len); + pbuf->MaximumLength =3D cpu_to_le16(len); + smb->offset +=3D len; + pcur +=3D len; + } +} + +static void cifs_append_security_blob(struct smb_message *smb, + SECURITY_BUFFER *pbuf, + const void *content, + int len, + unsigned char **pcur) +{ + if (!content) { + pbuf->BufferOffset =3D cpu_to_le32(smb->offset); + pbuf->Length =3D 0; + pbuf->MaximumLength =3D 0; + } else { + memcpy(pcur, content, len); + pbuf->BufferOffset =3D cpu_to_le32(smb->offset); + pbuf->Length =3D cpu_to_le16(len); + pbuf->MaximumLength =3D cpu_to_le16(len); + smb->offset +=3D len; + pcur +=3D len; + } +} + static inline void cifs_security_buffer_from_str(SECURITY_BUFFER *pbuf, - char *str_value, + const char *str_value, int str_length, unsigned char *pstart, unsigned char **pcur, @@ -1038,7 +1092,7 @@ int build_ntlmssp_negotiate_blob(unsigned char **pbuf= fer, unsigned char *tmp; int len; =20 - len =3D size_of_ntlmssp_blob(ses, sizeof(NEGOTIATE_MESSAGE)); + len =3D size_of_ntlmssp_blob(ses, sizeof(NEGOTIATE_MESSAGE), nls_cp); *pbuffer =3D kmalloc(len, GFP_KERNEL); if (!*pbuffer) { rc =3D -ENOMEM; @@ -1088,173 +1142,148 @@ int build_ntlmssp_negotiate_blob(unsigned char **= pbuffer, * supported by modern servers. For safety limit to SMB3 or later * See notes in MS-NLMP Section 2.2.2.1 e.g. */ -int build_ntlmssp_smb3_negotiate_blob(unsigned char **pbuffer, - u16 *buflen, - struct cifs_ses *ses, - struct TCP_Server_Info *server, - const struct nls_table *nls_cp) +int build_ntlmssp_smb3_negotiate_blob(struct smb_message *smb, + struct cifs_ses *ses, + struct TCP_Server_Info *server, + const struct nls_table *nls_cp) { - int rc =3D 0; - struct negotiate_message *sec_blob; - __u32 flags; + struct negotiate_message *neg_msg; unsigned char *tmp; + __u32 flags; + void *blob; int len; + int rc =3D 0; =20 - len =3D size_of_ntlmssp_blob(ses, sizeof(struct negotiate_message)); - *pbuffer =3D kmalloc(len, GFP_KERNEL); - if (!*pbuffer) { + len =3D size_of_ntlmssp_blob(ses, sizeof(*neg_msg), nls_cp); + blob =3D cifs_allocate_tx_buf(server, len); + if (!blob) { rc =3D -ENOMEM; cifs_dbg(VFS, "Error %d during NTLMSSP allocation\n", rc); - *buflen =3D 0; goto setup_ntlm_smb3_neg_ret; } - sec_blob =3D (struct negotiate_message *)*pbuffer; =20 - memset(*pbuffer, 0, sizeof(struct negotiate_message)); - memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8); - sec_blob->MessageType =3D NtLmNegotiate; + smb_add_segment_to_tx_buf(smb, blob, len); + smb->offset =3D sizeof(*neg_msg); =20 /* BB is NTLMV2 session security format easier to use here? */ - flags =3D NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET | - NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | - NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC | - NTLMSSP_NEGOTIATE_ALWAYS_SIGN | NTLMSSP_NEGOTIATE_SEAL | - NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_VERSION; + flags =3D NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET | + NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | + NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC | + NTLMSSP_NEGOTIATE_ALWAYS_SIGN | NTLMSSP_NEGOTIATE_SEAL | + NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_VERSION; if (!server->session_estab || ses->ntlmssp->sesskey_per_smbsess) flags |=3D NTLMSSP_NEGOTIATE_KEY_XCH; =20 - sec_blob->Version.ProductMajorVersion =3D LINUX_VERSION_MAJOR; - sec_blob->Version.ProductMinorVersion =3D LINUX_VERSION_PATCHLEVEL; - sec_blob->Version.ProductBuild =3D cpu_to_le16(SMB3_PRODUCT_BUILD); - sec_blob->Version.NTLMRevisionCurrent =3D NTLMSSP_REVISION_W2K3; + neg_msg =3D (struct negotiate_message *)blob; + *neg_msg =3D (struct negotiate_message){ + .Signature =3D NTLMSSP_SIGNATURE, + .MessageType =3D NtLmNegotiate, + .NegotiateFlags =3D cpu_to_le32(flags), + .Version.ProductMajorVersion =3D LINUX_VERSION_MAJOR, + .Version.ProductMinorVersion =3D LINUX_VERSION_PATCHLEVEL, + .Version.ProductBuild =3D cpu_to_le16(SMB3_PRODUCT_BUILD), + .Version.NTLMRevisionCurrent =3D NTLMSSP_REVISION_W2K3, + }; =20 - tmp =3D *pbuffer + sizeof(struct negotiate_message); ses->ntlmssp->client_flags =3D flags; - sec_blob->NegotiateFlags =3D cpu_to_le32(flags); + tmp =3D blob + sizeof(struct negotiate_message); =20 /* these fields should be null in negotiate phase MS-NLMP 3.1.5.1.1 */ - cifs_security_buffer_from_str(&sec_blob->DomainName, - NULL, - CIFS_MAX_DOMAINNAME_LEN, - *pbuffer, &tmp, - nls_cp); + cifs_append_security_string(smb, &neg_msg->DomainName, + NULL, CIFS_MAX_DOMAINNAME_LEN, + &tmp, nls_cp); =20 - cifs_security_buffer_from_str(&sec_blob->WorkstationName, - NULL, - CIFS_MAX_WORKSTATION_LEN, - *pbuffer, &tmp, - nls_cp); - - *buflen =3D tmp - *pbuffer; + cifs_append_security_string(smb, &neg_msg->WorkstationName, + NULL, CIFS_MAX_WORKSTATION_LEN, + &tmp, nls_cp); setup_ntlm_smb3_neg_ret: return rc; } =20 =20 /* See MS-NLMP 2.2.1.3 */ -int build_ntlmssp_auth_blob(unsigned char **pbuffer, - u16 *buflen, - struct cifs_ses *ses, - struct TCP_Server_Info *server, - const struct nls_table *nls_cp) +int build_ntlmssp_auth_blob(struct smb_message *smb, + struct cifs_ses *ses, + struct TCP_Server_Info *server, + const struct nls_table *nls_cp) { - int rc; - AUTHENTICATE_MESSAGE *sec_blob; - __u32 flags; + struct ntlmssp_authenticate_message *auth_msg; unsigned char *tmp; + __u32 flags; + void *blob; int len; + int rc; =20 rc =3D setup_ntlmv2_rsp(ses, nls_cp); if (rc) { cifs_dbg(VFS, "Error %d during NTLMSSP authentication\n", rc); - *buflen =3D 0; goto setup_ntlmv2_ret; } =20 - len =3D size_of_ntlmssp_blob(ses, sizeof(AUTHENTICATE_MESSAGE)); - *pbuffer =3D kmalloc(len, GFP_KERNEL); - if (!*pbuffer) { + len =3D size_of_ntlmssp_blob(ses, sizeof(*auth_msg), nls_cp); + blob =3D cifs_allocate_tx_buf(server, len); + if (!blob) { rc =3D -ENOMEM; cifs_dbg(VFS, "Error %d during NTLMSSP allocation\n", rc); - *buflen =3D 0; goto setup_ntlmv2_ret; } - sec_blob =3D (AUTHENTICATE_MESSAGE *)*pbuffer; =20 - memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8); - sec_blob->MessageType =3D NtLmAuthenticate; + smb_add_segment_to_tx_buf(smb, blob, len); + smb->offset =3D sizeof(*auth_msg); =20 /* send version information in ntlmssp authenticate also */ - flags =3D ses->ntlmssp->server_flags | NTLMSSP_REQUEST_TARGET | - NTLMSSP_NEGOTIATE_TARGET_INFO | NTLMSSP_NEGOTIATE_VERSION | + flags =3D ses->ntlmssp->server_flags | NTLMSSP_REQUEST_TARGET | + NTLMSSP_NEGOTIATE_TARGET_INFO | NTLMSSP_NEGOTIATE_VERSION | NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED; =20 - sec_blob->Version.ProductMajorVersion =3D LINUX_VERSION_MAJOR; - sec_blob->Version.ProductMinorVersion =3D LINUX_VERSION_PATCHLEVEL; - sec_blob->Version.ProductBuild =3D cpu_to_le16(SMB3_PRODUCT_BUILD); - sec_blob->Version.NTLMRevisionCurrent =3D NTLMSSP_REVISION_W2K3; + auth_msg =3D blob; + *auth_msg =3D (struct ntlmssp_authenticate_message){ + .Signature =3D NTLMSSP_SIGNATURE, + .MessageType =3D NtLmAuthenticate, + .NegotiateFlags =3D cpu_to_le32(flags), + .Version.ProductMajorVersion =3D LINUX_VERSION_MAJOR, + .Version.ProductMinorVersion =3D LINUX_VERSION_PATCHLEVEL, + .Version.ProductBuild =3D cpu_to_le16(SMB3_PRODUCT_BUILD), + .Version.NTLMRevisionCurrent =3D NTLMSSP_REVISION_W2K3, + }; =20 - tmp =3D *pbuffer + sizeof(AUTHENTICATE_MESSAGE); - sec_blob->NegotiateFlags =3D cpu_to_le32(flags); + tmp =3D blob + sizeof(*auth_msg); =20 - sec_blob->LmChallengeResponse.BufferOffset =3D - cpu_to_le32(sizeof(AUTHENTICATE_MESSAGE)); - sec_blob->LmChallengeResponse.Length =3D 0; - sec_blob->LmChallengeResponse.MaximumLength =3D 0; + cifs_append_security_blob(smb, &auth_msg->LmChallengeResponse, + NULL, 0, &tmp); =20 - sec_blob->NtChallengeResponse.BufferOffset =3D - cpu_to_le32(tmp - *pbuffer); - if (ses->user_name !=3D NULL) { - memcpy(tmp, ses->auth_key.response + CIFS_SESS_KEY_SIZE, - ses->auth_key.len - CIFS_SESS_KEY_SIZE); - tmp +=3D ses->auth_key.len - CIFS_SESS_KEY_SIZE; + /* Only send an NT Response for anonymous access */ + if (ses->user_name) + cifs_append_security_blob(smb, &auth_msg->NtChallengeResponse, + ses->auth_key.response + CIFS_SESS_KEY_SIZE, + ses->auth_key.len - CIFS_SESS_KEY_SIZE, + &tmp); + else + cifs_append_security_blob(smb, &auth_msg->NtChallengeResponse, + NULL, 0, &tmp); =20 - sec_blob->NtChallengeResponse.Length =3D - cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE); - sec_blob->NtChallengeResponse.MaximumLength =3D - cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE); - } else { - /* - * don't send an NT Response for anonymous access - */ - sec_blob->NtChallengeResponse.Length =3D 0; - sec_blob->NtChallengeResponse.MaximumLength =3D 0; - } + cifs_append_security_string(smb, &auth_msg->DomainName, + ses->domainName, CIFS_MAX_DOMAINNAME_LEN, + &tmp, nls_cp); =20 - cifs_security_buffer_from_str(&sec_blob->DomainName, - ses->domainName, - CIFS_MAX_DOMAINNAME_LEN, - *pbuffer, &tmp, - nls_cp); + cifs_append_security_string(smb, &auth_msg->UserName, + ses->user_name, CIFS_MAX_USERNAME_LEN, + &tmp, nls_cp); =20 - cifs_security_buffer_from_str(&sec_blob->UserName, - ses->user_name, - CIFS_MAX_USERNAME_LEN, - *pbuffer, &tmp, - nls_cp); - - cifs_security_buffer_from_str(&sec_blob->WorkstationName, - ses->workstation_name, - ntlmssp_workstation_name_size(ses), - *pbuffer, &tmp, - nls_cp); + cifs_append_security_string(smb, &auth_msg->WorkstationName, + ses->workstation_name, + ntlmssp_workstation_name_size(ses), + &tmp, nls_cp); =20 if ((ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_KEY_XCH) && (!ses->server->session_estab || ses->ntlmssp->sesskey_per_smbsess) && - !calc_seckey(ses)) { - memcpy(tmp, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE); - sec_blob->SessionKey.BufferOffset =3D cpu_to_le32(tmp - *pbuffer); - sec_blob->SessionKey.Length =3D cpu_to_le16(CIFS_CPHTXT_SIZE); - sec_blob->SessionKey.MaximumLength =3D - cpu_to_le16(CIFS_CPHTXT_SIZE); - tmp +=3D CIFS_CPHTXT_SIZE; - } else { - sec_blob->SessionKey.BufferOffset =3D cpu_to_le32(tmp - *pbuffer); - sec_blob->SessionKey.Length =3D 0; - sec_blob->SessionKey.MaximumLength =3D 0; - } - - *buflen =3D tmp - *pbuffer; + !calc_seckey(ses)) + cifs_append_security_blob(smb, &auth_msg->SessionKey, + ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE, + &tmp); + else + cifs_append_security_blob(smb, &auth_msg->SessionKey, + NULL, 0, &tmp); setup_ntlmv2_ret: return rc; } diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c index f1b6d36fe7cd..685af9c0cdcb 100644 --- a/fs/smb/client/smb2pdu.c +++ b/fs/smb/client/smb2pdu.c @@ -1740,33 +1740,29 @@ struct SMB2_sess_data { void (*func)(struct SMB2_sess_data *); int result; u64 previous_session; - - /* we will send the SMB in three pieces: - * a fixed length beginning part, an optional - * SPNEGO blob (which can be zero length), and a - * last part which will include the strings - * and rest of bcc area. This allows us to avoid - * a large buffer 17K allocation - */ - int buf0_type; - struct kvec iov[2]; }; =20 -static int -SMB2_sess_alloc_buffer(struct SMB2_sess_data *sess_data) +static struct smb_message * +SMB2_create_session_request(struct SMB2_sess_data *sess_data) { - int rc; + struct smb_message *smb; struct cifs_ses *ses =3D sess_data->ses; struct TCP_Server_Info *server =3D sess_data->server; struct smb2_sess_setup_req *req; - unsigned int total_len; bool is_binding =3D false; =20 - rc =3D smb2_plain_req_init(SMB2_SESSION_SETUP, NULL, server, - (void **) &req, - &total_len); - if (rc) - return rc; + /* We will send the SMB in three pieces: + * - a fixed length beginning part, + * - an optional SPNEGO blob (which can be zero length), and + * - a last part which will include the strings and rest of bcc area. + * This allows us to avoid a large buffer 17K allocation + */ + smb =3D smb2_create_request(SMB2_SESSION_SETUP, server, NULL, + sizeof(*req), sizeof(*req), 0, + SMB2_REQ_DYNAMIC | + SMB2_REQ_SENSITIVE); + if (!smb) + return NULL; =20 spin_lock(&ses->ses_lock); is_binding =3D (ses->ses_status =3D=3D SES_GOOD); @@ -1815,55 +1811,25 @@ SMB2_sess_alloc_buffer(struct SMB2_sess_data *sess_= data) =20 req->Channel =3D 0; /* MBZ */ =20 - sess_data->iov[0].iov_base =3D (char *)req; - /* 1 for pad */ - sess_data->iov[0].iov_len =3D total_len - 1; - /* - * This variable will be used to clear the buffer - * allocated above in case of any error in the calling function. - */ - sess_data->buf0_type =3D CIFS_SMALL_BUFFER; - - return 0; -} - -static void -SMB2_sess_free_buffer(struct SMB2_sess_data *sess_data) -{ - struct kvec *iov =3D sess_data->iov; - - /* iov[1] is already freed by caller */ - if (sess_data->buf0_type !=3D CIFS_NO_BUFFER && iov[0].iov_base) - memzero_explicit(iov[0].iov_base, iov[0].iov_len); - - free_rsp_buf(sess_data->buf0_type, iov[0].iov_base); - sess_data->buf0_type =3D CIFS_NO_BUFFER; + /* Testing shows that buffer offset must be at location of Buffer[0] */ + req->SecurityBufferOffset =3D cpu_to_le16(sizeof(*req)); + req->SecurityBufferLength =3D 0; + return smb; } =20 static int -SMB2_sess_sendreceive(struct SMB2_sess_data *sess_data) +SMB2_sess_sendreceive(struct SMB2_sess_data *sess_data, + struct smb_message *smb) { int rc; - struct smb_rqst rqst; - struct smb2_sess_setup_req *req =3D sess_data->iov[0].iov_base; - struct kvec rsp_iov =3D { NULL, 0 }; + struct smb2_sess_setup_req *req =3D smb->request; =20 - /* Testing shows that buffer offset must be at location of Buffer[0] */ - req->SecurityBufferOffset =3D - cpu_to_le16(sizeof(struct smb2_sess_setup_req)); - req->SecurityBufferLength =3D cpu_to_le16(sess_data->iov[1].iov_len); - - memset(&rqst, 0, sizeof(struct smb_rqst)); - rqst.rq_iov =3D sess_data->iov; - rqst.rq_nvec =3D 2; + req->SecurityBufferLength =3D cpu_to_le16(smb->total_len - sizeof(*req)); =20 /* BB add code to build os and lm fields */ - rc =3D cifs_send_recv(sess_data->xid, sess_data->ses, - sess_data->server, - &rqst, - &sess_data->buf0_type, - CIFS_LOG_ERROR | CIFS_SESS_OP, &rsp_iov); - cifs_small_buf_release(sess_data->iov[0].iov_base); + rc =3D smb_send_recv_messages(sess_data->xid, sess_data->ses, sess_data->= server, + smb, CIFS_LOG_ERROR | CIFS_SESS_OP); + smb_clear_request(smb); if (rc =3D=3D 0) sess_data->ses->expired_pwd =3D false; else if ((rc =3D=3D -EACCES) || (rc =3D=3D -EKEYEXPIRED) || (rc =3D=3D -E= KEYREVOKED)) { @@ -1875,8 +1841,6 @@ SMB2_sess_sendreceive(struct SMB2_sess_data *sess_dat= a) sess_data->ses->expired_pwd =3D true; } =20 - memcpy(&sess_data->iov[0], &rsp_iov, sizeof(struct kvec)); - return rc; } =20 @@ -1911,16 +1875,18 @@ SMB2_sess_establish_session(struct SMB2_sess_data *= sess_data) static void SMB2_auth_kerberos(struct SMB2_sess_data *sess_data) { - int rc; - struct cifs_ses *ses =3D sess_data->ses; + struct smb2_sess_setup_rsp *rsp =3D NULL; struct TCP_Server_Info *server =3D sess_data->server; struct cifs_spnego_msg *msg; + struct smb_message *smb =3D NULL; + struct cifs_ses *ses =3D sess_data->ses; struct key *spnego_key =3D NULL; - struct smb2_sess_setup_rsp *rsp =3D NULL; + void *key_buf =3D NULL; bool is_binding =3D false; + int rc =3D -ENOMEM; =20 - rc =3D SMB2_sess_alloc_buffer(sess_data); - if (rc) + smb =3D SMB2_create_session_request(sess_data); + if (!smb) goto out; =20 spnego_key =3D cifs_get_spnego_key(ses, server); @@ -1962,14 +1928,21 @@ SMB2_auth_kerberos(struct SMB2_sess_data *sess_data) ses->auth_key.len =3D msg->sesskey_len; } =20 - sess_data->iov[1].iov_base =3D msg->data + msg->sesskey_len; - sess_data->iov[1].iov_len =3D msg->secblob_len; + /* Copy the key data here so that we can pass it to MSG_SPLICE_PAGES + * and the need to copy the whole message. + */ + key_buf =3D cifs_allocate_tx_buf(server, msg->secblob_len); + if (!key_buf) + goto out; + + memcpy(key_buf, msg->data + msg->sesskey_len, msg->secblob_len); + smb_add_segment_to_tx_buf(smb, key_buf, msg->secblob_len); =20 - rc =3D SMB2_sess_sendreceive(sess_data); + rc =3D SMB2_sess_sendreceive(sess_data, smb); if (rc) goto out_put_spnego_key; =20 - rsp =3D (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base; + rsp =3D (struct smb2_sess_setup_rsp *)smb->response; /* keep session id and flags if binding */ if (!is_binding) { ses->Suid =3D le64_to_cpu(rsp->hdr.SessionId); @@ -1985,10 +1958,11 @@ SMB2_auth_kerberos(struct SMB2_sess_data *sess_data) ses->auth_key.response =3D NULL; ses->auth_key.len =3D 0; } + out: + smb_put_messages(smb); sess_data->result =3D rc; sess_data->func =3D NULL; - SMB2_sess_free_buffer(sess_data); } #else static void @@ -2006,14 +1980,13 @@ SMB2_sess_auth_rawntlmssp_authenticate(struct SMB2_= sess_data *sess_data); static void SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_sess_data *sess_data) { - int rc; - struct cifs_ses *ses =3D sess_data->ses; - struct TCP_Server_Info *server =3D sess_data->server; struct smb2_sess_setup_rsp *rsp =3D NULL; - unsigned char *ntlmssp_blob =3D NULL; + struct TCP_Server_Info *server =3D sess_data->server; + struct smb_message *smb =3D NULL; + struct cifs_ses *ses =3D sess_data->ses; bool use_spnego =3D false; /* else use raw ntlmssp */ - u16 blob_length =3D 0; bool is_binding =3D false; + int rc =3D -ENOMEM; =20 /* * If memory allocation is successful, caller of this function @@ -2026,13 +1999,12 @@ SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_ses= s_data *sess_data) } ses->ntlmssp->sesskey_per_smbsess =3D true; =20 - rc =3D SMB2_sess_alloc_buffer(sess_data); - if (rc) + smb =3D SMB2_create_session_request(sess_data); + if (!smb) goto out_err; =20 - rc =3D build_ntlmssp_smb3_negotiate_blob(&ntlmssp_blob, - &blob_length, ses, server, - sess_data->nls_cp); + rc =3D build_ntlmssp_smb3_negotiate_blob(smb, ses, server, + sess_data->nls_cp); if (rc) goto out; =20 @@ -2042,15 +2014,12 @@ SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_ses= s_data *sess_data) rc =3D -EOPNOTSUPP; goto out; } - sess_data->iov[1].iov_base =3D ntlmssp_blob; - sess_data->iov[1].iov_len =3D blob_length; =20 - rc =3D SMB2_sess_sendreceive(sess_data); - rsp =3D (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base; + rc =3D SMB2_sess_sendreceive(sess_data, smb); + rsp =3D (struct smb2_sess_setup_rsp *)smb->response; =20 /* If true, rc here is expected and not an error */ - if (sess_data->buf0_type !=3D CIFS_NO_BUFFER && - rsp->hdr.Status =3D=3D STATUS_MORE_PROCESSING_REQUIRED) + if (rsp->hdr.Status =3D=3D STATUS_MORE_PROCESSING_REQUIRED) rc =3D 0; =20 if (rc) @@ -2081,14 +2050,13 @@ SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_ses= s_data *sess_data) } =20 out: - kfree_sensitive(ntlmssp_blob); - SMB2_sess_free_buffer(sess_data); if (!rc) { sess_data->result =3D 0; sess_data->func =3D SMB2_sess_auth_rawntlmssp_authenticate; return; } out_err: + smb_put_messages(smb); kfree_sensitive(ses->ntlmssp); ses->ntlmssp =3D NULL; sess_data->result =3D rc; @@ -2098,26 +2066,23 @@ SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_ses= s_data *sess_data) static void SMB2_sess_auth_rawntlmssp_authenticate(struct SMB2_sess_data *sess_data) { - int rc; + struct smb_message *smb; struct cifs_ses *ses =3D sess_data->ses; struct TCP_Server_Info *server =3D sess_data->server; struct smb2_sess_setup_req *req; struct smb2_sess_setup_rsp *rsp =3D NULL; - unsigned char *ntlmssp_blob =3D NULL; bool use_spnego =3D false; /* else use raw ntlmssp */ - u16 blob_length =3D 0; bool is_binding =3D false; + int rc =3D -ENOMEM; =20 - rc =3D SMB2_sess_alloc_buffer(sess_data); - if (rc) + smb =3D SMB2_create_session_request(sess_data); + if (!smb) goto out; =20 - req =3D (struct smb2_sess_setup_req *) sess_data->iov[0].iov_base; + req =3D smb->request; req->hdr.SessionId =3D cpu_to_le64(ses->Suid); =20 - rc =3D build_ntlmssp_auth_blob(&ntlmssp_blob, &blob_length, - ses, server, - sess_data->nls_cp); + rc =3D build_ntlmssp_auth_blob(smb, ses, server, sess_data->nls_cp); if (rc) { cifs_dbg(FYI, "build_ntlmssp_auth_blob failed %d\n", rc); goto out; @@ -2129,14 +2094,12 @@ SMB2_sess_auth_rawntlmssp_authenticate(struct SMB2_= sess_data *sess_data) rc =3D -EOPNOTSUPP; goto out; } - sess_data->iov[1].iov_base =3D ntlmssp_blob; - sess_data->iov[1].iov_len =3D blob_length; =20 - rc =3D SMB2_sess_sendreceive(sess_data); + rc =3D SMB2_sess_sendreceive(sess_data, smb); if (rc) goto out; =20 - rsp =3D (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base; + rsp =3D (struct smb2_sess_setup_rsp *)smb->response; =20 spin_lock(&ses->ses_lock); is_binding =3D (ses->ses_status =3D=3D SES_GOOD); @@ -2165,8 +2128,6 @@ SMB2_sess_auth_rawntlmssp_authenticate(struct SMB2_se= ss_data *sess_data) } #endif out: - kfree_sensitive(ntlmssp_blob); - SMB2_sess_free_buffer(sess_data); kfree_sensitive(ses->ntlmssp); ses->ntlmssp =3D NULL; sess_data->result =3D rc; @@ -2224,7 +2185,6 @@ SMB2_sess_setup(const unsigned int xid, struct cifs_s= es *ses, sess_data->xid =3D xid; sess_data->ses =3D ses; sess_data->server =3D server; - sess_data->buf0_type =3D CIFS_NO_BUFFER; sess_data->nls_cp =3D (struct nls_table *) nls_cp; sess_data->previous_session =3D ses->Suid; From nobody Thu Dec 18 03:20:29 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DA8BF2D3A88 for ; Wed, 6 Aug 2025 20:39:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512769; cv=none; b=NRfzlQNV9dv+8CxSy9VvXxPRxxfd3rHhD6A6ScZOb/OuKGgGqoN8wgU6ftLar4tvybMUfQNzCHe3Qh3dmkR1Zm+xtkYhLMKQ8Q7XZFfjM7vKpoQokb13v5DF5K9VfZHHfsAXFAlFz97OJpTMViIPyQQCMHxdAZjhezUV4Oa5PDU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512769; c=relaxed/simple; bh=vdI+9J76+Cl2+uKmq0mv/gnrM8i3Q2sgMJ9yHiTjJLU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=dv+1VRKUOhKxxtf8bojQuY2bV29v5NqOM8aBKKvfq/LYu2mfa2LtX51a5DAb2bMby34mO7PuLPLNvXyODW0atEnLreHZRElMazLljLBfzCbuQQDblnQ6Y+tudAJgSq5XqdKZXZD/Pp0Tot5Yma7b+A0L+g4WFsGytnkrkE1XpdE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=cYEp1kNu; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="cYEp1kNu" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1754512767; h=from:from:reply-to:subject:subject: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=TviJ0wsdbXIbz3z58i/ZtA4k4O1wXNxFsbxV+K9WGqo=; b=cYEp1kNue2Fta8ffbKx0zeeZOM/VP94b6jZJKWmMYUo9LhLnfCH4oiVf6h5y78vAJS+3YA oEC7rFX8GDks+eVexDiWlU8gvuQ/cV1M/nqs0ax8g6Gy5juHlBQLo2RH+LO8VeAU4GNRkZ YsU3cWgk6P8soPo8MtVtD1OW5n+kmRc= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-228-MtxQM8lUNAW7Tfx7OKc4Zw-1; Wed, 06 Aug 2025 16:39:23 -0400 X-MC-Unique: MtxQM8lUNAW7Tfx7OKc4Zw-1 X-Mimecast-MFC-AGG-ID: MtxQM8lUNAW7Tfx7OKc4Zw_1754512760 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 49B6C1800446; Wed, 6 Aug 2025 20:39:20 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.17]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 449053000198; Wed, 6 Aug 2025 20:39:17 +0000 (UTC) From: David Howells To: Steve French Cc: David Howells , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Wang Zhaolong , Stefan Metzmacher , Mina Almasry , linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org, netfs@lists.linux.dev, linux-fsdevel@vger.kernel.org Subject: [RFC PATCH 26/31] cifs: Convert SMB2 Logoff request Date: Wed, 6 Aug 2025 21:36:47 +0100 Message-ID: <20250806203705.2560493-27-dhowells@redhat.com> In-Reply-To: <20250806203705.2560493-1-dhowells@redhat.com> References: <20250806203705.2560493-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Howells cc: Steve French cc: Paulo Alcantara cc: Shyam Prasad N cc: Tom Talpey cc: linux-cifs@vger.kernel.org cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/smb/client/smb2pdu.c | 31 +++++++++---------------------- 1 file changed, 9 insertions(+), 22 deletions(-) diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c index 685af9c0cdcb..c63c62cd6638 100644 --- a/fs/smb/client/smb2pdu.c +++ b/fs/smb/client/smb2pdu.c @@ -2212,15 +2212,10 @@ SMB2_sess_setup(const unsigned int xid, struct cifs= _ses *ses, int SMB2_logoff(const unsigned int xid, struct cifs_ses *ses) { - struct smb_rqst rqst; - struct smb2_logoff_req *req; /* response is also trivial struct */ - int rc =3D 0; struct TCP_Server_Info *server; - int flags =3D 0; - unsigned int total_len; - struct kvec iov[1]; - struct kvec rsp_iov; - int resp_buf_type; + struct smb2_logoff_req *req; /* response is also trivial struct */ + struct smb_message *smb =3D NULL; + int rc =3D 0, flags =3D 0; =20 cifs_dbg(FYI, "disconnect session %p\n", ses); =20 @@ -2237,10 +2232,10 @@ SMB2_logoff(const unsigned int xid, struct cifs_ses= *ses) } spin_unlock(&ses->chan_lock); =20 - rc =3D smb2_plain_req_init(SMB2_LOGOFF, NULL, ses->server, - (void **) &req, &total_len); - if (rc) - return rc; + smb =3D smb2_create_request(SMB2_LOGOFF, server, NULL, + sizeof(*req), sizeof(*req), 0, 0); + if (!smb) + return -ENOMEM; =20 /* since no tcon, smb2_init can not do this, so do here */ req->hdr.SessionId =3D cpu_to_le64(ses->Suid); @@ -2252,21 +2247,13 @@ SMB2_logoff(const unsigned int xid, struct cifs_ses= *ses) =20 flags |=3D CIFS_NO_RSP_BUF; =20 - iov[0].iov_base =3D (char *)req; - iov[0].iov_len =3D total_len; - - memset(&rqst, 0, sizeof(struct smb_rqst)); - rqst.rq_iov =3D iov; - rqst.rq_nvec =3D 1; - - rc =3D cifs_send_recv(xid, ses, ses->server, - &rqst, &resp_buf_type, flags, &rsp_iov); - cifs_small_buf_release(req); + rc =3D smb_send_recv_messages(xid, ses, ses->server, smb, flags); /* * No tcon so can't do * cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]); */ =20 + smb_put_messages(smb); smb2_session_already_dead: return rc; } From nobody Thu Dec 18 03:20:29 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A664C2D3EDF for ; Wed, 6 Aug 2025 20:39:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512773; cv=none; b=Xln2zl+wQIoH73hTN0RYygfHxq9vq8GTMpnfPuPnHTYhJgZV3zV009skwhwBkYhOK8JsTQsRs8mIOkBmT/29w5K7txEAiEVbJR5Wulyb/s0oqTluPYgMJp6pNI3CSDdNSaqDgjRT0dGrICNXuxbUBC0DDODDrYdvygbnTMVwrzA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512773; c=relaxed/simple; bh=EmcC1MzHMapaCFx8ngoOknAJSipRgtspC2cISwSR4YA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=siiJcSuti0rhLHs3tw2A9pz4/3WSjxSx3zq8lAhcYzaLJaTjCLLKlB87YUnNk9snwtZlF4Ra9pyfsFWE+bKtVgDbVvKHbBYCEHm7IxaOJRXHQfONACKfxATbL3OaBWh4ibLBOGWHotMyhQQ9K1LBvtnATQBstFvbOk77/n6lFdg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=AP1I3w1Z; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="AP1I3w1Z" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1754512770; h=from:from:reply-to:subject:subject: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=1N8y8Gx1EbPTw63BonzmbK2SbB3Yno56oTacfPQuS/A=; b=AP1I3w1Z+UcCTPN5IyHipNg3zabF+Mhb6mN/fImdOv0wu23nEE3LSMasRmKcpk43RXC9t/ BnYBHQpHZCQeDvmXbEPZb9+6VUhvjkS+V/El8SLD2OiuQ/MOWzA9bmiLQoskyj84TaDrIi gRkRDbFQMlrYRBXuavm43VZL6tffItc= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-637-sf-38EwgNMepm8E2h_JoXw-1; Wed, 06 Aug 2025 16:39:27 -0400 X-MC-Unique: sf-38EwgNMepm8E2h_JoXw-1 X-Mimecast-MFC-AGG-ID: sf-38EwgNMepm8E2h_JoXw_1754512765 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 501691800346; Wed, 6 Aug 2025 20:39:25 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.17]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id D9C8619560AD; Wed, 6 Aug 2025 20:39:21 +0000 (UTC) From: David Howells To: Steve French Cc: David Howells , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Wang Zhaolong , Stefan Metzmacher , Mina Almasry , linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org, netfs@lists.linux.dev, linux-fsdevel@vger.kernel.org Subject: [RFC PATCH 27/31] cifs: Convert SMB2 Tree Connect request Date: Wed, 6 Aug 2025 21:36:48 +0100 Message-ID: <20250806203705.2560493-28-dhowells@redhat.com> In-Reply-To: <20250806203705.2560493-1-dhowells@redhat.com> References: <20250806203705.2560493-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Howells cc: Steve French cc: Paulo Alcantara cc: Shyam Prasad N cc: Tom Talpey cc: linux-cifs@vger.kernel.org cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/smb/client/smb2pdu.c | 71 +++++++++++++++-------------------------- 1 file changed, 25 insertions(+), 46 deletions(-) diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c index c63c62cd6638..4300ae311ee2 100644 --- a/fs/smb/client/smb2pdu.c +++ b/fs/smb/client/smb2pdu.c @@ -2277,57 +2277,43 @@ int SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, struct cifs_tcon *tcon, const struct nls_table *cp) { - struct smb_rqst rqst; + struct TCP_Server_Info *server =3D cifs_pick_channel(ses); struct smb2_tree_connect_req *req; struct smb2_tree_connect_rsp *rsp =3D NULL; - struct kvec iov[2]; - struct kvec rsp_iov =3D { NULL, 0 }; - int rc =3D 0; - int resp_buftype; - int unc_path_len; - __le16 *unc_path =3D NULL; + struct smb_message *smb =3D NULL; + int unc_path_size; int flags =3D 0; - unsigned int total_len; - struct TCP_Server_Info *server =3D cifs_pick_channel(ses); + int rc =3D 0; =20 cifs_dbg(FYI, "TCON\n"); =20 if (!server || !tree) return -EIO; =20 - unc_path =3D kmalloc(MAX_SHARENAME_LENGTH * 2, GFP_KERNEL); - if (unc_path =3D=3D NULL) - return -ENOMEM; - - unc_path_len =3D cifs_strtoUTF16(unc_path, tree, strlen(tree), cp); - if (unc_path_len <=3D 0) { - kfree(unc_path); - return -EINVAL; - } - unc_path_len *=3D 2; + unc_path_size =3D cifs_size_strtoUTF16(tree, INT_MAX, cp); =20 /* SMB2 TREE_CONNECT request must be called with TreeId =3D=3D 0 */ tcon->tid =3D 0; atomic_set(&tcon->num_remote_opens, 0); - rc =3D smb2_plain_req_init(SMB2_TREE_CONNECT, tcon, server, - (void **) &req, &total_len); - if (rc) { - kfree(unc_path); - return rc; - } + + smb =3D smb2_create_request(SMB2_TREE_CONNECT, server, tcon, + sizeof(*req), sizeof(*req) + unc_path_size, 0, + SMB2_REQ_DYNAMIC); + if (!smb) + return -ENOMEM; =20 if (smb3_encryption_required(tcon)) flags |=3D CIFS_TRANSFORM_REQ; =20 - iov[0].iov_base =3D (char *)req; - /* 1 for pad */ - iov[0].iov_len =3D total_len - 1; - /* Testing shows that buffer offset must be at location of Buffer[0] */ - req->PathOffset =3D cpu_to_le16(sizeof(struct smb2_tree_connect_req)); - req->PathLength =3D cpu_to_le16(unc_path_len); - iov[1].iov_base =3D unc_path; - iov[1].iov_len =3D unc_path_len; + req->PathOffset =3D cpu_to_le16(smb->ext_offset); + req->PathLength =3D cpu_to_le16(unc_path_size); + + rc =3D cifs_strtoUTF16(smb->request + smb->ext_offset, tree, strlen(tree)= , cp); + if (rc <=3D 0) { + rc =3D -EINVAL; + goto tcon_exit; + } =20 /* * 3.11 tcon req must be signed if not encrypted. See MS-SMB2 3.2.4.1.1 @@ -2341,22 +2327,17 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *= ses, const char *tree, ((ses->user_name !=3D NULL) || (ses->sectype =3D=3D Kerberos))) req->hdr.Flags |=3D SMB2_FLAGS_SIGNED; =20 - memset(&rqst, 0, sizeof(struct smb_rqst)); - rqst.rq_iov =3D iov; - rqst.rq_nvec =3D 2; - /* Need 64 for max size write so ask for more in case not there yet */ if (server->credits >=3D server->max_credits) req->hdr.CreditRequest =3D cpu_to_le16(0); else req->hdr.CreditRequest =3D cpu_to_le16( - min_t(int, server->max_credits - - server->credits, 64)); + min_t(int, server->max_credits - server->credits, 64)); =20 - rc =3D cifs_send_recv(xid, ses, server, - &rqst, &resp_buftype, flags, &rsp_iov); - cifs_small_buf_release(req); - rsp =3D (struct smb2_tree_connect_rsp *)rsp_iov.iov_base; + rc =3D smb_send_recv_messages(xid, ses, server, smb, flags); + smb_clear_request(smb); + + rsp =3D (struct smb2_tree_connect_rsp *)smb->response; trace_smb3_tcon(xid, tcon->tid, ses->Suid, tree, rc); if ((rc !=3D 0) || (rsp =3D=3D NULL)) { cifs_stats_fail_inc(tcon, SMB2_TREE_CONNECT); @@ -2403,9 +2384,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *se= s, const char *tree, if (tcon->share_flags & SMB2_SHAREFLAG_ISOLATED_TRANSPORT) server->nosharesock =3D true; tcon_exit: - - free_rsp_buf(resp_buftype, rsp); - kfree(unc_path); + smb_put_messages(smb); return rc; =20 tcon_error_exit: From nobody Thu Dec 18 03:20:29 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D911E2D46BA for ; Wed, 6 Aug 2025 20:39:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512778; cv=none; b=uuVIjb4IeCdAWE7vNdugvE5hodCZlvi5MuHQ30q1x4mCfFgKKaNIG6CNE8lYAd4W8mMbH34CJoaRcLSBJkzqNE2y7DOCaXBYTPei1cXtvj4j/5DuyywfaWVYdEieFoZfH0qOOAl2Bv8JFx7XqszgCFGWr/bJQwkbzqLpM8TjLNU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512778; c=relaxed/simple; bh=XoqgTX1eo1X1heEZwLfDpLWPxo4E0Ftvt+pp/Wua9Tc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=nyh2mABudViENU0CXwGKYYiY3Nq6zqDZXJnoqwddtc9hDPAwcGEkJiy1svunhqSYkNOm2B0DukqJD+93FkjzQmGm+Iv3iN1BpAs58u/V0aYBBb2IPBJlO9T9xTPeLIctu0FGhmYeF7pFDLyW5tsk/A278QWAxjQcrlQJvl1Q3ko= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=FQuGj8xd; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="FQuGj8xd" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1754512775; h=from:from:reply-to:subject:subject: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=h1DRWP+raeweIc7wbapxyNrt0tD9BCSLBA67eiNSXJg=; b=FQuGj8xdcOded9aWrj6c1sk8OglYUlqhwbQQBeGRA4HAKsWuWb3kYYM3ZizN+VS5q/F7if PraXN9flMSTJi5FPzbOQ2E5iQW5Hcgtqxyn4FbljVhA03zWf3aF6vZqctRC6+GFe0YvIdJ MqIU1ORlG5QezJ1vDn8YRkNcjGYWycg= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-384-WZyqM8nJOvWGdMwc-ZI6mw-1; Wed, 06 Aug 2025 16:39:31 -0400 X-MC-Unique: WZyqM8nJOvWGdMwc-ZI6mw-1 X-Mimecast-MFC-AGG-ID: WZyqM8nJOvWGdMwc-ZI6mw_1754512770 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id EE87A19560B4; Wed, 6 Aug 2025 20:39:29 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.17]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id DC3CF19560AD; Wed, 6 Aug 2025 20:39:26 +0000 (UTC) From: David Howells To: Steve French Cc: David Howells , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Wang Zhaolong , Stefan Metzmacher , Mina Almasry , linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org, netfs@lists.linux.dev, linux-fsdevel@vger.kernel.org Subject: [RFC PATCH 28/31] cifs: Convert SMB2 Tree Disconnect request Date: Wed, 6 Aug 2025 21:36:49 +0100 Message-ID: <20250806203705.2560493-29-dhowells@redhat.com> In-Reply-To: <20250806203705.2560493-1-dhowells@redhat.com> References: <20250806203705.2560493-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Howells cc: Steve French cc: Paulo Alcantara cc: Shyam Prasad N cc: Tom Talpey cc: linux-cifs@vger.kernel.org cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/smb/client/smb2pdu.c | 31 ++++++++++--------------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c index 4300ae311ee2..9357c4953d9f 100644 --- a/fs/smb/client/smb2pdu.c +++ b/fs/smb/client/smb2pdu.c @@ -2396,16 +2396,12 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *= ses, const char *tree, int SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon) { - struct smb_rqst rqst; struct smb2_tree_disconnect_req *req; /* response is trivial */ - int rc =3D 0; + struct smb_message *smb =3D NULL; struct cifs_ses *ses =3D tcon->ses; struct TCP_Server_Info *server =3D cifs_pick_channel(ses); int flags =3D 0; - unsigned int total_len; - struct kvec iov[1]; - struct kvec rsp_iov; - int resp_buf_type; + int rc =3D 0; =20 cifs_dbg(FYI, "Tree Disconnect\n"); =20 @@ -2423,33 +2419,26 @@ SMB2_tdis(const unsigned int xid, struct cifs_tcon = *tcon) =20 invalidate_all_cached_dirs(tcon); =20 - rc =3D smb2_plain_req_init(SMB2_TREE_DISCONNECT, tcon, server, - (void **) &req, - &total_len); - if (rc) - return rc; + smb =3D smb2_create_request(SMB2_TREE_DISCONNECT, server, tcon, + sizeof(*req), sizeof(*req), 0, + SMB2_REQ_DYNAMIC); + if (!smb) + return -ENOMEM; =20 if (smb3_encryption_required(tcon)) flags |=3D CIFS_TRANSFORM_REQ; =20 flags |=3D CIFS_NO_RSP_BUF; =20 - iov[0].iov_base =3D (char *)req; - iov[0].iov_len =3D total_len; - - memset(&rqst, 0, sizeof(struct smb_rqst)); - rqst.rq_iov =3D iov; - rqst.rq_nvec =3D 1; - - rc =3D cifs_send_recv(xid, ses, server, - &rqst, &resp_buf_type, flags, &rsp_iov); - cifs_small_buf_release(req); + rc =3D smb_send_recv_messages(xid, ses, server, smb, flags); + smb_clear_request(smb); if (rc) { cifs_stats_fail_inc(tcon, SMB2_TREE_DISCONNECT); trace_smb3_tdis_err(xid, tcon->tid, ses->Suid, rc); } trace_smb3_tdis_done(xid, tcon->tid, ses->Suid); =20 + smb_put_messages(smb); return rc; } From nobody Thu Dec 18 03:20:29 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C4F192BEC27 for ; Wed, 6 Aug 2025 20:39:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512797; cv=none; b=JFdhif2ULz9CR5IYH7B24Fj04aCY1RvUkiH1Y6MWJ2uixyoPJ0nGtxroHvJMxd/IKj7Bg4sYFKrg/iLkv8Ng5Nv6iD9RCN6wB2iBvkha/38M0x0VUHRsCMF1FSHpkxn487+RR0zicT5eK+kPS7+IMlf02cXxyhDdM0rwNQ6FQtI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512797; c=relaxed/simple; bh=w29jphyP+fzgfrn42RwyyriQgd/HIEHbbYuoo/K4Biw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Q4igjcq+h6QWJe3lrcqZbg9nmLm+5k0NzB7mYGdt+LkrOrF57l71GrcerPZYFnJCJ6ilYzZ5oRDIadBP7ckD662PXxhBZofSNoXKTJ1LIp8sBxOrUP7giOeXlHMABu5hjBCl7y5RT3UY7ySsG7ht6YtAUoA7Yf2r/JC1i0w7zRA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=F9D5PsVD; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="F9D5PsVD" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1754512795; h=from:from:reply-to:subject:subject: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=GAakLlrB9vWvfnHytlwwIHshMEgP8xr92t7+SCjWx94=; b=F9D5PsVDtyqjp5wN0gQ2fUNHDr3cjkzzU8fQA7P0Eu23rBB63Gpueqf+ZrtxQn2v8LyXSs NhlzgpTPe6D1UkgFdcHi6sW8hHn22LyUrSxjMFVsQ3uwHjzL2gzclBtYnnyPhsCKNfyOA8 lfAACgouyhJwkdGF9p7Rww7GeJfTsY8= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-491-TWS4fjsvPk-pp9br3XjYlA-1; Wed, 06 Aug 2025 16:39:49 -0400 X-MC-Unique: TWS4fjsvPk-pp9br3XjYlA-1 X-Mimecast-MFC-AGG-ID: TWS4fjsvPk-pp9br3XjYlA_1754512774 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 92BA41955D99; Wed, 6 Aug 2025 20:39:34 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.17]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 852BF1956086; Wed, 6 Aug 2025 20:39:31 +0000 (UTC) From: David Howells To: Steve French Cc: David Howells , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Wang Zhaolong , Stefan Metzmacher , Mina Almasry , linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org, netfs@lists.linux.dev, linux-fsdevel@vger.kernel.org Subject: [RFC PATCH 29/31] cifs: Rearrange Create request subfuncs Date: Wed, 6 Aug 2025 21:36:50 +0100 Message-ID: <20250806203705.2560493-30-dhowells@redhat.com> In-Reply-To: <20250806203705.2560493-1-dhowells@redhat.com> References: <20250806203705.2560493-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Howells cc: Steve French cc: Paulo Alcantara cc: Shyam Prasad N cc: Tom Talpey cc: linux-cifs@vger.kernel.org cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/smb/client/smb2pdu.c | 357 ++++++++++++++++++++-------------------- 1 file changed, 178 insertions(+), 179 deletions(-) diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c index 9357c4953d9f..85486748dd7b 100644 --- a/fs/smb/client/smb2pdu.c +++ b/fs/smb/client/smb2pdu.c @@ -1228,61 +1228,6 @@ static int smb311_decode_neg_context(struct smb_mess= age *smb, return rc; } =20 -static struct create_posix * -create_posix_buf(umode_t mode) -{ - struct create_posix *buf; - - buf =3D kzalloc(sizeof(struct create_posix), - GFP_KERNEL); - if (!buf) - return NULL; - - buf->ccontext.DataOffset =3D - cpu_to_le16(offsetof(struct create_posix, Mode)); - buf->ccontext.DataLength =3D cpu_to_le32(4); - buf->ccontext.NameOffset =3D - cpu_to_le16(offsetof(struct create_posix, Name)); - buf->ccontext.NameLength =3D cpu_to_le16(16); - - /* SMB2_CREATE_TAG_POSIX is "0x93AD25509CB411E7B42383DE968BCD7C" */ - buf->Name[0] =3D 0x93; - buf->Name[1] =3D 0xAD; - buf->Name[2] =3D 0x25; - buf->Name[3] =3D 0x50; - buf->Name[4] =3D 0x9C; - buf->Name[5] =3D 0xB4; - buf->Name[6] =3D 0x11; - buf->Name[7] =3D 0xE7; - buf->Name[8] =3D 0xB4; - buf->Name[9] =3D 0x23; - buf->Name[10] =3D 0x83; - buf->Name[11] =3D 0xDE; - buf->Name[12] =3D 0x96; - buf->Name[13] =3D 0x8B; - buf->Name[14] =3D 0xCD; - buf->Name[15] =3D 0x7C; - buf->Mode =3D cpu_to_le32(mode); - cifs_dbg(FYI, "mode on posix create 0%o\n", mode); - return buf; -} - -static int -add_posix_context(struct kvec *iov, unsigned int *num_iovec, umode_t mode) -{ - unsigned int num =3D *num_iovec; - - iov[num].iov_base =3D create_posix_buf(mode); - if (mode =3D=3D ACL_NO_MODE) - cifs_dbg(FYI, "%s: no mode\n", __func__); - if (iov[num].iov_base =3D=3D NULL) - return -ENOMEM; - iov[num].iov_len =3D sizeof(struct create_posix); - *num_iovec =3D num + 1; - return 0; -} - - /* * * SMB2 Worker functions follow: @@ -2443,6 +2388,60 @@ SMB2_tdis(const unsigned int xid, struct cifs_tcon *= tcon) } =20 =20 +static struct create_posix * +create_posix_buf(umode_t mode) +{ + struct create_posix *buf; + + buf =3D kzalloc(sizeof(struct create_posix), + GFP_KERNEL); + if (!buf) + return NULL; + + buf->ccontext.DataOffset =3D + cpu_to_le16(offsetof(struct create_posix, Mode)); + buf->ccontext.DataLength =3D cpu_to_le32(4); + buf->ccontext.NameOffset =3D + cpu_to_le16(offsetof(struct create_posix, Name)); + buf->ccontext.NameLength =3D cpu_to_le16(16); + + /* SMB2_CREATE_TAG_POSIX is "0x93AD25509CB411E7B42383DE968BCD7C" */ + buf->Name[0] =3D 0x93; + buf->Name[1] =3D 0xAD; + buf->Name[2] =3D 0x25; + buf->Name[3] =3D 0x50; + buf->Name[4] =3D 0x9C; + buf->Name[5] =3D 0xB4; + buf->Name[6] =3D 0x11; + buf->Name[7] =3D 0xE7; + buf->Name[8] =3D 0xB4; + buf->Name[9] =3D 0x23; + buf->Name[10] =3D 0x83; + buf->Name[11] =3D 0xDE; + buf->Name[12] =3D 0x96; + buf->Name[13] =3D 0x8B; + buf->Name[14] =3D 0xCD; + buf->Name[15] =3D 0x7C; + buf->Mode =3D cpu_to_le32(mode); + cifs_dbg(FYI, "mode on posix create 0%o\n", mode); + return buf; +} + +static int +add_posix_context(struct kvec *iov, unsigned int *num_iovec, umode_t mode) +{ + unsigned int num =3D *num_iovec; + + iov[num].iov_base =3D create_posix_buf(mode); + if (mode =3D=3D ACL_NO_MODE) + cifs_dbg(FYI, "%s: no mode\n", __func__); + if (iov[num].iov_base =3D=3D NULL) + return -ENOMEM; + iov[num].iov_len =3D sizeof(struct create_posix); + *num_iovec =3D num + 1; + return 0; +} + static struct create_durable * create_durable_buf(void) { @@ -2491,130 +2490,6 @@ create_reconnect_durable_buf(struct cifs_fid *fid) return buf; } =20 -static void -parse_query_id_ctxt(struct create_context *cc, struct smb2_file_all_info *= buf) -{ - struct create_disk_id_rsp *pdisk_id =3D (struct create_disk_id_rsp *)cc; - - cifs_dbg(FYI, "parse query id context 0x%llx 0x%llx\n", - pdisk_id->DiskFileId, pdisk_id->VolumeId); - buf->IndexNumber =3D pdisk_id->DiskFileId; -} - -static void -parse_posix_ctxt(struct create_context *cc, struct smb2_file_all_info *inf= o, - struct create_posix_rsp *posix) -{ - int sid_len; - u8 *beg =3D (u8 *)cc + le16_to_cpu(cc->DataOffset); - u8 *end =3D beg + le32_to_cpu(cc->DataLength); - u8 *sid; - - memset(posix, 0, sizeof(*posix)); - - posix->nlink =3D le32_to_cpu(*(__le32 *)(beg + 0)); - posix->reparse_tag =3D le32_to_cpu(*(__le32 *)(beg + 4)); - posix->mode =3D le32_to_cpu(*(__le32 *)(beg + 8)); - - sid =3D beg + 12; - sid_len =3D posix_info_sid_size(sid, end); - if (sid_len < 0) { - cifs_dbg(VFS, "bad owner sid in posix create response\n"); - return; - } - memcpy(&posix->owner, sid, sid_len); - - sid =3D sid + sid_len; - sid_len =3D posix_info_sid_size(sid, end); - if (sid_len < 0) { - cifs_dbg(VFS, "bad group sid in posix create response\n"); - return; - } - memcpy(&posix->group, sid, sid_len); - - cifs_dbg(FYI, "nlink=3D%d mode=3D%o reparse_tag=3D%x\n", - posix->nlink, posix->mode, posix->reparse_tag); -} - -int smb2_parse_contexts(struct TCP_Server_Info *server, - struct kvec *rsp_iov, - __u16 *epoch, - char *lease_key, __u8 *oplock, - struct smb2_file_all_info *buf, - struct create_posix_rsp *posix) -{ - struct smb2_create_rsp *rsp =3D rsp_iov->iov_base; - struct create_context *cc; - size_t rem, off, len; - size_t doff, dlen; - size_t noff, nlen; - char *name; - static const char smb3_create_tag_posix[] =3D { - 0x93, 0xAD, 0x25, 0x50, 0x9C, - 0xB4, 0x11, 0xE7, 0xB4, 0x23, 0x83, - 0xDE, 0x96, 0x8B, 0xCD, 0x7C - }; - - *oplock =3D 0; - - off =3D le32_to_cpu(rsp->CreateContextsOffset); - rem =3D le32_to_cpu(rsp->CreateContextsLength); - if (check_add_overflow(off, rem, &len) || len > rsp_iov->iov_len) - return -EINVAL; - cc =3D (struct create_context *)((u8 *)rsp + off); - - /* Initialize inode number to 0 in case no valid data in qfid context */ - if (buf) - buf->IndexNumber =3D 0; - - while (rem >=3D sizeof(*cc)) { - doff =3D le16_to_cpu(cc->DataOffset); - dlen =3D le32_to_cpu(cc->DataLength); - if (check_add_overflow(doff, dlen, &len) || len > rem) - return -EINVAL; - - noff =3D le16_to_cpu(cc->NameOffset); - nlen =3D le16_to_cpu(cc->NameLength); - if (noff + nlen > doff) - return -EINVAL; - - name =3D (char *)cc + noff; - switch (nlen) { - case 4: - if (!strncmp(name, SMB2_CREATE_REQUEST_LEASE, 4)) { - *oplock =3D server->ops->parse_lease_buf(cc, epoch, - lease_key); - } else if (buf && - !strncmp(name, SMB2_CREATE_QUERY_ON_DISK_ID, 4)) { - parse_query_id_ctxt(cc, buf); - } - break; - case 16: - if (posix && !memcmp(name, smb3_create_tag_posix, 16)) - parse_posix_ctxt(cc, buf, posix); - break; - default: - cifs_dbg(FYI, "%s: unhandled context (nlen=3D%zu dlen=3D%zu)\n", - __func__, nlen, dlen); - if (IS_ENABLED(CONFIG_CIFS_DEBUG2)) - cifs_dump_mem("context data: ", cc, dlen); - break; - } - - off =3D le32_to_cpu(cc->Next); - if (!off) - break; - if (check_sub_overflow(rem, off, &rem)) - return -EINVAL; - cc =3D (struct create_context *)((u8 *)cc + off); - } - - if (rsp->OplockLevel !=3D SMB2_OPLOCK_LEVEL_LEASE) - *oplock =3D rsp->OplockLevel; - - return 0; -} - static int add_lease_context(struct TCP_Server_Info *server, struct smb2_create_req *req, @@ -3383,6 +3258,130 @@ SMB2_open_init(struct cifs_tcon *tcon, struct TCP_S= erver_Info *server, return 0; } =20 +static void +parse_query_id_ctxt(struct create_context *cc, struct smb2_file_all_info *= buf) +{ + struct create_disk_id_rsp *pdisk_id =3D (struct create_disk_id_rsp *)cc; + + cifs_dbg(FYI, "parse query id context 0x%llx 0x%llx\n", + pdisk_id->DiskFileId, pdisk_id->VolumeId); + buf->IndexNumber =3D pdisk_id->DiskFileId; +} + +static void +parse_posix_ctxt(struct create_context *cc, struct smb2_file_all_info *inf= o, + struct create_posix_rsp *posix) +{ + int sid_len; + u8 *beg =3D (u8 *)cc + le16_to_cpu(cc->DataOffset); + u8 *end =3D beg + le32_to_cpu(cc->DataLength); + u8 *sid; + + memset(posix, 0, sizeof(*posix)); + + posix->nlink =3D le32_to_cpu(*(__le32 *)(beg + 0)); + posix->reparse_tag =3D le32_to_cpu(*(__le32 *)(beg + 4)); + posix->mode =3D le32_to_cpu(*(__le32 *)(beg + 8)); + + sid =3D beg + 12; + sid_len =3D posix_info_sid_size(sid, end); + if (sid_len < 0) { + cifs_dbg(VFS, "bad owner sid in posix create response\n"); + return; + } + memcpy(&posix->owner, sid, sid_len); + + sid =3D sid + sid_len; + sid_len =3D posix_info_sid_size(sid, end); + if (sid_len < 0) { + cifs_dbg(VFS, "bad group sid in posix create response\n"); + return; + } + memcpy(&posix->group, sid, sid_len); + + cifs_dbg(FYI, "nlink=3D%d mode=3D%o reparse_tag=3D%x\n", + posix->nlink, posix->mode, posix->reparse_tag); +} + +int smb2_parse_contexts(struct TCP_Server_Info *server, + struct kvec *rsp_iov, + __u16 *epoch, + char *lease_key, __u8 *oplock, + struct smb2_file_all_info *buf, + struct create_posix_rsp *posix) +{ + struct smb2_create_rsp *rsp =3D rsp_iov->iov_base; + struct create_context *cc; + size_t rem, off, len; + size_t doff, dlen; + size_t noff, nlen; + char *name; + static const char smb3_create_tag_posix[] =3D { + 0x93, 0xAD, 0x25, 0x50, 0x9C, + 0xB4, 0x11, 0xE7, 0xB4, 0x23, 0x83, + 0xDE, 0x96, 0x8B, 0xCD, 0x7C + }; + + *oplock =3D 0; + + off =3D le32_to_cpu(rsp->CreateContextsOffset); + rem =3D le32_to_cpu(rsp->CreateContextsLength); + if (check_add_overflow(off, rem, &len) || len > rsp_iov->iov_len) + return -EINVAL; + cc =3D (struct create_context *)((u8 *)rsp + off); + + /* Initialize inode number to 0 in case no valid data in qfid context */ + if (buf) + buf->IndexNumber =3D 0; + + while (rem >=3D sizeof(*cc)) { + doff =3D le16_to_cpu(cc->DataOffset); + dlen =3D le32_to_cpu(cc->DataLength); + if (check_add_overflow(doff, dlen, &len) || len > rem) + return -EINVAL; + + noff =3D le16_to_cpu(cc->NameOffset); + nlen =3D le16_to_cpu(cc->NameLength); + if (noff + nlen > doff) + return -EINVAL; + + name =3D (char *)cc + noff; + switch (nlen) { + case 4: + if (!strncmp(name, SMB2_CREATE_REQUEST_LEASE, 4)) { + *oplock =3D server->ops->parse_lease_buf(cc, epoch, + lease_key); + } else if (buf && + !strncmp(name, SMB2_CREATE_QUERY_ON_DISK_ID, 4)) { + parse_query_id_ctxt(cc, buf); + } + break; + case 16: + if (posix && !memcmp(name, smb3_create_tag_posix, 16)) + parse_posix_ctxt(cc, buf, posix); + break; + default: + cifs_dbg(FYI, "%s: unhandled context (nlen=3D%zu dlen=3D%zu)\n", + __func__, nlen, dlen); + if (IS_ENABLED(CONFIG_CIFS_DEBUG2)) + cifs_dump_mem("context data: ", cc, dlen); + break; + } + + off =3D le32_to_cpu(cc->Next); + if (!off) + break; + if (check_sub_overflow(rem, off, &rem)) + return -EINVAL; + cc =3D (struct create_context *)((u8 *)cc + off); + } + + if (rsp->OplockLevel !=3D SMB2_OPLOCK_LEVEL_LEASE) + *oplock =3D rsp->OplockLevel; + + return 0; +} + /* rq_iov[0] is the request and is released by cifs_small_buf_release(). * All other vectors are freed by kfree(). */ From nobody Thu Dec 18 03:20:29 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 66DA12BEC2F for ; Wed, 6 Aug 2025 20:39:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512797; cv=none; b=OUZJTKLiuoPm2cZolqo13CeoITRlpkW+K3vvrbb54D/z7IzYffpSiqFawN1Sogv45vlGoZ7twnfFF5VgowK3Gydvhy0NHXEvDktzvAo0BgKbuKC133IiIkPq3YrJxg4o+OcjSN+NVsQ4riNX8tsfMVKTS91ANqXQp+339si28jI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512797; c=relaxed/simple; bh=pScYZK0I9EANIJh7jUKFAeAVWFzRano4dJTf29mBV78=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XwFS/NKEh9XMO6QD2WfEKWGFBC4dzcxvx3+iLRY15/fM4BB244TR0sRG0aX9KX65b8eQf9h+XepjSlvSHObBpK9szwYWgHGBEilVaAbo0cwAlqgLx5aOOnMl/CmRC5C1RPaS/flASy8yy9aWKuWI1bp8lfPEOK727frEoWzLYYs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=d6edQJL4; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="d6edQJL4" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1754512794; h=from:from:reply-to:subject:subject: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=66jr/y7YOc44P4z2T9xA9okDQqLDR/TOpWQnaz5O5Q0=; b=d6edQJL4ij4Kl59A71roGpijxXZbIcKtEyI7M8T3AwGM8T10bICITw9q/1bw4+0hVi0uMX ABe0evK2sODA6oLfEdSSI11c6qZ5nICk/l1eRi77Ni/rWegzlfx97XlryZ3ogaysLUyppp YS2T8NqwRa8yElyDFb7JSn4YNRDmwUY= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-92-cs8AQvgkN9el8UbyoPR5WQ-1; Wed, 06 Aug 2025 16:39:50 -0400 X-MC-Unique: cs8AQvgkN9el8UbyoPR5WQ-1 X-Mimecast-MFC-AGG-ID: cs8AQvgkN9el8UbyoPR5WQ_1754512779 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 395971956089; Wed, 6 Aug 2025 20:39:39 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.17]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 2E80D180035C; Wed, 6 Aug 2025 20:39:35 +0000 (UTC) From: David Howells To: Steve French Cc: David Howells , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Wang Zhaolong , Stefan Metzmacher , Mina Almasry , linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org, netfs@lists.linux.dev, linux-fsdevel@vger.kernel.org Subject: [RFC PATCH 30/31] cifs: Convert SMB2 Posix Mkdir request Date: Wed, 6 Aug 2025 21:36:51 +0100 Message-ID: <20250806203705.2560493-31-dhowells@redhat.com> In-Reply-To: <20250806203705.2560493-1-dhowells@redhat.com> References: <20250806203705.2560493-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Howells cc: Steve French cc: Paulo Alcantara cc: Shyam Prasad N cc: Tom Talpey cc: linux-cifs@vger.kernel.org cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/smb/client/smb2pdu.c | 244 ++++++++++++++++++++++------------------ 1 file changed, 137 insertions(+), 107 deletions(-) diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c index 85486748dd7b..9fc55b315474 100644 --- a/fs/smb/client/smb2pdu.c +++ b/fs/smb/client/smb2pdu.c @@ -2388,16 +2388,8 @@ SMB2_tdis(const unsigned int xid, struct cifs_tcon *= tcon) } =20 =20 -static struct create_posix * -create_posix_buf(umode_t mode) +static void fill_posix_buf(struct create_posix *buf, umode_t mode) { - struct create_posix *buf; - - buf =3D kzalloc(sizeof(struct create_posix), - GFP_KERNEL); - if (!buf) - return NULL; - buf->ccontext.DataOffset =3D cpu_to_le16(offsetof(struct create_posix, Mode)); buf->ccontext.DataLength =3D cpu_to_le32(4); @@ -2424,20 +2416,25 @@ create_posix_buf(umode_t mode) buf->Name[15] =3D 0x7C; buf->Mode =3D cpu_to_le32(mode); cifs_dbg(FYI, "mode on posix create 0%o\n", mode); - return buf; } =20 static int add_posix_context(struct kvec *iov, unsigned int *num_iovec, umode_t mode) { + struct create_posix *buf; unsigned int num =3D *num_iovec; =20 - iov[num].iov_base =3D create_posix_buf(mode); if (mode =3D=3D ACL_NO_MODE) cifs_dbg(FYI, "%s: no mode\n", __func__); - if (iov[num].iov_base =3D=3D NULL) + + buf =3D kzalloc(sizeof(struct create_posix), GFP_KERNEL); + if (!buf) return -ENOMEM; - iov[num].iov_len =3D sizeof(struct create_posix); + + fill_posix_buf(buf, mode); + + iov[num].iov_base =3D buf; + iov[num].iov_len =3D sizeof(struct create_posix); *num_iovec =3D num + 1; return 0; } @@ -2906,72 +2903,140 @@ alloc_path_with_tree_prefix(__le16 **out_path, int= *out_size, int *out_len, return 0; } =20 +struct smb2_create_layout { + const struct nls_table *cp; + u16 offset; /* Running offset for assembly */ + u16 path_len; /* Length of utf16 path (or 0) */ + u16 treename_len; /* Length of DFS prefix (or 0) */ + u16 name_len; /* Total name length */ + u16 name_offset; /* Offset in message of name */ + u16 contexts_offset; /* Offset in message contexts */ + u16 contexts_len; /* Length of contexts (or 0) */ + u16 posix_offset; /* Offset in message of posix context */ + u8 name_pad; /* Amount of name padding needed */ +}; + +static int smb311_posix_mkdir_layout(struct cifs_tcon *tcon, + struct smb2_create_layout *lay) +{ + size_t offset =3D lay->offset; + size_t tmp; + bool has_contexts =3D false; + + /* [MS-SMB2] 2.2.13 NameOffset: If SMB2_FLAGS_DFS_OPERATIONS + * is set in the Flags field of the SMB2 header, the file name + * includes a prefix that will be processed during DFS name + * normalization as specified in section 3.3.5.9. Otherwise, + * the file name is relative to the share that is identified + * by the TreeId in the SMB2 header. + */ + lay->name_offset =3D offset; + if (tcon->share_flags & SHI1005_FLAGS_DFS) { + const char *treename =3D tcon->tree_name; + int treename_len; + + /* skip leading "\\" */ + if (!(treename[0] =3D=3D '\\' && treename[1] =3D=3D '\\')) + return -EINVAL; + + treename_len =3D cifs_size_strtoUTF16(treename + 2, INT_MAX, lay->cp); + + lay->treename_len =3D treename_len; + lay->name_len =3D treename_len; + if (lay->path_len) + lay->name_len +=3D 2 + lay->path_len; + } else { + lay->name_len =3D lay->path_len; + } + + offset +=3D lay->name_len; + tmp =3D offset; + offset =3D ALIGN8(offset); + lay->name_pad =3D offset - tmp; + lay->contexts_offset =3D offset; + + if (tcon->posix_extensions) { + /* resource #3: posix buf */ + offset +=3D sizeof(struct create_posix); + has_contexts =3D true; + } + + if (has_contexts) + lay->contexts_len =3D offset - lay->contexts_offset; + else + lay->contexts_offset =3D 0; + + lay->offset =3D offset; + return 0; +} + int smb311_posix_mkdir(const unsigned int xid, struct inode *inode, umode_t mode, struct cifs_tcon *tcon, const char *full_path, struct cifs_sb_info *cifs_sb) { - struct smb_rqst rqst; + struct TCP_Server_Info *server; struct smb2_create_req *req; struct smb2_create_rsp *rsp =3D NULL; + struct smb_message *smb =3D NULL; struct cifs_ses *ses =3D tcon->ses; - struct kvec iov[3]; /* make sure at least one for each open context */ - struct kvec rsp_iov =3D {NULL, 0}; - int resp_buftype; - int uni_path_len; - __le16 *copy_path =3D NULL; - int copy_size; - int rc =3D 0; - unsigned int n_iov =3D 2; + __le16 *utf16_path =3D NULL; __u32 file_attributes =3D 0; - char *pc_buf =3D NULL; + int retries =3D 0, cur_sleep =3D 1, path_len; int flags =3D 0; - unsigned int total_len; - __le16 *utf16_path =3D NULL; - struct TCP_Server_Info *server; - int retries =3D 0, cur_sleep =3D 1; + int rc =3D 0; + + /* resource #1: path allocation */ + utf16_path =3D cifs_convert_path_to_utf16(full_path, cifs_sb); + if (!utf16_path) + return -ENOMEM; + path_len =3D UniStrlen(utf16_path); =20 replay_again: /* reinitialize for possible replay */ flags =3D 0; - n_iov =3D 2; server =3D cifs_pick_channel(ses); =20 cifs_dbg(FYI, "mkdir\n"); =20 - /* resource #1: path allocation */ - utf16_path =3D cifs_convert_path_to_utf16(full_path, cifs_sb); - if (!utf16_path) - return -ENOMEM; - - if (!ses || !server) { + if (!server) { rc =3D -EIO; goto err_free_path; } =20 + struct smb2_create_layout layout =3D { + .offset =3D sizeof(struct smb2_create_req), + .path_len =3D path_len, + .cp =3D cifs_sb->local_nls, + }; + rc =3D smb311_posix_mkdir_layout(tcon, &layout); + if (rc < 0) + goto err_free_path; + /* resource #2: request */ - rc =3D smb2_plain_req_init(SMB2_CREATE, tcon, server, - (void **) &req, &total_len); - if (rc) + rc =3D -ENOMEM; + smb =3D smb2_create_request(SMB2_CREATE, server, tcon, + sizeof(*req), layout.offset, 0, + SMB2_REQ_DYNAMIC); + if (!smb) goto err_free_path; =20 =20 if (smb3_encryption_required(tcon)) flags |=3D CIFS_TRANSFORM_REQ; =20 - req->ImpersonationLevel =3D IL_IMPERSONATION; - req->DesiredAccess =3D cpu_to_le32(FILE_WRITE_ATTRIBUTES); + req->ImpersonationLevel =3D IL_IMPERSONATION; + req->DesiredAccess =3D cpu_to_le32(FILE_WRITE_ATTRIBUTES); /* File attributes ignored on open (used in create though) */ - req->FileAttributes =3D cpu_to_le32(file_attributes); - req->ShareAccess =3D FILE_SHARE_ALL_LE; - req->CreateDisposition =3D cpu_to_le32(FILE_CREATE); - req->CreateOptions =3D cpu_to_le32(CREATE_NOT_FILE); - - iov[0].iov_base =3D (char *)req; - /* -1 since last byte is buf[0] which is sent below (path) */ - iov[0].iov_len =3D total_len - 1; - - req->NameOffset =3D cpu_to_le16(sizeof(struct smb2_create_req)); + req->FileAttributes =3D cpu_to_le32(file_attributes); + req->ShareAccess =3D FILE_SHARE_ALL_LE; + req->CreateDisposition =3D cpu_to_le32(FILE_CREATE); + req->CreateOptions =3D cpu_to_le32(CREATE_NOT_FILE); + req->NameOffset =3D cpu_to_le16(layout.name_offset); + req->NameLength =3D cpu_to_le16(layout.name_len); + req->RequestedOplockLevel =3D SMB2_OPLOCK_LEVEL_NONE; + req->CreateContextsOffset =3D cpu_to_le32(layout.contexts_offset); + req->CreateContextsLength =3D cpu_to_le32(layout.contexts_len); =20 /* [MS-SMB2] 2.2.13 NameOffset: * If SMB2_FLAGS_DFS_OPERATIONS is set in the Flags field of @@ -2981,78 +3046,48 @@ int smb311_posix_mkdir(const unsigned int xid, stru= ct inode *inode, * the share that is identified by the TreeId in the SMB2 * header. */ + __le16 *name =3D smb->request + layout.name_offset; + if (tcon->share_flags & SHI1005_FLAGS_DFS) { - int name_len; + int tmp; =20 req->hdr.Flags |=3D SMB2_FLAGS_DFS_OPERATIONS; - rc =3D alloc_path_with_tree_prefix(©_path, ©_size, - &name_len, - tcon->tree_name, utf16_path); - if (rc) - goto err_free_req; =20 - req->NameLength =3D cpu_to_le16(name_len * 2); - uni_path_len =3D copy_size; - /* free before overwriting resource */ - kfree(utf16_path); - utf16_path =3D copy_path; - } else { - uni_path_len =3D (2 * UniStrnlen((wchar_t *)utf16_path, PATH_MAX)) + 2; - /* MUST set path len (NameLength) to 0 opening root of share */ - req->NameLength =3D cpu_to_le16(uni_path_len - 2); - if (uni_path_len % 8 !=3D 0) { - copy_size =3D roundup(uni_path_len, 8); - copy_path =3D kzalloc(copy_size, GFP_KERNEL); - if (!copy_path) { - rc =3D -ENOMEM; - goto err_free_req; - } - memcpy((char *)copy_path, (const char *)utf16_path, - uni_path_len); - uni_path_len =3D copy_size; - /* free before overwriting resource */ - kfree(utf16_path); - utf16_path =3D copy_path; + tmp =3D cifs_strtoUTF16(name, tcon->tree_name + 2, INT_MAX, + layout.cp); + WARN_ON(tmp !=3D layout.treename_len); + name +=3D tmp; + if (layout.path_len) { + *name++ =3D cpu_to_le16('\\'); + memcpy(name, utf16_path, layout.path_len); } + } else { + memcpy(name, utf16_path, layout.path_len); } =20 - iov[1].iov_len =3D uni_path_len; - iov[1].iov_base =3D utf16_path; - req->RequestedOplockLevel =3D SMB2_OPLOCK_LEVEL_NONE; + if (layout.name_pad) + memset(smb->request + layout.name_offset + layout.name_len, + 0, layout.name_pad); =20 - if (tcon->posix_extensions) { + if (tcon->posix_extensions) /* resource #3: posix buf */ - rc =3D add_posix_context(iov, &n_iov, mode); - if (rc) - goto err_free_req; - req->CreateContextsOffset =3D cpu_to_le32( - sizeof(struct smb2_create_req) + - iov[1].iov_len); - le32_add_cpu(&req->CreateContextsLength, iov[n_iov-1].iov_len); - pc_buf =3D iov[n_iov-1].iov_base; - } - - - memset(&rqst, 0, sizeof(struct smb_rqst)); - rqst.rq_iov =3D iov; - rqst.rq_nvec =3D n_iov; + fill_posix_buf(smb->request + layout.posix_offset, mode); =20 /* no need to inc num_remote_opens because we close it just below */ trace_smb3_posix_mkdir_enter(xid, tcon->tid, ses->Suid, full_path, CREATE= _NOT_FILE, FILE_WRITE_ATTRIBUTES); =20 if (retries) - smb2_set_replay(server, &rqst); + smb2_set_replay_smb(server, smb); =20 /* resource #4: response buffer */ - rc =3D cifs_send_recv(xid, ses, server, - &rqst, &resp_buftype, flags, &rsp_iov); + rc =3D smb_send_recv_messages(xid, ses, server, smb, flags); if (rc) { cifs_stats_fail_inc(tcon, SMB2_CREATE); trace_smb3_posix_mkdir_err(xid, tcon->tid, ses->Suid, CREATE_NOT_FILE, FILE_WRITE_ATTRIBUTES, rc); - goto err_free_rsp_buf; + goto err_free_req; } =20 /* @@ -3060,10 +3095,9 @@ int smb311_posix_mkdir(const unsigned int xid, struc= t inode *inode, * adding check below is slightly safer long term (and quiets Coverity * warning) */ - rsp =3D (struct smb2_create_rsp *)rsp_iov.iov_base; + rsp =3D (struct smb2_create_rsp *)smb->response; if (rsp =3D=3D NULL) { rc =3D -EIO; - kfree(pc_buf); goto err_free_req; } =20 @@ -3074,18 +3108,14 @@ int smb311_posix_mkdir(const unsigned int xid, stru= ct inode *inode, =20 /* Eventually save off posix specific response info and timestamps */ =20 -err_free_rsp_buf: - free_rsp_buf(resp_buftype, rsp_iov.iov_base); - kfree(pc_buf); err_free_req: - cifs_small_buf_release(req); + smb_put_messages(smb); err_free_path: - kfree(utf16_path); - if (is_replayable_error(rc) && smb2_should_replay(tcon, &retries, &cur_sleep)) goto replay_again; =20 + kfree(utf16_path); return rc; } From nobody Thu Dec 18 03:20:29 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 05FE92D542A for ; Wed, 6 Aug 2025 20:39:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512800; cv=none; b=GAUzWtRrk6mNutZwXOtC1xk7BXXXjwpKg5kog+JVhlN2KVCwMGjtBKS4D7ajEydiZNOdCdxIWlS4BSBgz8ZsirKZIWCFidB9bcRulzADzUBli3Zrz33X7tzzxN/1PvV+DbXjn0ecN0wSzXacErxp+YnWvEj/tg+0/fl8fC5ObnM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754512800; c=relaxed/simple; bh=Gghf6k/fnry+2WFWCe6fJYxjAU0qFTZeucHXPfX09aw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=T+SlXZ/j1vwB9Jzuvhq4DnoTM8NPDDF6oYQQobXRfnlOaNXejV7BdeBUg14f6yY9TCAFEwxbdWf0e4WnZoeI3sCfrhrwQaik/i68ovjlYbb3GRgcB/Q5SZKdmqGcyTpgOAu9O4K3pKiNPrBWDY7NzLpax0BSmF691mj3MBvhHQk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=HavLCzNI; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="HavLCzNI" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1754512796; h=from:from:reply-to:subject:subject: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=dmhepafm0TOsow0EGo0RSETMNdoSQ3DnpqhK9FsEIx8=; b=HavLCzNIOwku0ZC+QSUyioqve82+esIzz4d+Inom7WkHjtx/+FE5nrDTjZC+zwr4ky+4lO kF/agCScuZJSYdagbxfiGUBVDWPDySkp6WAbWLg7XZ7LcwMGaph18QHqQLJPMc/69S80J2 xGk9fi00IM63KUvr1k2mG/uq6Red8a4= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-635-sBmFLl4uNSSSd-fvQyqKsg-1; Wed, 06 Aug 2025 16:39:52 -0400 X-MC-Unique: sBmFLl4uNSSSd-fvQyqKsg-1 X-Mimecast-MFC-AGG-ID: sBmFLl4uNSSSd-fvQyqKsg_1754512784 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 5DCDF180035B; Wed, 6 Aug 2025 20:39:44 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.17]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id CDE681956086; Wed, 6 Aug 2025 20:39:40 +0000 (UTC) From: David Howells To: Steve French Cc: David Howells , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Wang Zhaolong , Stefan Metzmacher , Mina Almasry , linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org, netfs@lists.linux.dev, linux-fsdevel@vger.kernel.org Subject: [RFC PATCH 31/31] cifs: Convert SMB2 Open request Date: Wed, 6 Aug 2025 21:36:52 +0100 Message-ID: <20250806203705.2560493-32-dhowells@redhat.com> In-Reply-To: <20250806203705.2560493-1-dhowells@redhat.com> References: <20250806203705.2560493-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Content-Type: text/plain; charset="utf-8" Signed-off-by: David Howells cc: Steve French cc: Paulo Alcantara cc: Shyam Prasad N cc: Tom Talpey cc: linux-cifs@vger.kernel.org cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/smb/client/cached_dir.c | 41 +- fs/smb/client/cifsglob.h | 5 +- fs/smb/client/smb2inode.c | 6 +- fs/smb/client/smb2ops.c | 34 +- fs/smb/client/smb2pdu.c | 877 +++++++++++++++---------------------- fs/smb/client/smb2proto.h | 29 +- 6 files changed, 399 insertions(+), 593 deletions(-) diff --git a/fs/smb/client/cached_dir.c b/fs/smb/client/cached_dir.c index 368e870624da..e4534f6b31da 100644 --- a/fs/smb/client/cached_dir.c +++ b/fs/smb/client/cached_dir.c @@ -141,9 +141,7 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon = *tcon, struct cifs_open_parms oparms; struct smb2_create_rsp *o_rsp =3D NULL; struct smb2_query_info_rsp *qi_rsp =3D NULL; - int resp_buftype[2]; - struct smb_rqst rqst[2]; - struct kvec rsp_iov[2]; + struct smb_message *smb; struct kvec open_iov[SMB2_CREATE_IOV_SIZE]; struct kvec qi_iov[1]; int rc, flags =3D 0; @@ -260,29 +258,20 @@ int open_cached_dir(unsigned int xid, struct cifs_tco= n *tcon, =20 server->ops->new_lease_key(pfid); =20 - memset(rqst, 0, sizeof(rqst)); - resp_buftype[0] =3D resp_buftype[1] =3D CIFS_NO_BUFFER; - memset(rsp_iov, 0, sizeof(rsp_iov)); - /* Open */ - memset(&open_iov, 0, sizeof(open_iov)); - rqst[0].rq_iov =3D open_iov; - rqst[0].rq_nvec =3D SMB2_CREATE_IOV_SIZE; - oparms =3D (struct cifs_open_parms) { - .tcon =3D tcon, - .path =3D path, - .create_options =3D cifs_create_options(cifs_sb, CREATE_NOT_FILE), - .desired_access =3D FILE_READ_DATA | FILE_READ_ATTRIBUTES | - FILE_READ_EA, - .disposition =3D FILE_OPEN, - .fid =3D pfid, - .lease_flags =3D lease_flags, - .replay =3D !!(retries), + .tcon =3D tcon, + .path =3D path, + .create_options =3D cifs_create_options(cifs_sb, CREATE_NOT_FILE), + .desired_access =3D FILE_READ_DATA | FILE_READ_ATTRIBUTES | + FILE_READ_EA, + .disposition =3D FILE_OPEN, + .fid =3D pfid, + .lease_flags =3D lease_flags, + .replay =3D !!(retries), }; =20 - rc =3D SMB2_open_init(tcon, server, - &rqst[0], &oplock, &oparms, utf16_path); + smb =3D SMB2_open_init(tcon, server, &oplock, &oparms, utf16_path); if (rc) goto oshr_free; smb2_set_next_command(tcon, &rqst[0]); @@ -336,10 +325,10 @@ int open_cached_dir(unsigned int xid, struct cifs_tco= n *tcon, goto oshr_free; } =20 - rc =3D smb2_parse_contexts(server, rsp_iov, - &oparms.fid->epoch, - oparms.fid->lease_key, - &oplock, NULL, NULL); + rc =3D smb2_parse_create_response(server, rsp_iov, + &oparms.fid->epoch, + oparms.fid->lease_key, + &oplock, NULL, NULL); if (rc) { spin_unlock(&cfids->cfid_list_lock); goto oshr_free; diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index 0cc71f504c68..b96c45f57c2b 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h @@ -554,8 +554,9 @@ struct smb_version_operations { /* set oplock level for the inode */ void (*set_oplock_level)(struct cifsInodeInfo *cinode, __u32 oplock, __u1= 6 epoch, bool *purge_cache); - /* create lease context buffer for CREATE request */ - char * (*create_lease_buf)(u8 *lease_key, u8 oplock, u8 *parent_lease_key= , __le32 le_flags); + /* Fill in a lease context buffer for CREATE request */ + void (*fill_lease_buf)(struct smb_message *smb, const u8 *lease_key, u8 o= plock, + const u8 *parent_lease_key, __le32 le_flags); /* parse lease context buffer and return oplock/epoch info */ __u8 (*parse_lease_buf)(void *buf, __u16 *epoch, char *lkey); ssize_t (*copychunk_range)(const unsigned int, diff --git a/fs/smb/client/smb2inode.c b/fs/smb/client/smb2inode.c index 2a3e46b8e15a..c5041fa94779 100644 --- a/fs/smb/client/smb2inode.c +++ b/fs/smb/client/smb2inode.c @@ -663,9 +663,9 @@ static int smb2_compound_op(const unsigned int xid, str= uct cifs_tcon *tcon, idata->fi.DeletePending =3D 0; idata->fi.Directory =3D !!(le32_to_cpu(create_rsp->FileAttributes) & ATT= R_DIRECTORY); =20 - /* smb2_parse_contexts() fills idata->fi.IndexNumber */ - rc =3D smb2_parse_contexts(server, &rsp_iov[0], &oparms->fid->epoch, - oparms->fid->lease_key, &oplock, &idata->fi, NULL); + /* smb2_parse_create_response() fills idata->fi.IndexNumber */ + rc =3D smb2_parse_create_response(server, &rsp_iov[0], &oparms->fid->epo= ch, + oparms->fid->lease_key, &oplock, &idata->fi, NULL); if (rc) cifs_dbg(VFS, "rc: %d parsing context of compound op\n", rc); } diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c index 9db383ec22e8..7c30475054b8 100644 --- a/fs/smb/client/smb2ops.c +++ b/fs/smb/client/smb2ops.c @@ -4086,14 +4086,11 @@ map_oplock_to_lease(u8 oplock) return 0; } =20 -static char * -smb2_create_lease_buf(u8 *lease_key, u8 oplock, u8 *parent_lease_key, __le= 32 flags) +static void +smb2_fill_lease_buf(struct smb_message *smb, const u8 *lease_key, u8 oploc= k, + const u8 *parent_lease_key, __le32 flags) { - struct create_lease *buf; - - buf =3D kzalloc(sizeof(struct create_lease), GFP_KERNEL); - if (!buf) - return NULL; + struct create_lease *buf =3D cifs_begin_extension(smb); =20 memcpy(&buf->lcontext.LeaseKey, lease_key, SMB2_LEASE_KEY_SIZE); buf->lcontext.LeaseState =3D map_oplock_to_lease(oplock); @@ -4109,17 +4106,14 @@ smb2_create_lease_buf(u8 *lease_key, u8 oplock, u8 = *parent_lease_key, __le32 fla buf->Name[1] =3D 'q'; buf->Name[2] =3D 'L'; buf->Name[3] =3D 's'; - return (char *)buf; + cifs_end_extension(smb, sizeof(*buf)); } =20 -static char * -smb3_create_lease_buf(u8 *lease_key, u8 oplock, u8 *parent_lease_key, __le= 32 flags) +static void +smb3_fill_lease_buf(struct smb_message *smb, const u8 *lease_key, u8 oploc= k, + const u8 *parent_lease_key, __le32 flags) { - struct create_lease_v2 *buf; - - buf =3D kzalloc(sizeof(struct create_lease_v2), GFP_KERNEL); - if (!buf) - return NULL; + struct create_lease_v2 *buf =3D cifs_begin_extension(smb); =20 memcpy(&buf->lcontext.LeaseKey, lease_key, SMB2_LEASE_KEY_SIZE); buf->lcontext.LeaseState =3D map_oplock_to_lease(oplock); @@ -4138,7 +4132,7 @@ smb3_create_lease_buf(u8 *lease_key, u8 oplock, u8 *p= arent_lease_key, __le32 fla buf->Name[1] =3D 'q'; buf->Name[2] =3D 'L'; buf->Name[3] =3D 's'; - return (char *)buf; + cifs_end_extension(smb, sizeof(*buf)); } =20 static __u8 @@ -5263,7 +5257,7 @@ struct smb_version_operations smb20_operations =3D { .calc_signature =3D smb2_calc_signature, .is_read_op =3D smb2_is_read_op, .set_oplock_level =3D smb2_set_oplock_level, - .create_lease_buf =3D smb2_create_lease_buf, + .fill_lease_buf =3D smb2_fill_lease_buf, .parse_lease_buf =3D smb2_parse_lease_buf, .copychunk_range =3D smb2_copychunk_range, .wp_retry_size =3D smb2_wp_retry_size, @@ -5366,7 +5360,7 @@ struct smb_version_operations smb21_operations =3D { .calc_signature =3D smb2_calc_signature, .is_read_op =3D smb21_is_read_op, .set_oplock_level =3D smb21_set_oplock_level, - .create_lease_buf =3D smb2_create_lease_buf, + .fill_lease_buf =3D smb2_fill_lease_buf, .parse_lease_buf =3D smb2_parse_lease_buf, .copychunk_range =3D smb2_copychunk_range, .wp_retry_size =3D smb2_wp_retry_size, @@ -5476,7 +5470,7 @@ struct smb_version_operations smb30_operations =3D { .set_integrity =3D smb3_set_integrity, .is_read_op =3D smb21_is_read_op, .set_oplock_level =3D smb3_set_oplock_level, - .create_lease_buf =3D smb3_create_lease_buf, + .fill_lease_buf =3D smb3_fill_lease_buf, .parse_lease_buf =3D smb3_parse_lease_buf, .copychunk_range =3D smb2_copychunk_range, .duplicate_extents =3D smb2_duplicate_extents, @@ -5592,7 +5586,7 @@ struct smb_version_operations smb311_operations =3D { .set_integrity =3D smb3_set_integrity, .is_read_op =3D smb21_is_read_op, .set_oplock_level =3D smb3_set_oplock_level, - .create_lease_buf =3D smb3_create_lease_buf, + .fill_lease_buf =3D smb3_fill_lease_buf, .parse_lease_buf =3D smb3_parse_lease_buf, .copychunk_range =3D smb2_copychunk_range, .duplicate_extents =3D smb2_duplicate_extents, diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c index 9fc55b315474..e9827aeab43f 100644 --- a/fs/smb/client/smb2pdu.c +++ b/fs/smb/client/smb2pdu.c @@ -2387,298 +2387,179 @@ SMB2_tdis(const unsigned int xid, struct cifs_tco= n *tcon) return rc; } =20 - -static void fill_posix_buf(struct create_posix *buf, umode_t mode) +/* + * Begin a create context record. This fills in the chain pointer on the + * previous record if there was one. + */ +static void *cifs_begin_ccontext(struct smb_message *smb) { - buf->ccontext.DataOffset =3D - cpu_to_le16(offsetof(struct create_posix, Mode)); - buf->ccontext.DataLength =3D cpu_to_le32(4); - buf->ccontext.NameOffset =3D - cpu_to_le16(offsetof(struct create_posix, Name)); - buf->ccontext.NameLength =3D cpu_to_le16(16); + struct create_context_hdr *ccontext =3D cifs_begin_extension(smb); =20 - /* SMB2_CREATE_TAG_POSIX is "0x93AD25509CB411E7B42383DE968BCD7C" */ - buf->Name[0] =3D 0x93; - buf->Name[1] =3D 0xAD; - buf->Name[2] =3D 0x25; - buf->Name[3] =3D 0x50; - buf->Name[4] =3D 0x9C; - buf->Name[5] =3D 0xB4; - buf->Name[6] =3D 0x11; - buf->Name[7] =3D 0xE7; - buf->Name[8] =3D 0xB4; - buf->Name[9] =3D 0x23; - buf->Name[10] =3D 0x83; - buf->Name[11] =3D 0xDE; - buf->Name[12] =3D 0x96; - buf->Name[13] =3D 0x8B; - buf->Name[14] =3D 0xCD; - buf->Name[15] =3D 0x7C; - buf->Mode =3D cpu_to_le32(mode); - cifs_dbg(FYI, "mode on posix create 0%o\n", mode); + if (smb->latest_record) { + struct create_context_hdr *latest =3D smb->request + smb->latest_record; + + latest->Next =3D cpu_to_le32(smb->offset - smb->latest_record); + } + smb->latest_record =3D smb->offset; + return ccontext; } =20 -static int -add_posix_context(struct kvec *iov, unsigned int *num_iovec, umode_t mode) +#define CREATE_CONTEXT_HDR(ptr, name, data, namelen) { \ + .NameOffset =3D cpu_to_le16(offsetof(ptr, name)), \ + .NameLength =3D cpu_to_le16(namelen), \ + .DataOffset =3D cpu_to_le16(offsetof(ptr, data)), \ + .DataLength =3D cpu_to_le32(sizeof_field(ptr, data)), \ + } + +static void fill_posix_context(struct smb_message *smb, umode_t mode) { - struct create_posix *buf; - unsigned int num =3D *num_iovec; + struct create_posix *buf =3D cifs_begin_ccontext(smb); =20 if (mode =3D=3D ACL_NO_MODE) cifs_dbg(FYI, "%s: no mode\n", __func__); =20 - buf =3D kzalloc(sizeof(struct create_posix), GFP_KERNEL); - if (!buf) - return -ENOMEM; - - fill_posix_buf(buf, mode); - - iov[num].iov_base =3D buf; - iov[num].iov_len =3D sizeof(struct create_posix); - *num_iovec =3D num + 1; - return 0; + *buf =3D (struct create_posix){ + .ccontext =3D CREATE_CONTEXT_HDR(struct create_posix, Name, Mode, 16), + /* SMB2_CREATE_TAG_POSIX is "0x93AD25509CB411E7B42383DE968BCD7C" */ + .Name =3D { + 0x93, 0xAD, 0x25, 0x50, 0x9C, 0xB4, 0x11, 0xE7, + 0xB4, 0x23, 0x83, 0xDE, 0x96, 0x8B, 0xCD, 0x7C + }, + .Mode =3D cpu_to_le32(mode), + }; + cifs_dbg(FYI, "mode on posix create 0%o\n", mode); + cifs_end_extension(smb, sizeof(*buf)); } =20 -static struct create_durable * -create_durable_buf(void) +static void fill_lease_context(struct TCP_Server_Info *server, + struct smb2_create_req *req, + struct smb_message *smb, + u8 *lease_key, + __u8 *oplock, + u8 *parent_lease_key, + __le32 flags) { - struct create_durable *buf; - - buf =3D kzalloc(sizeof(struct create_durable), GFP_KERNEL); - if (!buf) - return NULL; - - buf->ccontext.DataOffset =3D cpu_to_le16(offsetof - (struct create_durable, Data)); - buf->ccontext.DataLength =3D cpu_to_le32(16); - buf->ccontext.NameOffset =3D cpu_to_le16(offsetof - (struct create_durable, Name)); - buf->ccontext.NameLength =3D cpu_to_le16(4); - /* SMB2_CREATE_DURABLE_HANDLE_REQUEST is "DHnQ" */ - buf->Name[0] =3D 'D'; - buf->Name[1] =3D 'H'; - buf->Name[2] =3D 'n'; - buf->Name[3] =3D 'Q'; - return buf; + req->RequestedOplockLevel =3D SMB2_OPLOCK_LEVEL_LEASE; + server->ops->fill_lease_buf(smb, lease_key, *oplock, + parent_lease_key, flags); } =20 -static struct create_durable * -create_reconnect_durable_buf(struct cifs_fid *fid) +static void fill_durable_v1_context(struct smb_message *smb) { - struct create_durable *buf; + struct create_durable *buf =3D cifs_begin_ccontext(smb); =20 - buf =3D kzalloc(sizeof(struct create_durable), GFP_KERNEL); - if (!buf) - return NULL; - - buf->ccontext.DataOffset =3D cpu_to_le16(offsetof - (struct create_durable, Data)); - buf->ccontext.DataLength =3D cpu_to_le32(16); - buf->ccontext.NameOffset =3D cpu_to_le16(offsetof - (struct create_durable, Name)); - buf->ccontext.NameLength =3D cpu_to_le16(4); - buf->Data.Fid.PersistentFileId =3D fid->persistent_fid; - buf->Data.Fid.VolatileFileId =3D fid->volatile_fid; - /* SMB2_CREATE_DURABLE_HANDLE_RECONNECT is "DHnC" */ - buf->Name[0] =3D 'D'; - buf->Name[1] =3D 'H'; - buf->Name[2] =3D 'n'; - buf->Name[3] =3D 'C'; - return buf; + *buf =3D (struct create_durable){ + .ccontext =3D CREATE_CONTEXT_HDR(struct create_durable, Name, Data, 4), + /* SMB2_CREATE_DURABLE_HANDLE_REQUEST is "DHnQ" */ + .Name =3D {'D', 'H', 'n', 'Q' }, + }; + cifs_end_extension(smb, sizeof(*buf)); } =20 -static int -add_lease_context(struct TCP_Server_Info *server, - struct smb2_create_req *req, - struct kvec *iov, - unsigned int *num_iovec, - u8 *lease_key, - __u8 *oplock, - u8 *parent_lease_key, - __le32 flags) +static void fill_reconnect_durable_context(struct smb_message *smb, + struct cifs_open_parms *oparms) { - unsigned int num =3D *num_iovec; + struct create_durable *buf =3D cifs_begin_ccontext(smb); + struct cifs_fid *fid =3D oparms->fid; =20 - iov[num].iov_base =3D server->ops->create_lease_buf(lease_key, *oplock, - parent_lease_key, flags); - if (iov[num].iov_base =3D=3D NULL) - return -ENOMEM; - iov[num].iov_len =3D server->vals->create_lease_size; - req->RequestedOplockLevel =3D SMB2_OPLOCK_LEVEL_LEASE; - *num_iovec =3D num + 1; - return 0; + /* indicate that we don't need to relock the file */ + oparms->reconnect =3D false; + + *buf =3D (struct create_durable){ + .ccontext =3D CREATE_CONTEXT_HDR(struct create_durable, Name, Data, 4), + /* SMB2_CREATE_DURABLE_HANDLE_RECONNECT is "DHnC" */ + .Name =3D {'D', 'H', 'n', 'C' }, + .Data.Fid.PersistentFileId =3D fid->persistent_fid, + .Data.Fid.VolatileFileId =3D fid->volatile_fid, + }; + cifs_end_extension(smb, sizeof(*buf)); } =20 -static struct create_durable_v2 * -create_durable_v2_buf(struct cifs_open_parms *oparms) +static void fill_durable_v2_context(struct smb_message *smb, + struct cifs_open_parms *oparms) { - struct cifs_fid *pfid =3D oparms->fid; - struct create_durable_v2 *buf; + struct create_durable_v2 *buf =3D cifs_begin_ccontext(smb); + struct cifs_fid *fid =3D oparms->fid; =20 - buf =3D kzalloc(sizeof(struct create_durable_v2), GFP_KERNEL); - if (!buf) - return NULL; + *buf =3D (struct create_durable_v2){ + .ccontext =3D CREATE_CONTEXT_HDR(struct create_durable_v2, Name, dcontex= t, 4), + /* SMB2_CREATE_DURABLE_HANDLE_REQUEST is "DH2Q" */ + .Name =3D {'D', 'H', '2', 'Q' }, =20 - buf->ccontext.DataOffset =3D cpu_to_le16(offsetof - (struct create_durable_v2, dcontext)); - buf->ccontext.DataLength =3D cpu_to_le32(sizeof(struct durable_context_v2= )); - buf->ccontext.NameOffset =3D cpu_to_le16(offsetof - (struct create_durable_v2, Name)); - buf->ccontext.NameLength =3D cpu_to_le16(4); - - /* - * NB: Handle timeout defaults to 0, which allows server to choose - * (most servers default to 120 seconds) and most clients default to 0. - * This can be overridden at mount ("handletimeout=3D") if the user wants - * a different persistent (or resilient) handle timeout for all opens - * on a particular SMB3 mount. - */ - buf->dcontext.Timeout =3D cpu_to_le32(oparms->tcon->handle_timeout); - buf->dcontext.Flags =3D cpu_to_le32(SMB2_DHANDLE_FLAG_PERSISTENT); + /* + * NB: Handle timeout defaults to 0, which allows server to + * choose (most servers default to 120 seconds) and most + * clients default to 0. This can be overridden at mount + * ("handletimeout=3D") if the user wants a different persistent + * (or resilient) handle timeout for all opens on a particular + * SMB3 mount. + */ + .dcontext.Timeout =3D cpu_to_le32(oparms->tcon->handle_timeout), + .dcontext.Flags =3D cpu_to_le32(SMB2_DHANDLE_FLAG_PERSISTENT), + }; =20 /* for replay, we should not overwrite the existing create guid */ if (!oparms->replay) { generate_random_uuid(buf->dcontext.CreateGuid); - memcpy(pfid->create_guid, buf->dcontext.CreateGuid, 16); - } else - memcpy(buf->dcontext.CreateGuid, pfid->create_guid, 16); - - /* SMB2_CREATE_DURABLE_HANDLE_REQUEST is "DH2Q" */ - buf->Name[0] =3D 'D'; - buf->Name[1] =3D 'H'; - buf->Name[2] =3D '2'; - buf->Name[3] =3D 'Q'; - return buf; -} - -static struct create_durable_handle_reconnect_v2 * -create_reconnect_durable_v2_buf(struct cifs_fid *fid) -{ - struct create_durable_handle_reconnect_v2 *buf; - - buf =3D kzalloc(sizeof(struct create_durable_handle_reconnect_v2), - GFP_KERNEL); - if (!buf) - return NULL; - - buf->ccontext.DataOffset =3D - cpu_to_le16(offsetof(struct create_durable_handle_reconnect_v2, - dcontext)); - buf->ccontext.DataLength =3D - cpu_to_le32(sizeof(struct durable_reconnect_context_v2)); - buf->ccontext.NameOffset =3D - cpu_to_le16(offsetof(struct create_durable_handle_reconnect_v2, - Name)); - buf->ccontext.NameLength =3D cpu_to_le16(4); - - buf->dcontext.Fid.PersistentFileId =3D fid->persistent_fid; - buf->dcontext.Fid.VolatileFileId =3D fid->volatile_fid; - buf->dcontext.Flags =3D cpu_to_le32(SMB2_DHANDLE_FLAG_PERSISTENT); - memcpy(buf->dcontext.CreateGuid, fid->create_guid, 16); - - /* SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 is "DH2C" */ - buf->Name[0] =3D 'D'; - buf->Name[1] =3D 'H'; - buf->Name[2] =3D '2'; - buf->Name[3] =3D 'C'; - return buf; -} - -static int -add_durable_v2_context(struct kvec *iov, unsigned int *num_iovec, - struct cifs_open_parms *oparms) -{ - unsigned int num =3D *num_iovec; + memcpy(fid->create_guid, buf->dcontext.CreateGuid, 16); + } else { + memcpy(buf->dcontext.CreateGuid, fid->create_guid, 16); + } =20 - iov[num].iov_base =3D create_durable_v2_buf(oparms); - if (iov[num].iov_base =3D=3D NULL) - return -ENOMEM; - iov[num].iov_len =3D sizeof(struct create_durable_v2); - *num_iovec =3D num + 1; - return 0; + cifs_end_extension(smb, sizeof(*buf)); } =20 -static int -add_durable_reconnect_v2_context(struct kvec *iov, unsigned int *num_iovec, - struct cifs_open_parms *oparms) +static void fill_durable_reconnect_v2_context(struct smb_message *smb, + struct cifs_open_parms *oparms) { - unsigned int num =3D *num_iovec; + struct create_durable_handle_reconnect_v2 *buf =3D cifs_begin_ccontext(sm= b); + struct cifs_fid *fid =3D oparms->fid; =20 /* indicate that we don't need to relock the file */ oparms->reconnect =3D false; =20 - iov[num].iov_base =3D create_reconnect_durable_v2_buf(oparms->fid); - if (iov[num].iov_base =3D=3D NULL) - return -ENOMEM; - iov[num].iov_len =3D sizeof(struct create_durable_handle_reconnect_v2); - *num_iovec =3D num + 1; - return 0; + *buf =3D (struct create_durable_handle_reconnect_v2){ + .ccontext =3D CREATE_CONTEXT_HDR(struct create_durable_handle_reconnect_= v2, + Name, dcontext, 4), + /* SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 is "DH2C" */ + .Name =3D {'D', 'H', '2', 'C' }, + .dcontext.Fid.PersistentFileId =3D fid->persistent_fid, + .dcontext.Fid.VolatileFileId =3D fid->volatile_fid, + .dcontext.Flags =3D cpu_to_le32(SMB2_DHANDLE_FLAG_PERSISTENT), + }; + + memcpy(buf->dcontext.CreateGuid, fid->create_guid, 16); + cifs_end_extension(smb, sizeof(*buf)); } =20 -static int -add_durable_context(struct kvec *iov, unsigned int *num_iovec, - struct cifs_open_parms *oparms, bool use_persistent) +static void +fill_durable_context(struct smb_message *smb, + struct cifs_open_parms *oparms, bool use_persistent) { - unsigned int num =3D *num_iovec; - if (use_persistent) { if (oparms->reconnect) - return add_durable_reconnect_v2_context(iov, num_iovec, - oparms); - else - return add_durable_v2_context(iov, num_iovec, oparms); + return fill_durable_reconnect_v2_context(smb, oparms); + return fill_durable_v2_context(smb, oparms); } =20 - if (oparms->reconnect) { - iov[num].iov_base =3D create_reconnect_durable_buf(oparms->fid); - /* indicate that we don't need to relock the file */ - oparms->reconnect =3D false; - } else - iov[num].iov_base =3D create_durable_buf(); - if (iov[num].iov_base =3D=3D NULL) - return -ENOMEM; - iov[num].iov_len =3D sizeof(struct create_durable); - *num_iovec =3D num + 1; - return 0; + if (oparms->reconnect) + return fill_reconnect_durable_context(smb, oparms); + return fill_durable_v1_context(smb); } =20 /* See MS-SMB2 2.2.13.2.7 */ -static struct crt_twarp_ctxt * -create_twarp_buf(__u64 timewarp) +static void fill_twarp_context(struct smb_message *smb, __u64 timewarp) { - struct crt_twarp_ctxt *buf; - - buf =3D kzalloc(sizeof(struct crt_twarp_ctxt), GFP_KERNEL); - if (!buf) - return NULL; - - buf->ccontext.DataOffset =3D cpu_to_le16(offsetof - (struct crt_twarp_ctxt, Timestamp)); - buf->ccontext.DataLength =3D cpu_to_le32(8); - buf->ccontext.NameOffset =3D cpu_to_le16(offsetof - (struct crt_twarp_ctxt, Name)); - buf->ccontext.NameLength =3D cpu_to_le16(4); - /* SMB2_CREATE_TIMEWARP_TOKEN is "TWrp" */ - buf->Name[0] =3D 'T'; - buf->Name[1] =3D 'W'; - buf->Name[2] =3D 'r'; - buf->Name[3] =3D 'p'; - buf->Timestamp =3D cpu_to_le64(timewarp); - return buf; -} + struct crt_twarp_ctxt *buf =3D cifs_begin_ccontext(smb); =20 -/* See MS-SMB2 2.2.13.2.7 */ -static int -add_twarp_context(struct kvec *iov, unsigned int *num_iovec, __u64 timewar= p) -{ - unsigned int num =3D *num_iovec; + *buf =3D (struct crt_twarp_ctxt){ + .ccontext =3D CREATE_CONTEXT_HDR(struct crt_twarp_ctxt, Name, Timestamp,= 4), + /* SMB2_CREATE_TIMEWARP_TOKEN is "TWrp" */ + .Name =3D {'T', 'W', 'r', 'p' }, + .Timestamp =3D cpu_to_le64(timewarp), + }; =20 - iov[num].iov_base =3D create_twarp_buf(timewarp); - if (iov[num].iov_base =3D=3D NULL) - return -ENOMEM; - iov[num].iov_len =3D sizeof(struct crt_twarp_ctxt); - *num_iovec =3D num + 1; - return 0; + cifs_end_extension(smb, sizeof(*buf)); } =20 /* See http://technet.microsoft.com/en-us/library/hh509017(v=3Dws.10).aspx= */ @@ -2706,26 +2587,21 @@ static void setup_owner_group_sids(char *buf) } =20 /* See MS-SMB2 2.2.13.2.2 and MS-DTYP 2.4.6 */ -static struct crt_sd_ctxt * -create_sd_buf(umode_t mode, bool set_owner, unsigned int *len) +static void fill_sd_context(struct smb_message *smb, umode_t mode, bool se= t_owner) { - struct crt_sd_ctxt *buf; + struct crt_sd_ctxt *buf =3D cifs_begin_extension(smb); __u8 *ptr, *aclptr; unsigned int acelen, acl_size, ace_count; unsigned int owner_offset =3D 0; unsigned int group_offset =3D 0; + unsigned int len; struct smb3_acl acl =3D {}; =20 - *len =3D ALIGN8(sizeof(struct crt_sd_ctxt) + (sizeof(struct smb_ace) * 4)= ); + len =3D ALIGN8(sizeof(struct crt_sd_ctxt) + (sizeof(struct smb_ace) * 4)); =20 - if (set_owner) { + if (set_owner) /* sizeof(struct owner_group_sids) is already multiple of 8 so no need t= o round */ - *len +=3D sizeof(struct owner_group_sids); - } - - buf =3D kzalloc(*len, GFP_KERNEL); - if (buf =3D=3D NULL) - return buf; + len +=3D sizeof(struct owner_group_sids); =20 ptr =3D (__u8 *)&buf[1]; if (set_owner) { @@ -2791,33 +2667,15 @@ create_sd_buf(umode_t mode, bool set_owner, unsigne= d int *len) memcpy(aclptr, &acl, sizeof(struct smb3_acl)); =20 buf->ccontext.DataLength =3D cpu_to_le32(ptr - (__u8 *)&buf->sd); - *len =3D ALIGN8((unsigned int)(ptr - (__u8 *)buf)); - - return buf; -} - -static int -add_sd_context(struct kvec *iov, unsigned int *num_iovec, umode_t mode, bo= ol set_owner) -{ - unsigned int num =3D *num_iovec; - unsigned int len =3D 0; - - iov[num].iov_base =3D create_sd_buf(mode, set_owner, &len); - if (iov[num].iov_base =3D=3D NULL) - return -ENOMEM; - iov[num].iov_len =3D len; - *num_iovec =3D num + 1; - return 0; + len =3D ALIGN8((unsigned int)(ptr - (__u8 *)buf)); + cifs_end_extension(smb, len); + cifs_pad_to_8(smb); } =20 -static struct crt_query_id_ctxt * -create_query_id_buf(void) +/* See MS-SMB2 2.2.13.2.9 */ +static void fill_query_id_context(struct smb_message *smb) { - struct crt_query_id_ctxt *buf; - - buf =3D kzalloc(sizeof(struct crt_query_id_ctxt), GFP_KERNEL); - if (!buf) - return NULL; + struct crt_query_id_ctxt *buf =3D cifs_begin_extension(smb); =20 buf->ccontext.DataOffset =3D cpu_to_le16(0); buf->ccontext.DataLength =3D cpu_to_le32(0); @@ -2829,78 +2687,19 @@ create_query_id_buf(void) buf->Name[1] =3D 'F'; buf->Name[2] =3D 'i'; buf->Name[3] =3D 'd'; - return buf; -} - -/* See MS-SMB2 2.2.13.2.9 */ -static int -add_query_id_context(struct kvec *iov, unsigned int *num_iovec) -{ - unsigned int num =3D *num_iovec; - - iov[num].iov_base =3D create_query_id_buf(); - if (iov[num].iov_base =3D=3D NULL) - return -ENOMEM; - iov[num].iov_len =3D sizeof(struct crt_query_id_ctxt); - *num_iovec =3D num + 1; - return 0; + cifs_end_extension(smb, sizeof(*buf)); } =20 -static void add_ea_context(struct cifs_open_parms *oparms, - struct kvec *rq_iov, unsigned int *num_iovs) +static void fill_ea_context(struct smb_message *smb, const struct cifs_ope= n_parms *oparms) { - struct kvec *iov =3D oparms->ea_cctx; + const struct kvec *iov =3D oparms->ea_cctx; =20 if (iov && iov->iov_base && iov->iov_len) { - rq_iov[(*num_iovs)++] =3D *iov; - memset(iov, 0, sizeof(*iov)); - } -} - -static int -alloc_path_with_tree_prefix(__le16 **out_path, int *out_size, int *out_len, - const char *treename, const __le16 *path) -{ - int treename_len, path_len; - struct nls_table *cp; - const __le16 sep[] =3D {cpu_to_le16('\\'), cpu_to_le16(0x0000)}; + void *p =3D cifs_begin_extension(smb); =20 - /* - * skip leading "\\" - */ - treename_len =3D strlen(treename); - if (treename_len < 2 || !(treename[0] =3D=3D '\\' && treename[1] =3D=3D '= \\')) - return -EINVAL; - - treename +=3D 2; - treename_len -=3D 2; - - path_len =3D UniStrnlen((wchar_t *)path, PATH_MAX); - - /* make room for one path separator only if @path isn't empty */ - *out_len =3D treename_len + (path[0] ? 1 : 0) + path_len; - - /* - * final path needs to be 8-byte aligned as specified in - * MS-SMB2 2.2.13 SMB2 CREATE Request. - */ - *out_size =3D ALIGN8(*out_len * sizeof(__le16)); - *out_path =3D kzalloc(*out_size + sizeof(__le16) /* null */, GFP_KERNEL); - if (!*out_path) - return -ENOMEM; - - cp =3D load_nls_default(); - cifs_strtoUTF16(*out_path, treename, treename_len, cp); - - /* Do not append the separator if the path is empty */ - if (path[0] !=3D cpu_to_le16(0x0000)) { - UniStrcat((wchar_t *)*out_path, (wchar_t *)sep); - UniStrcat((wchar_t *)*out_path, (wchar_t *)path); + memcpy(p, iov->iov_base, iov->iov_len); + cifs_end_extension(smb, iov->iov_len); } - - unload_nls(cp); - - return 0; } =20 struct smb2_create_layout { @@ -2912,7 +2711,6 @@ struct smb2_create_layout { u16 name_offset; /* Offset in message of name */ u16 contexts_offset; /* Offset in message contexts */ u16 contexts_len; /* Length of contexts (or 0) */ - u16 posix_offset; /* Offset in message of posix context */ u8 name_pad; /* Amount of name padding needed */ }; =20 @@ -2920,8 +2718,6 @@ static int smb311_posix_mkdir_layout(struct cifs_tcon= *tcon, struct smb2_create_layout *lay) { size_t offset =3D lay->offset; - size_t tmp; - bool has_contexts =3D false; =20 /* [MS-SMB2] 2.2.13 NameOffset: If SMB2_FLAGS_DFS_OPERATIONS * is set in the Flags field of the SMB2 header, the file name @@ -2950,22 +2746,17 @@ static int smb311_posix_mkdir_layout(struct cifs_tc= on *tcon, } =20 offset +=3D lay->name_len; - tmp =3D offset; - offset =3D ALIGN8(offset); - lay->name_pad =3D offset - tmp; + offset =3D ALIGN(offset, 8); lay->contexts_offset =3D offset; =20 - if (tcon->posix_extensions) { + if (tcon->posix_extensions) /* resource #3: posix buf */ offset +=3D sizeof(struct create_posix); - has_contexts =3D true; - } =20 - if (has_contexts) - lay->contexts_len =3D offset - lay->contexts_offset; + if (offset =3D=3D lay->contexts_offset) + lay->contexts_offset =3D 0; /* None */ else - lay->contexts_offset =3D 0; - + lay->contexts_len =3D offset - lay->contexts_offset; lay->offset =3D offset; return 0; } @@ -3065,13 +2856,12 @@ int smb311_posix_mkdir(const unsigned int xid, stru= ct inode *inode, memcpy(name, utf16_path, layout.path_len); } =20 - if (layout.name_pad) - memset(smb->request + layout.name_offset + layout.name_len, - 0, layout.name_pad); + smb->offset =3D layout.name_offset + layout.name_len; + cifs_pad_to_8(smb); =20 if (tcon->posix_extensions) /* resource #3: posix buf */ - fill_posix_buf(smb->request + layout.posix_offset, mode); + fill_posix_context(smb, mode); =20 /* no need to inc num_remote_opens because we close it just below */ trace_smb3_posix_mkdir_enter(xid, tcon->tid, ses->Suid, full_path, CREATE= _NOT_FILE, @@ -3119,81 +2909,185 @@ int smb311_posix_mkdir(const unsigned int xid, str= uct inode *inode, return rc; } =20 -int -SMB2_open_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server, - struct smb_rqst *rqst, __u8 *oplock, - struct cifs_open_parms *oparms, __le16 *path) +/* + * Calculate the request size and layout for an "open" (i.e. Create) reque= st. + */ +static int smb2_lay_out_open(const struct cifs_tcon *tcon, + const struct TCP_Server_Info *server, + __u8 oplock, + const struct cifs_open_parms *oparms, + struct smb2_create_layout *lay) +{ + size_t offset =3D lay->offset, csize, tmp; + + /* [MS-SMB2] 2.2.13 NameOffset: If SMB2_FLAGS_DFS_OPERATIONS + * is set in the Flags field of the SMB2 header, the file name + * includes a prefix that will be processed during DFS name + * normalization as specified in section 3.3.5.9. Otherwise, + * the file name is relative to the share that is identified + * by the TreeId in the SMB2 header. + */ + lay->name_offset =3D offset; + if (tcon->share_flags & SHI1005_FLAGS_DFS) { + const char *treename =3D tcon->tree_name; + int treename_len; + + /* skip leading "\\" */ + if (!(treename[0] =3D=3D '\\' && treename[1] =3D=3D '\\')) + return -EINVAL; + + treename_len =3D cifs_size_strtoUTF16(treename + 2, INT_MAX, lay->cp); + + lay->treename_len =3D treename_len; + lay->name_len =3D treename_len; + if (lay->path_len) + lay->name_len +=3D 2 + lay->path_len; + } else { + lay->name_len =3D lay->path_len; + } + + offset +=3D lay->name_len; + tmp =3D offset; + offset =3D round_up(offset, 8); + lay->name_pad =3D offset - tmp; + lay->contexts_offset =3D offset; + + /* TODO: This bit of code is very suspicious. */ + if (!(server->capabilities & SMB2_GLOBAL_CAP_LEASING) || + oplock =3D=3D SMB2_OPLOCK_LEVEL_NONE) + ; + else if (!(server->capabilities & SMB2_GLOBAL_CAP_DIRECTORY_LEASING) && + (oparms->create_options & CREATE_NOT_FILE)) + ; /* no srv lease support */ + else + offset =3D ALIGN(offset, 8) + server->vals->create_lease_size; + + if (oplock =3D=3D SMB2_OPLOCK_LEVEL_BATCH) { + if (!tcon->use_persistent) + csize =3D sizeof(struct create_durable); + else if (oparms->reconnect) + csize =3D sizeof(struct create_durable_handle_reconnect_v2); + else + csize =3D sizeof(struct create_durable_v2); + offset =3D ALIGN(offset, 8) + csize; + } + + if (tcon->posix_extensions) + offset =3D ALIGN(offset, 8) + sizeof(struct create_posix); + if (tcon->snapshot_time) + offset =3D ALIGN(offset, 8) + sizeof(struct crt_twarp_ctxt); + + if (oparms->disposition !=3D FILE_OPEN && oparms->cifs_sb) { + bool set_mode; + bool set_owner; + + set_mode =3D (oparms->cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID= ) && + (oparms->mode !=3D ACL_NO_MODE); + + set_owner =3D oparms->cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL; + + if (set_owner || set_mode) { + csize =3D sizeof(struct crt_sd_ctxt) + sizeof(struct smb_ace) * 4; + csize =3D round_up(csize, 8); + + if (set_owner) { + /* sizeof(struct owner_group_sids) is already + * multiple of 8 so no need to round */ + csize +=3D sizeof(struct owner_group_sids); + } + } + offset =3D ALIGN(offset, 8) + csize; + } + + offset =3D ALIGN(offset, 8) + sizeof(struct crt_query_id_ctxt); + + /* TODO: Pass down the desired EA list and render directly into the buffe= r. */ + if (oparms->ea_cctx->iov_base && oparms->ea_cctx->iov_len) + offset =3D ALIGN(offset, 8) + oparms->ea_cctx->iov_len; + + if (tcon->posix_extensions) + offset =3D ALIGN(offset, 8) + sizeof(struct create_posix); + + lay->contexts_len =3D offset - lay->contexts_offset; + lay->offset =3D offset; + return 0; +} + +struct smb_message *SMB2_open_init(struct cifs_tcon *tcon, + struct TCP_Server_Info *server, __u8 *oplock, + struct cifs_open_parms *oparms, __le16 *path) { struct smb2_create_req *req; - unsigned int n_iov =3D 2; + struct smb_message *smb; __u32 file_attributes =3D 0; - int copy_size; - int uni_path_len; - unsigned int total_len; - struct kvec *iov =3D rqst->rq_iov; - __le16 *copy_path; int rc; =20 - rc =3D smb2_plain_req_init(SMB2_CREATE, tcon, server, - (void **) &req, &total_len); - if (rc) - return rc; + if (!server->oplocks || tcon->no_lease) + *oplock =3D SMB2_OPLOCK_LEVEL_NONE; =20 - iov[0].iov_base =3D (char *)req; - /* -1 since last byte is buf[0] which is sent below (path) */ - iov[0].iov_len =3D total_len - 1; + struct smb2_create_layout layout =3D { + .cp =3D oparms->cifs_sb->local_nls, + .offset =3D sizeof(struct smb2_create_req), + .path_len =3D UniStrnlen((wchar_t *)path, PATH_MAX) * 2, + }; + + rc =3D smb2_lay_out_open(tcon, server, *oplock, oparms, &layout); + if (rc < 0) + return ERR_PTR(rc); + + smb =3D smb2_create_request(SMB2_CREATE, server, tcon, + sizeof(*req), layout.offset, 0, + SMB2_REQ_DYNAMIC); + if (!smb) + return ERR_PTR(-ENOMEM); =20 if (oparms->create_options & CREATE_OPTION_READONLY) file_attributes |=3D ATTR_READONLY; if (oparms->create_options & CREATE_OPTION_SPECIAL) file_attributes |=3D ATTR_SYSTEM; =20 - req->ImpersonationLevel =3D IL_IMPERSONATION; - req->DesiredAccess =3D cpu_to_le32(oparms->desired_access); + req->ImpersonationLevel =3D IL_IMPERSONATION; + req->DesiredAccess =3D cpu_to_le32(oparms->desired_access); /* File attributes ignored on open (used in create though) */ - req->FileAttributes =3D cpu_to_le32(file_attributes); - req->ShareAccess =3D FILE_SHARE_ALL_LE; - - req->CreateDisposition =3D cpu_to_le32(oparms->disposition); - req->CreateOptions =3D cpu_to_le32(oparms->create_options & CREATE_OPTION= S_MASK); - req->NameOffset =3D cpu_to_le16(sizeof(struct smb2_create_req)); + req->FileAttributes =3D cpu_to_le32(file_attributes); + req->ShareAccess =3D FILE_SHARE_ALL_LE; + req->CreateDisposition =3D cpu_to_le32(oparms->disposition); + req->CreateOptions =3D cpu_to_le32(oparms->create_options & CREATE_OPTION= S_MASK); + req->NameOffset =3D cpu_to_le16(layout.name_offset); + req->NameLength =3D cpu_to_le16(layout.name_len); + req->RequestedOplockLevel =3D SMB2_OPLOCK_LEVEL_NONE; + req->CreateContextsOffset =3D cpu_to_le32(layout.contexts_offset); + req->CreateContextsLength =3D cpu_to_le32(layout.contexts_len); =20 /* [MS-SMB2] 2.2.13 NameOffset: - * If SMB2_FLAGS_DFS_OPERATIONS is set in the Flags field of - * the SMB2 header, the file name includes a prefix that will - * be processed during DFS name normalization as specified in - * section 3.3.5.9. Otherwise, the file name is relative to - * the share that is identified by the TreeId in the SMB2 - * header. + * If SMB2_FLAGS_DFS_OPERATIONS is set in the Flags field of the SMB2 + * header, the file name includes a prefix that will be processed + * during DFS name normalization as specified in section + * 3.3.5.9. Otherwise, the file name is relative to the share that is + * identified by the TreeId in the SMB2 header. */ + __le16 *name =3D smb->request + layout.name_offset; + if (tcon->share_flags & SHI1005_FLAGS_DFS) { - int name_len; + int tmp; =20 req->hdr.Flags |=3D SMB2_FLAGS_DFS_OPERATIONS; - rc =3D alloc_path_with_tree_prefix(©_path, ©_size, - &name_len, - tcon->tree_name, path); - if (rc) - return rc; - req->NameLength =3D cpu_to_le16(name_len * 2); - uni_path_len =3D copy_size; - path =3D copy_path; - } else { - uni_path_len =3D (2 * UniStrnlen((wchar_t *)path, PATH_MAX)) + 2; - /* MUST set path len (NameLength) to 0 opening root of share */ - req->NameLength =3D cpu_to_le16(uni_path_len - 2); - copy_size =3D ALIGN8(uni_path_len); - copy_path =3D kzalloc(copy_size, GFP_KERNEL); - if (!copy_path) - return -ENOMEM; - memcpy((char *)copy_path, (const char *)path, - uni_path_len); - uni_path_len =3D copy_size; - path =3D copy_path; + + tmp =3D cifs_strtoUTF16(name, tcon->tree_name + 2, INT_MAX, + layout.cp); + WARN_ON(tmp !=3D layout.treename_len); + name +=3D tmp; + if (layout.path_len) { + *name++ =3D cpu_to_le16('\\'); + memcpy(name, path, layout.path_len); + } + } else if (layout.path_len) { + memcpy(name, path, layout.path_len); } =20 - iov[1].iov_len =3D uni_path_len; - iov[1].iov_base =3D path; + smb->offset =3D layout.name_offset + layout.name_len; + cifs_pad_to_8(smb); + WARN_ON_ONCE(smb->offset !=3D layout.contexts_offset); =20 if ((!server->oplocks) || (tcon->no_lease)) *oplock =3D SMB2_OPLOCK_LEVEL_NONE; @@ -3205,32 +3099,21 @@ SMB2_open_init(struct cifs_tcon *tcon, struct TCP_S= erver_Info *server, (oparms->create_options & CREATE_NOT_FILE)) req->RequestedOplockLevel =3D *oplock; /* no srv lease support */ else { - rc =3D add_lease_context(server, req, iov, &n_iov, - oparms->fid->lease_key, oplock, - oparms->fid->parent_lease_key, - oparms->lease_flags); - if (rc) - return rc; + fill_lease_context(server, req, smb, + oparms->fid->lease_key, oplock, + oparms->fid->parent_lease_key, + oparms->lease_flags); } =20 - if (*oplock =3D=3D SMB2_OPLOCK_LEVEL_BATCH) { - rc =3D add_durable_context(iov, &n_iov, oparms, - tcon->use_persistent); - if (rc) - return rc; - } + if (*oplock =3D=3D SMB2_OPLOCK_LEVEL_BATCH) + fill_durable_context(smb, oparms, tcon->use_persistent); =20 - if (tcon->posix_extensions) { - rc =3D add_posix_context(iov, &n_iov, oparms->mode); - if (rc) - return rc; - } + if (tcon->posix_extensions) + fill_posix_context(smb, oparms->mode); =20 if (tcon->snapshot_time) { cifs_dbg(FYI, "adding snapshot context\n"); - rc =3D add_twarp_context(iov, &n_iov, tcon->snapshot_time); - if (rc) - return rc; + fill_twarp_context(smb, tcon->snapshot_time); } =20 if ((oparms->disposition !=3D FILE_OPEN) && (oparms->cifs_sb)) { @@ -3252,40 +3135,13 @@ SMB2_open_init(struct cifs_tcon *tcon, struct TCP_S= erver_Info *server, =20 if (set_owner | set_mode) { cifs_dbg(FYI, "add sd with mode 0x%x\n", oparms->mode); - rc =3D add_sd_context(iov, &n_iov, oparms->mode, set_owner); - if (rc) - return rc; + fill_sd_context(smb, oparms->mode, set_owner); } } =20 - add_query_id_context(iov, &n_iov); - add_ea_context(oparms, iov, &n_iov); - - if (n_iov > 2) { - /* - * We have create contexts behind iov[1] (the file - * name), point at them from the main create request - */ - req->CreateContextsOffset =3D cpu_to_le32( - sizeof(struct smb2_create_req) + - iov[1].iov_len); - req->CreateContextsLength =3D 0; - - for (unsigned int i =3D 2; i < (n_iov-1); i++) { - struct kvec *v =3D &iov[i]; - size_t len =3D v->iov_len; - struct create_context *cctx =3D - (struct create_context *)v->iov_base; - - cctx->Next =3D cpu_to_le32(len); - le32_add_cpu(&req->CreateContextsLength, len); - } - le32_add_cpu(&req->CreateContextsLength, - iov[n_iov-1].iov_len); - } - - rqst->rq_nvec =3D n_iov; - return 0; + fill_query_id_context(smb); + fill_ea_context(smb, oparms); + return smb; } =20 static void @@ -3333,14 +3189,14 @@ parse_posix_ctxt(struct create_context *cc, struct = smb2_file_all_info *info, posix->nlink, posix->mode, posix->reparse_tag); } =20 -int smb2_parse_contexts(struct TCP_Server_Info *server, - struct kvec *rsp_iov, - __u16 *epoch, - char *lease_key, __u8 *oplock, - struct smb2_file_all_info *buf, - struct create_posix_rsp *posix) +int smb2_parse_create_response(struct TCP_Server_Info *server, + struct smb_message *smb, + __u16 *epoch, + char *lease_key, __u8 *oplock, + struct smb2_file_all_info *buf, + struct create_posix_rsp *posix) { - struct smb2_create_rsp *rsp =3D rsp_iov->iov_base; + struct smb2_create_rsp *rsp =3D smb->response; struct create_context *cc; size_t rem, off, len; size_t doff, dlen; @@ -3356,7 +3212,7 @@ int smb2_parse_contexts(struct TCP_Server_Info *serve= r, =20 off =3D le32_to_cpu(rsp->CreateContextsOffset); rem =3D le32_to_cpu(rsp->CreateContextsLength); - if (check_add_overflow(off, rem, &len) || len > rsp_iov->iov_len) + if (check_add_overflow(off, rem, &len) || len > smb->response_len) return -EINVAL; cc =3D (struct create_context *)((u8 *)rsp + off); =20 @@ -3412,39 +3268,18 @@ int smb2_parse_contexts(struct TCP_Server_Info *ser= ver, return 0; } =20 -/* rq_iov[0] is the request and is released by cifs_small_buf_release(). - * All other vectors are freed by kfree(). - */ -void -SMB2_open_free(struct smb_rqst *rqst) -{ - int i; - - if (rqst && rqst->rq_iov) { - cifs_small_buf_release(rqst->rq_iov[0].iov_base); - for (i =3D 1; i < rqst->rq_nvec; i++) - if (rqst->rq_iov[i].iov_base !=3D smb2_padding) - kfree(rqst->rq_iov[i].iov_base); - } -} - -int -SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *= path, - __u8 *oplock, struct smb2_file_all_info *buf, - struct create_posix_rsp *posix, - struct kvec *err_iov, int *buftype) +int SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le= 16 *path, + __u8 *oplock, struct smb2_file_all_info *buf, + struct create_posix_rsp *posix, struct kvec *err_iov) { - struct smb_rqst rqst; + struct TCP_Server_Info *server; struct smb2_create_rsp *rsp =3D NULL; + struct smb_message *smb; struct cifs_tcon *tcon =3D oparms->tcon; struct cifs_ses *ses =3D tcon->ses; - struct TCP_Server_Info *server; - struct kvec iov[SMB2_CREATE_IOV_SIZE]; - struct kvec rsp_iov =3D {NULL, 0}; - int resp_buftype =3D CIFS_NO_BUFFER; - int rc =3D 0; - int flags =3D 0; int retries =3D 0, cur_sleep =3D 1; + int flags =3D 0; + int rc =3D 0; =20 replay_again: /* reinitialize for possible replay */ @@ -3459,34 +3294,27 @@ SMB2_open(const unsigned int xid, struct cifs_open_= parms *oparms, __le16 *path, if (smb3_encryption_required(tcon)) flags |=3D CIFS_TRANSFORM_REQ; =20 - memset(&rqst, 0, sizeof(struct smb_rqst)); - memset(&iov, 0, sizeof(iov)); - rqst.rq_iov =3D iov; - rqst.rq_nvec =3D SMB2_CREATE_IOV_SIZE; - - rc =3D SMB2_open_init(tcon, server, - &rqst, oplock, oparms, path); - if (rc) + smb =3D SMB2_open_init(tcon, server, oplock, oparms, path); + if (IS_ERR(smb)) { + rc =3D PTR_ERR(smb); + smb =3D NULL; goto creat_exit; + } =20 trace_smb3_open_enter(xid, tcon->tid, tcon->ses->Suid, oparms->path, oparms->create_options, oparms->desired_access); =20 if (retries) - smb2_set_replay(server, &rqst); + smb2_set_replay_smb(server, smb); =20 - rc =3D cifs_send_recv(xid, ses, server, - &rqst, &resp_buftype, flags, - &rsp_iov); - rsp =3D (struct smb2_create_rsp *)rsp_iov.iov_base; + rc =3D smb_send_recv_messages(xid, ses, server, smb, flags); + rsp =3D (struct smb2_create_rsp *)smb->response; =20 if (rc !=3D 0) { cifs_stats_fail_inc(tcon, SMB2_CREATE); if (err_iov && rsp) { - *err_iov =3D rsp_iov; - *buftype =3D resp_buftype; - resp_buftype =3D CIFS_NO_BUFFER; - rsp =3D NULL; + err_iov->iov_base =3D smb->response; + err_iov->iov_len =3D smb->response_len; } trace_smb3_open_err(xid, tcon->tid, ses->Suid, oparms->create_options, oparms->desired_access, rc); @@ -3496,10 +3324,11 @@ SMB2_open(const unsigned int xid, struct cifs_open_= parms *oparms, __le16 *path, tcon->need_reconnect =3D true; } goto creat_exit; - } else if (rsp =3D=3D NULL) /* unlikely to happen, but safer to check */ + } + if (!rsp) /* unlikely to happen, but safer to check */ goto creat_exit; - else - trace_smb3_open_done(xid, rsp->PersistentFileId, tcon->tid, ses->Suid, + + trace_smb3_open_done(xid, rsp->PersistentFileId, tcon->tid, ses->Suid, oparms->create_options, oparms->desired_access); =20 atomic_inc(&tcon->num_remote_opens); @@ -3523,12 +3352,10 @@ SMB2_open(const unsigned int xid, struct cifs_open_= parms *oparms, __le16 *path, } =20 =20 - rc =3D smb2_parse_contexts(server, &rsp_iov, &oparms->fid->epoch, - oparms->fid->lease_key, oplock, buf, posix); + rc =3D smb2_parse_create_response(server, smb, &oparms->fid->epoch, + oparms->fid->lease_key, oplock, buf, posix); creat_exit: - SMB2_open_free(&rqst); - free_rsp_buf(resp_buftype, rsp); - + smb_put_messages(smb); if (is_replayable_error(rc) && smb2_should_replay(tcon, &retries, &cur_sleep)) goto replay_again; diff --git a/fs/smb/client/smb2proto.h b/fs/smb/client/smb2proto.h index 22284a52f300..f854093dd92c 100644 --- a/fs/smb/client/smb2proto.h +++ b/fs/smb/client/smb2proto.h @@ -151,17 +151,12 @@ extern int SMB2_tcon(const unsigned int xid, struct c= ifs_ses *ses, const char *tree, struct cifs_tcon *tcon, const struct nls_table *); extern int SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon); -extern int SMB2_open(const unsigned int xid, struct cifs_open_parms *oparm= s, - __le16 *path, __u8 *oplock, - struct smb2_file_all_info *buf, - struct create_posix_rsp *posix, - struct kvec *err_iov, int *resp_buftype); -extern int SMB2_open_init(struct cifs_tcon *tcon, - struct TCP_Server_Info *server, - struct smb_rqst *rqst, - __u8 *oplock, struct cifs_open_parms *oparms, - __le16 *path); -extern void SMB2_open_free(struct smb_rqst *rqst); +int SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le= 16 *path, + __u8 *oplock, struct smb2_file_all_info *buf, + struct create_posix_rsp *posix, struct kvec *err_iov); +struct smb_message *SMB2_open_init(struct cifs_tcon *tcon, + struct TCP_Server_Info *server, __u8 *oplock, + struct cifs_open_parms *oparms, __le16 *path); extern int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid, u32 opcode, char *in_data, u32 indatalen, u32 maxoutlen, @@ -276,12 +271,12 @@ extern int smb3_validate_negotiate(const unsigned int= , struct cifs_tcon *); =20 extern enum securityEnum smb2_select_sectype(struct TCP_Server_Info *, enum securityEnum); -int smb2_parse_contexts(struct TCP_Server_Info *server, - struct kvec *rsp_iov, - __u16 *epoch, - char *lease_key, __u8 *oplock, - struct smb2_file_all_info *buf, - struct create_posix_rsp *posix); +int smb2_parse_create_response(struct TCP_Server_Info *server, + struct smb_message *smb, + __u16 *epoch, + char *lease_key, __u8 *oplock, + struct smb2_file_all_info *buf, + struct create_posix_rsp *posix); =20 extern int smb3_encryption_required(const struct cifs_tcon *tcon); extern int smb2_validate_iov(unsigned int offset, unsigned int buffer_leng= th,