All of lore.kernel.org
 help / color / mirror / Atom feed
From: Volker Lendecke <Volker.Lendecke@sernet.de>
To: linux-cifs@vger.kernel.org
Cc: Paulo Alcantara <pc@manguebit.com>, Steve French <smfrench@gmail.com>
Subject: Helper functions for smb2 compound ops
Date: Sun, 19 Mar 2023 20:18:52 +0100	[thread overview]
Message-ID: <ZBdgHL3J+UVViuOI@sernet.de> (raw)

[-- Attachment #1: Type: text/plain, Size: 347 bytes --]

Hello!

This is not a formal patchset, more a request for comments.

In fs/cifs when doing compound operations I see a lot of fiddly
boilerplate code. Attached find a little patchset that introduces a
struct smb2_compound_op capturing most of that boilerplate code, along
with a few sample uses.

Is that worth exploring further?

Thanks,

Volker

[-- Attachment #2: smb2_compound_op.patch --]
[-- Type: text/x-diff, Size: 26246 bytes --]

From 171cceab65b87153d165ffb86c7bd218facb3e51 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl@samba.org>
Date: Sun, 19 Mar 2023 16:53:18 +0100
Subject: [PATCH 1/6] cifs: Add required includes to cifsfs.h

struct file and a few others are referenced in prototypes.

Signed-off-by: Volker Lendecke <vl@samba.org>
---
 fs/cifs/cifsfs.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 71fe0a0a7992..23391162391e 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -9,6 +9,9 @@
 #ifndef _CIFSFS_H
 #define _CIFSFS_H
 
+#include <linux/dcache.h>
+#include <linux/fs.h>
+
 #include <linux/hash.h>
 
 #define ROOT_I 2
-- 
2.30.2


From ab37ec994a2d6f5e98760b85c3cb31582676e322 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl@samba.org>
Date: Sun, 19 Mar 2023 16:54:50 +0100
Subject: [PATCH 2/6] cifs: Add struct smb2_compound_op

Infrastructure to make handling of open/<op>/close easier

Signed-off-by: Volker Lendecke <vl@samba.org>
---
 fs/cifs/Makefile       |   1 +
 fs/cifs/smb2compound.c | 200 +++++++++++++++++++++++++++++++++++++++++
 fs/cifs/smb2compound.h |  33 +++++++
 3 files changed, 234 insertions(+)
 create mode 100644 fs/cifs/smb2compound.c
 create mode 100644 fs/cifs/smb2compound.h

diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile
index 304a7f6cc13a..ece58d2e3712 100644
--- a/fs/cifs/Makefile
+++ b/fs/cifs/Makefile
@@ -10,6 +10,7 @@ cifs-y := trace.o cifsfs.o cifs_debug.o connect.o dir.o file.o \
 	  cached_dir.o cifs_unicode.o nterr.o cifsencrypt.o \
 	  readdir.o ioctl.o sess.o export.o unc.o winucase.o \
 	  smb2ops.o smb2maperror.o smb2transport.o \
+	  smb2compound.o \
 	  smb2misc.o smb2pdu.o smb2inode.o smb2file.o cifsacl.o fs_context.o \
 	  dns_resolve.o cifs_spnego_negtokeninit.asn1.o asn1.o
 
diff --git a/fs/cifs/smb2compound.c b/fs/cifs/smb2compound.c
new file mode 100644
index 000000000000..ef64db12cb44
--- /dev/null
+++ b/fs/cifs/smb2compound.c
@@ -0,0 +1,200 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  Copyright (c) 2023, Volker Lendecke <vl@samba.org>
+ */
+
+#include "cifsfs.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "smb2pdu.h"
+#include "smb2proto.h"
+#include "smb2compound.h"
+
+struct smb2_compound_op *smb2_compound_op_init(bool openclose,
+					       int num_ops,
+					       int *num_rqst_iovs,
+					       int *op_idx)
+{
+	int num_rqst = num_ops;
+	int num_rqst_iov = 0;
+	struct smb_rqst *rqst;
+	struct kvec *rqst_iov;
+	struct smb2_compound_op *op;
+	int i;
+
+	if (openclose) {
+		num_rqst += 2;
+		num_rqst_iov += SMB2_CREATE_IOV_SIZE + 1; /* open+close */
+	}
+
+	for (i = 0; i < num_ops; i++)
+		num_rqst_iov += num_rqst_iovs[i];
+
+	/*
+	 * For now use a simple approach of multiple allocs. As a
+	 * valid optimization allocate all sub-structures of "op" from
+	 * one kzalloc.
+	 */
+
+	op = kzalloc(sizeof(*op), GFP_KERNEL);
+	if (!op)
+		return NULL;
+
+	op->num_rqst = num_rqst;
+
+	op->rqst = kcalloc(num_rqst, sizeof(*op->rqst), GFP_KERNEL);
+	if (!op->rqst)
+		goto nomem;
+
+	op->rqst_iov = kcalloc(num_rqst_iov, sizeof(*op->rqst_iov), GFP_KERNEL);
+	if (!op->rqst_iov)
+		goto nomem;
+
+	op->resp_buftype = kcalloc(num_rqst,
+				   sizeof(*op->resp_buftype),
+				   GFP_KERNEL);
+	if (!op->resp_buftype)
+		goto nomem;
+
+	op->rsp_iov = kcalloc(num_rqst, sizeof(*op->rsp_iov), GFP_KERNEL);
+	if (!op->rsp_iov)
+		goto nomem;
+
+	/*
+	 * Fill all op->rqst->rqst_iov structures
+	 */
+
+	rqst = op->rqst;
+	rqst_iov = op->rqst_iov;
+
+	if (openclose) {
+		/* open request */
+		rqst->rq_iov = rqst_iov;
+		rqst->rq_nvec = SMB2_CREATE_IOV_SIZE;
+		rqst_iov += SMB2_CREATE_IOV_SIZE;
+		rqst++;
+	}
+
+	for (i = 0; i < num_ops; i++) {
+		rqst->rq_iov = rqst_iov;
+		rqst->rq_nvec = num_rqst_iovs[i];
+		rqst_iov += num_rqst_iovs[i];
+		rqst++;
+	}
+
+	if (openclose) {
+		/* close request */
+		rqst->rq_iov = rqst_iov;
+		rqst->rq_nvec = 1;
+		rqst_iov += 1;
+		rqst++;
+	}
+
+	if (op_idx)
+		*op_idx = openclose ? 1 : 0;
+
+	return op;
+nomem:
+	smb2_compound_op_free(op);
+	return NULL;
+}
+
+void smb2_compound_op_free(struct smb2_compound_op *op)
+{
+	for (int i = 0; i < op->num_rqst; i++) {
+		struct smb_rqst *rqst = &op->rqst[i];
+		struct smb2_hdr *hdr = rqst->rq_iov[0].iov_base;
+
+		switch (hdr->Command) {
+		case SMB2_CREATE:
+			SMB2_open_free(rqst);
+			break;
+		case SMB2_QUERY_INFO:
+			SMB2_query_info_free(rqst);
+			break;
+		case SMB2_SET_INFO:
+			SMB2_set_info_free(rqst);
+			break;
+		case SMB2_IOCTL:
+			SMB2_ioctl_free(rqst);
+			break;
+		case SMB2_CLOSE:
+			SMB2_close_free(rqst);
+			break;
+		}
+	}
+
+	if (op->rsp_iov && op->resp_buftype) {
+		for (int i = 0; i < op->num_rqst; i++)
+			free_rsp_buf(op->resp_buftype[i],
+				     op->rsp_iov[i].iov_base);
+	}
+
+	kfree(op->rsp_iov);
+	kfree(op->resp_buftype);
+	kfree(op->rqst_iov);
+	kfree(op->rqst);
+	kfree(op);
+}
+
+int smb2_compound_openclose(struct smb2_compound_op *op,
+			    struct cifs_sb_info *cifs_sb,
+			    struct cifs_tcon *tcon,
+			    struct TCP_Server_Info *server,
+			    __u8 *oplock, struct cifs_open_parms *oparms,
+			    const char *path)
+{
+	__le16 *utf16_path = NULL;
+	u8 none_oplock = SMB2_OPLOCK_LEVEL_NONE;
+	int rc;
+
+	utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
+	if (!utf16_path)
+		return -ENOMEM;
+
+	if (!oplock)
+		oplock = &none_oplock;
+
+	oparms->fid = &op->fid;
+
+	rc = SMB2_open_init(tcon, server, &op->rqst[0], oplock, oparms,
+			    utf16_path);
+
+	kfree(utf16_path);
+
+	if (rc)
+		return rc;
+
+	rc = SMB2_close_init(tcon, server, &op->rqst[op->num_rqst-1],
+			     COMPOUND_FID, COMPOUND_FID, false);
+	return rc;
+}
+
+static void smb2_compound_set_related(struct cifs_tcon *tcon,
+			       struct smb2_compound_op *op)
+{
+	smb2_set_next_command(tcon, &op->rqst[0]);
+
+	for (int i = 1; i < op->num_rqst; i++) {
+		smb2_set_next_command(tcon, &op->rqst[i]);
+		smb2_set_related(&op->rqst[i]);
+	}
+}
+
+int smb2_compound_send_recv(const unsigned int xid,
+			    struct cifs_tcon *tcon,
+			    struct cifs_ses *ses,
+			    struct TCP_Server_Info *server,
+			    struct smb2_compound_op *op)
+{
+	int flags = CIFS_CP_CREATE_CLOSE_OP;
+
+	if (smb3_encryption_required(tcon))
+		flags |= CIFS_TRANSFORM_REQ;
+
+	smb2_compound_set_related(tcon, op);
+
+	return compound_send_recv(xid, ses, server, flags,
+				  op->num_rqst, op->rqst,
+				  op->resp_buftype, op->rsp_iov);
+}
diff --git a/fs/cifs/smb2compound.h b/fs/cifs/smb2compound.h
new file mode 100644
index 000000000000..0a4116ef32ba
--- /dev/null
+++ b/fs/cifs/smb2compound.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: LGPL-2.1 */
+/*
+ *  Copyright (c) 2023, Volker Lendecke <vl@samba.org>
+ */
+
+struct smb2_compound_op {
+	struct cifs_fid fid;
+	int num_rqst;
+	struct smb_rqst *rqst;
+	struct kvec *rqst_iov;
+	int *resp_buftype;
+	struct kvec *rsp_iov;
+};
+
+struct smb2_compound_op *smb2_compound_op_init(bool openclose,
+					       int num_ops,
+					       int *num_rqst_iovs,
+					       int *op_idx);
+
+void smb2_compound_op_free(struct smb2_compound_op *op);
+
+int smb2_compound_openclose(struct smb2_compound_op *op,
+			    struct cifs_sb_info *cifs_sb,
+			    struct cifs_tcon *tcon,
+			    struct TCP_Server_Info *server,
+			    __u8 *oplock, struct cifs_open_parms *oparms,
+			    const char *path);
+
+int smb2_compound_send_recv(const unsigned int xid,
+			    struct cifs_tcon *tcon,
+			    struct cifs_ses *ses,
+			    struct TCP_Server_Info *server,
+			    struct smb2_compound_op *op);
-- 
2.30.2


From a6deeaeddba1be71d8feca93579bbd128db682c3 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl@samba.org>
Date: Sun, 19 Mar 2023 16:25:07 +0100
Subject: [PATCH 3/6] cifs: Use smb2_compound_op in smb2_query_info_compound

Remove special-case code

Signed-off-by: Volker Lendecke <vl@samba.org>
---
 fs/cifs/smb2ops.c | 120 +++++++++++++---------------------------------
 1 file changed, 33 insertions(+), 87 deletions(-)

diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 6dfb865ee9d7..bf539c9d2cf8 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -28,6 +28,7 @@
 #include "fscache.h"
 #include "fs_context.h"
 #include "cached_dir.h"
+#include "smb2compound.h"
 
 /* Change credits for different ops and return the total number of credits */
 static int
@@ -2460,32 +2461,16 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon,
 {
 	struct cifs_ses *ses = tcon->ses;
 	struct TCP_Server_Info *server = cifs_pick_channel(ses);
-	int flags = CIFS_CP_CREATE_CLOSE_OP;
-	struct smb_rqst rqst[3];
-	int resp_buftype[3];
-	struct kvec rsp_iov[3];
-	struct kvec open_iov[SMB2_CREATE_IOV_SIZE];
-	struct kvec qi_iov[1];
-	struct kvec close_iov[1];
-	u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
-	struct cifs_open_parms oparms;
-	struct cifs_fid fid;
+	__u64 persistent_fid = COMPOUND_FID;
+	__u64 volatile_fid = COMPOUND_FID;
+	struct smb2_compound_op *op = NULL;
+	int num_qi_iov = 1;
+	int op_idx = 0;
 	int rc;
-	__le16 *utf16_path;
 	struct cached_fid *cfid = NULL;
 
 	if (!path)
 		path = "";
-	utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
-	if (!utf16_path)
-		return -ENOMEM;
-
-	if (smb3_encryption_required(tcon))
-		flags |= CIFS_TRANSFORM_REQ;
-
-	memset(rqst, 0, sizeof(rqst));
-	resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER;
-	memset(rsp_iov, 0, sizeof(rsp_iov));
 
 	/*
 	 * We can only call this for things we know are directories.
@@ -2494,73 +2479,38 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon,
 		open_cached_dir(xid, tcon, path, cifs_sb, false,
 				&cfid); /* cfid null if open dir failed */
 
-	memset(&open_iov, 0, sizeof(open_iov));
-	rqst[0].rq_iov = open_iov;
-	rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE;
-
-	oparms = (struct cifs_open_parms) {
-		.tcon = tcon,
-		.desired_access = desired_access,
-		.disposition = FILE_OPEN,
-		.create_options = cifs_create_options(cifs_sb, 0),
-		.fid = &fid,
-	};
-
-	rc = SMB2_open_init(tcon, server,
-			    &rqst[0], &oplock, &oparms, utf16_path);
-	if (rc)
+	op = smb2_compound_op_init(!cfid, 1, &num_qi_iov, &op_idx);
+	if (!op) {
+		rc = -ENOMEM;
 		goto qic_exit;
-	smb2_set_next_command(tcon, &rqst[0]);
-
-	memset(&qi_iov, 0, sizeof(qi_iov));
-	rqst[1].rq_iov = qi_iov;
-	rqst[1].rq_nvec = 1;
+	}
 
 	if (cfid) {
-		rc = SMB2_query_info_init(tcon, server,
-					  &rqst[1],
-					  cfid->fid.persistent_fid,
-					  cfid->fid.volatile_fid,
-					  class, type, 0,
-					  output_len, 0,
-					  NULL);
+		persistent_fid = cfid->fid.persistent_fid;
+		volatile_fid = cfid->fid.volatile_fid;
 	} else {
-		rc = SMB2_query_info_init(tcon, server,
-					  &rqst[1],
-					  COMPOUND_FID,
-					  COMPOUND_FID,
-					  class, type, 0,
-					  output_len, 0,
-					  NULL);
-	}
-	if (rc)
-		goto qic_exit;
-	if (!cfid) {
-		smb2_set_next_command(tcon, &rqst[1]);
-		smb2_set_related(&rqst[1]);
-	}
-
-	memset(&close_iov, 0, sizeof(close_iov));
-	rqst[2].rq_iov = close_iov;
-	rqst[2].rq_nvec = 1;
+		struct cifs_open_parms oparms = {
+			.tcon = tcon,
+			.desired_access = desired_access,
+			.disposition = FILE_OPEN,
+			.create_options = cifs_create_options(cifs_sb, 0),
+		};
+		rc = smb2_compound_openclose(op, cifs_sb, tcon, server, NULL,
+					     &oparms, path);
+		if (rc)
+			goto qic_exit;
+	};
 
-	rc = SMB2_close_init(tcon, server,
-			     &rqst[2], COMPOUND_FID, COMPOUND_FID, false);
+	rc = SMB2_query_info_init(tcon, server, &op->rqst[op_idx],
+				  persistent_fid, volatile_fid,
+				  class, type, 0,
+				  output_len, 0,
+				  NULL);
 	if (rc)
 		goto qic_exit;
-	smb2_set_related(&rqst[2]);
 
-	if (cfid) {
-		rc = compound_send_recv(xid, ses, server,
-					flags, 1, &rqst[1],
-					&resp_buftype[1], &rsp_iov[1]);
-	} else {
-		rc = compound_send_recv(xid, ses, server,
-					flags, 3, rqst,
-					resp_buftype, rsp_iov);
-	}
+	rc = smb2_compound_send_recv(xid, tcon, ses, server, op);
 	if (rc) {
-		free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
 		if (rc == -EREMCHG) {
 			tcon->need_reconnect = true;
 			pr_warn_once("server share %s deleted\n",
@@ -2568,16 +2518,12 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon,
 		}
 		goto qic_exit;
 	}
-	*rsp = rsp_iov[1];
-	*buftype = resp_buftype[1];
+	*rsp = op->rsp_iov[1];
+	*buftype = op->resp_buftype[1];
+	op->resp_buftype[1] = CIFS_NO_BUFFER; /* don't free here */
 
  qic_exit:
-	kfree(utf16_path);
-	SMB2_open_free(&rqst[0]);
-	SMB2_query_info_free(&rqst[1]);
-	SMB2_close_free(&rqst[2]);
-	free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
-	free_rsp_buf(resp_buftype[2], rsp_iov[2].iov_base);
+	smb2_compound_op_free(op);
 	if (cfid)
 		close_cached_dir(cfid);
 	return rc;
-- 
2.30.2


From c22a9bffca9b804d838bd176785d4c886b0938d4 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl@samba.org>
Date: Sun, 19 Mar 2023 17:50:59 +0100
Subject: [PATCH 4/6] cifs: Use smb2_compound_op in smb2_unlink()

Reduce use of smb2_compound_op()

Signed-off-by: Volker Lendecke <vl@samba.org>
---
 fs/cifs/smb2glob.h  |  1 -
 fs/cifs/smb2inode.c | 54 +++++++++++++++++++++++++++++++++------------
 2 files changed, 40 insertions(+), 15 deletions(-)

diff --git a/fs/cifs/smb2glob.h b/fs/cifs/smb2glob.h
index 82e916ad167c..d9e7c122eee5 100644
--- a/fs/cifs/smb2glob.h
+++ b/fs/cifs/smb2glob.h
@@ -29,7 +29,6 @@
 #define SMB2_OP_QUERY_DIR 4
 #define SMB2_OP_MKDIR 5
 #define SMB2_OP_RENAME 6
-#define SMB2_OP_DELETE 7
 #define SMB2_OP_HARDLINK 8
 #define SMB2_OP_SET_EOF 9
 #define SMB2_OP_RMDIR 10
diff --git a/fs/cifs/smb2inode.c b/fs/cifs/smb2inode.c
index 8dd3791b5c53..d1529ade2e58 100644
--- a/fs/cifs/smb2inode.c
+++ b/fs/cifs/smb2inode.c
@@ -25,6 +25,7 @@
 #include "smb2proto.h"
 #include "cached_dir.h"
 #include "smb2status.h"
+#include "smb2compound.h"
 
 static void
 free_set_inf_compound(struct smb_rqst *rqst)
@@ -199,9 +200,6 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
 		num_rqst++;
 		trace_smb3_posix_query_info_compound_enter(xid, ses->Suid, tcon->tid, full_path);
 		break;
-	case SMB2_OP_DELETE:
-		trace_smb3_delete_enter(xid, ses->Suid, tcon->tid, full_path);
-		break;
 	case SMB2_OP_MKDIR:
 		/*
 		 * Directories are created through parameters in the
@@ -473,14 +471,6 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
 		else
 			trace_smb3_posix_query_info_compound_done(xid, ses->Suid, tcon->tid);
 		break;
-	case SMB2_OP_DELETE:
-		if (rc)
-			trace_smb3_delete_err(xid,  ses->Suid, tcon->tid, rc);
-		else
-			trace_smb3_delete_done(xid, ses->Suid, tcon->tid);
-		if (rqst[1].rq_iov)
-			SMB2_close_free(&rqst[1]);
-		break;
 	case SMB2_OP_MKDIR:
 		if (rc)
 			trace_smb3_mkdir_err(xid,  ses->Suid, tcon->tid, rc);
@@ -748,9 +738,45 @@ int
 smb2_unlink(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
 	    struct cifs_sb_info *cifs_sb)
 {
-	return smb2_compound_op(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN,
-				CREATE_DELETE_ON_CLOSE | OPEN_REPARSE_POINT,
-				ACL_NO_MODE, NULL, SMB2_OP_DELETE, NULL, NULL, NULL, NULL, NULL);
+	struct cifs_ses *ses = tcon->ses;
+	struct TCP_Server_Info *server = cifs_pick_channel(ses);
+	struct cifs_open_parms oparms = {
+		.tcon = tcon,
+		.desired_access = DELETE,
+		.disposition = FILE_OPEN,
+		.create_options = cifs_create_options(cifs_sb,
+						      CREATE_DELETE_ON_CLOSE |
+						      OPEN_REPARSE_POINT),
+		.mode = ACL_NO_MODE,
+		.cifs_sb = cifs_sb,
+	};
+	struct smb2_compound_op *op = NULL;
+	int rc;
+
+	trace_smb3_delete_enter(xid, ses->Suid, tcon->tid, name);
+
+	op = smb2_compound_op_init(true, 0, NULL, NULL);
+	if (!op) {
+		rc = -ENOMEM;
+		goto fail;
+	}
+
+	rc = smb2_compound_openclose(op, cifs_sb, tcon, server, NULL, &oparms,
+				     name);
+	if (rc)
+		goto fail;
+
+	rc = smb2_compound_send_recv(xid, tcon, ses, server, op);
+
+fail:
+	smb2_compound_op_free(op);
+
+	if (rc)
+		trace_smb3_delete_err(xid,  ses->Suid, tcon->tid, rc);
+	else
+		trace_smb3_delete_done(xid, ses->Suid, tcon->tid);
+
+	return rc;
 }
 
 static int
-- 
2.30.2


From 71c8b6024ad6438712e0a0ab35710fa6ea7bc3f2 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl@samba.org>
Date: Sun, 19 Mar 2023 19:02:36 +0100
Subject: [PATCH 5/6] cifs: Use smb2_compound_op in smb2_set_path_size()

Avoid boilerplate code

Signed-off-by: Volker Lendecke <vl@samba.org>
---
 fs/cifs/smb2glob.h  |   1 -
 fs/cifs/smb2inode.c | 101 ++++++++++++++++++++++++--------------------
 2 files changed, 55 insertions(+), 47 deletions(-)

diff --git a/fs/cifs/smb2glob.h b/fs/cifs/smb2glob.h
index d9e7c122eee5..897c16c4ea69 100644
--- a/fs/cifs/smb2glob.h
+++ b/fs/cifs/smb2glob.h
@@ -30,7 +30,6 @@
 #define SMB2_OP_MKDIR 5
 #define SMB2_OP_RENAME 6
 #define SMB2_OP_HARDLINK 8
-#define SMB2_OP_SET_EOF 9
 #define SMB2_OP_RMDIR 10
 #define SMB2_OP_POSIX_QUERY_INFO 11
 
diff --git a/fs/cifs/smb2inode.c b/fs/cifs/smb2inode.c
index d1529ade2e58..787d17d0c6db 100644
--- a/fs/cifs/smb2inode.c
+++ b/fs/cifs/smb2inode.c
@@ -225,41 +225,6 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
 		smb2_set_related(&rqst[num_rqst++]);
 		trace_smb3_rmdir_enter(xid, ses->Suid, tcon->tid, full_path);
 		break;
-	case SMB2_OP_SET_EOF:
-		rqst[num_rqst].rq_iov = &vars->si_iov[0];
-		rqst[num_rqst].rq_nvec = 1;
-
-		size[0] = 8; /* sizeof __le64 */
-		data[0] = ptr;
-
-		if (cfile) {
-			rc = SMB2_set_info_init(tcon, server,
-						&rqst[num_rqst],
-						cfile->fid.persistent_fid,
-						cfile->fid.volatile_fid,
-						current->tgid,
-						FILE_END_OF_FILE_INFORMATION,
-						SMB2_O_INFO_FILE, 0,
-						data, size);
-		} else {
-			rc = SMB2_set_info_init(tcon, server,
-						&rqst[num_rqst],
-						COMPOUND_FID,
-						COMPOUND_FID,
-						current->tgid,
-						FILE_END_OF_FILE_INFORMATION,
-						SMB2_O_INFO_FILE, 0,
-						data, size);
-			if (!rc) {
-				smb2_set_next_command(tcon, &rqst[num_rqst]);
-				smb2_set_related(&rqst[num_rqst]);
-			}
-		}
-		if (rc)
-			goto finished;
-		num_rqst++;
-		trace_smb3_set_eof_enter(xid, ses->Suid, tcon->tid, full_path);
-		break;
 	case SMB2_OP_SET_INFO:
 		rqst[num_rqst].rq_iov = &vars->si_iov[0];
 		rqst[num_rqst].rq_nvec = 1;
@@ -500,13 +465,6 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
 			trace_smb3_rmdir_done(xid, ses->Suid, tcon->tid);
 		free_set_inf_compound(rqst);
 		break;
-	case SMB2_OP_SET_EOF:
-		if (rc)
-			trace_smb3_set_eof_err(xid,  ses->Suid, tcon->tid, rc);
-		else
-			trace_smb3_set_eof_done(xid, ses->Suid, tcon->tid);
-		free_set_inf_compound(rqst);
-		break;
 	case SMB2_OP_SET_INFO:
 		if (rc)
 			trace_smb3_set_info_compound_err(xid,  ses->Suid,
@@ -830,13 +788,64 @@ smb2_set_path_size(const unsigned int xid, struct cifs_tcon *tcon,
 		   const char *full_path, __u64 size,
 		   struct cifs_sb_info *cifs_sb, bool set_alloc)
 {
+	struct cifs_ses *ses = tcon->ses;
+	struct TCP_Server_Info *server = cifs_pick_channel(ses);
+	__u64 persistent_fid = COMPOUND_FID;
+	__u64 volatile_fid = COMPOUND_FID;
+	struct smb2_compound_op *op = NULL;
+	int num_si_iov = 1;
+	int op_idx = 0;
+	int rc;
+	struct cifsFileInfo *cfile = NULL;
 	__le64 eof = cpu_to_le64(size);
-	struct cifsFileInfo *cfile;
+
+	unsigned int sizes = sizeof(eof);
+	void *data = &eof;
+
+	trace_smb3_set_eof_enter(xid, ses->Suid, tcon->tid, full_path);
 
 	cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile);
-	return smb2_compound_op(xid, tcon, cifs_sb, full_path,
-				FILE_WRITE_DATA, FILE_OPEN, 0, ACL_NO_MODE,
-				&eof, SMB2_OP_SET_EOF, cfile, NULL, NULL, NULL, NULL);
+
+	op = smb2_compound_op_init(!cfile, 1, &num_si_iov, &op_idx);
+	if (!op) {
+		rc = -ENOMEM;
+		goto fail;
+	}
+
+	if (cfile) {
+		persistent_fid = cfile->fid.persistent_fid;
+		volatile_fid = cfile->fid.volatile_fid;
+	} else {
+		struct cifs_open_parms oparms = {
+			.tcon = tcon,
+			.desired_access = FILE_WRITE_DATA,
+			.disposition = FILE_OPEN,
+			.create_options = cifs_create_options(cifs_sb, 0),
+			.mode = ACL_NO_MODE,
+		};
+		rc = smb2_compound_openclose(op, cifs_sb, tcon, server, NULL,
+					     &oparms, full_path);
+		if (rc)
+			goto fail;
+	}
+
+	rc = SMB2_set_info_init(tcon, server, &op->rqst[op_idx],
+				persistent_fid, volatile_fid,
+				current->tgid, FILE_END_OF_FILE_INFORMATION,
+				SMB2_O_INFO_FILE, 0, &data, &sizes);
+	if (!rc)
+		goto fail;
+
+	rc = smb2_compound_send_recv(xid, tcon, ses, server, op);
+fail:
+	smb2_compound_op_free(op);
+
+	if (rc)
+		trace_smb3_set_eof_err(xid,  ses->Suid, tcon->tid, rc);
+	else
+		trace_smb3_set_eof_done(xid, ses->Suid, tcon->tid);
+
+	return rc;
 }
 
 int
-- 
2.30.2


From 35f02f7d37624e37f33eb53a4071c156a8d422a8 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl@samba.org>
Date: Sun, 19 Mar 2023 19:22:23 +0100
Subject: [PATCH 6/6] cifs: Use smb2_compound_op in smb2_query_symlink()

Avoid boilerplate code

Signed-off-by: Volker Lendecke <vl@samba.org>
---
 fs/cifs/smb2ops.c | 83 +++++++++--------------------------------------
 1 file changed, 16 insertions(+), 67 deletions(-)

diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index bf539c9d2cf8..43b59b33d308 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -2832,20 +2832,14 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
 		   struct cifs_sb_info *cifs_sb, const char *full_path,
 		   char **target_path, bool is_reparse_point)
 {
+	struct cifs_ses *ses = tcon->ses;
+	struct TCP_Server_Info *server = cifs_pick_channel(ses);
+	struct smb2_compound_op *op = NULL;
+	int num_ioctl_iov = SMB2_IOCTL_IOV_SIZE;
+	int op_idx = 0;
 	int rc;
-	__le16 *utf16_path = NULL;
-	__u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
 	struct cifs_open_parms oparms;
-	struct cifs_fid fid;
 	struct kvec err_iov = {NULL, 0};
-	struct TCP_Server_Info *server = cifs_pick_channel(tcon->ses);
-	int flags = CIFS_CP_CREATE_CLOSE_OP;
-	struct smb_rqst rqst[3];
-	int resp_buftype[3];
-	struct kvec rsp_iov[3];
-	struct kvec open_iov[SMB2_CREATE_IOV_SIZE];
-	struct kvec io_iov[SMB2_IOCTL_IOV_SIZE];
-	struct kvec close_iov[1];
 	struct smb2_create_rsp *create_rsp;
 	struct smb2_ioctl_rsp *ioctl_rsp;
 	struct reparse_data_buffer *reparse_buf;
@@ -2856,75 +2850,37 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
 
 	*target_path = NULL;
 
-	if (smb3_encryption_required(tcon))
-		flags |= CIFS_TRANSFORM_REQ;
-
-	memset(rqst, 0, sizeof(rqst));
-	resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER;
-	memset(rsp_iov, 0, sizeof(rsp_iov));
-
-	utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
-	if (!utf16_path)
+	op = smb2_compound_op_init(true, 1, &num_ioctl_iov, &op_idx);
+	if (!op)
 		return -ENOMEM;
 
-	/* Open */
-	memset(&open_iov, 0, sizeof(open_iov));
-	rqst[0].rq_iov = open_iov;
-	rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE;
-
 	oparms = (struct cifs_open_parms) {
 		.tcon = tcon,
 		.desired_access = FILE_READ_ATTRIBUTES,
 		.disposition = FILE_OPEN,
 		.create_options = cifs_create_options(cifs_sb, create_options),
-		.fid = &fid,
 	};
 
-	rc = SMB2_open_init(tcon, server,
-			    &rqst[0], &oplock, &oparms, utf16_path);
+	rc = smb2_compound_openclose(op, cifs_sb, tcon, server, NULL,
+				     &oparms, full_path);
 	if (rc)
 		goto querty_exit;
-	smb2_set_next_command(tcon, &rqst[0]);
-
-
-	/* IOCTL */
-	memset(&io_iov, 0, sizeof(io_iov));
-	rqst[1].rq_iov = io_iov;
-	rqst[1].rq_nvec = SMB2_IOCTL_IOV_SIZE;
 
 	rc = SMB2_ioctl_init(tcon, server,
-			     &rqst[1], fid.persistent_fid,
-			     fid.volatile_fid, FSCTL_GET_REPARSE_POINT, NULL, 0,
+			     &op->rqst[op_idx], COMPOUND_FID,
+			     COMPOUND_FID, FSCTL_GET_REPARSE_POINT, NULL, 0,
 			     CIFSMaxBufSize -
 			     MAX_SMB2_CREATE_RESPONSE_SIZE -
 			     MAX_SMB2_CLOSE_RESPONSE_SIZE);
 	if (rc)
 		goto querty_exit;
 
-	smb2_set_next_command(tcon, &rqst[1]);
-	smb2_set_related(&rqst[1]);
-
-
-	/* Close */
-	memset(&close_iov, 0, sizeof(close_iov));
-	rqst[2].rq_iov = close_iov;
-	rqst[2].rq_nvec = 1;
-
-	rc = SMB2_close_init(tcon, server,
-			     &rqst[2], COMPOUND_FID, COMPOUND_FID, false);
-	if (rc)
-		goto querty_exit;
-
-	smb2_set_related(&rqst[2]);
-
-	rc = compound_send_recv(xid, tcon->ses, server,
-				flags, 3, rqst,
-				resp_buftype, rsp_iov);
+	rc = smb2_compound_send_recv(xid, tcon, ses, server, op);
 
-	create_rsp = rsp_iov[0].iov_base;
+	create_rsp = op->rsp_iov[0].iov_base;
 	if (create_rsp && create_rsp->hdr.Status)
-		err_iov = rsp_iov[0];
-	ioctl_rsp = rsp_iov[1].iov_base;
+		err_iov = op->rsp_iov[0];
+	ioctl_rsp = op->rsp_iov[1].iov_base;
 
 	/*
 	 * Open was successful and we got an ioctl response.
@@ -2938,7 +2894,7 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
 		plen = le32_to_cpu(ioctl_rsp->OutputCount);
 
 		if (plen + le32_to_cpu(ioctl_rsp->OutputOffset) >
-		    rsp_iov[1].iov_len) {
+		    op->rsp_iov[1].iov_len) {
 			cifs_tcon_dbg(VFS, "srv returned invalid ioctl len: %d\n",
 				 plen);
 			rc = -EIO;
@@ -2959,13 +2915,6 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
 
  querty_exit:
 	cifs_dbg(FYI, "query symlink rc %d\n", rc);
-	kfree(utf16_path);
-	SMB2_open_free(&rqst[0]);
-	SMB2_ioctl_free(&rqst[1]);
-	SMB2_close_free(&rqst[2]);
-	free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
-	free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
-	free_rsp_buf(resp_buftype[2], rsp_iov[2].iov_base);
 	return rc;
 }
 
-- 
2.30.2


             reply	other threads:[~2023-03-19 19:21 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-03-19 19:18 Volker Lendecke [this message]
2023-03-19 19:49 ` Helper functions for smb2 compound ops Steve French
2023-03-19 20:14   ` Volker Lendecke

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ZBdgHL3J+UVViuOI@sernet.de \
    --to=volker.lendecke@sernet.de \
    --cc=linux-cifs@vger.kernel.org \
    --cc=pc@manguebit.com \
    --cc=smfrench@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.