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(+)
@@ -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
@@ -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
new file mode 100644
@@ -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);
+}
new file mode 100644
@@ -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(-)
@@ -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(-)
@@ -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
@@ -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(-)
@@ -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
@@ -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(-)
@@ -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