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
From 171cceab65b87153d165ffb86c7bd218facb3e51 Mon Sep 17 00:00:00 2001 From: Volker Lendecke <vl@xxxxxxxxx> 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@xxxxxxxxx> --- 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@xxxxxxxxx> 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@xxxxxxxxx> --- 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@xxxxxxxxx> + */ + +#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@xxxxxxxxx> + */ + +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@xxxxxxxxx> 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@xxxxxxxxx> --- 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@xxxxxxxxx> 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@xxxxxxxxx> --- 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@xxxxxxxxx> 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@xxxxxxxxx> --- 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@xxxxxxxxx> 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@xxxxxxxxx> --- 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