Skip to content

Commit

Permalink
smb: client: cleanup smb2_query_reparse_point()
Browse files Browse the repository at this point in the history
Use smb2_compound_op() with SMB2_OP_GET_REPARSE to get reparse point.

Signed-off-by: Paulo Alcantara (SUSE) <pc@manguebit.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
  • Loading branch information
Paulo Alcantara authored and Steve French committed Jan 7, 2024
1 parent 514d793 commit 3ded18a
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 139 deletions.
33 changes: 33 additions & 0 deletions fs/smb/client/smb2inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1053,3 +1053,36 @@ struct inode *smb2_get_reparse_inode(struct cifs_open_info_data *data,
}
return rc ? ERR_PTR(rc) : new;
}

int smb2_query_reparse_point(const unsigned int xid,
struct cifs_tcon *tcon,
struct cifs_sb_info *cifs_sb,
const char *full_path,
u32 *tag, struct kvec *rsp,
int *rsp_buftype)
{
struct cifs_open_info_data data = {};
struct cifsFileInfo *cfile;
struct kvec in_iov = { .iov_base = &data, .iov_len = sizeof(data), };
int rc;

cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path);

cifs_get_readable_path(tcon, full_path, &cfile);
rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
FILE_READ_ATTRIBUTES, FILE_OPEN,
OPEN_REPARSE_POINT, ACL_NO_MODE, &in_iov,
&(int){SMB2_OP_GET_REPARSE}, 1, cfile,
NULL, NULL, NULL, NULL);
if (rc)
goto out;

*tag = data.reparse.tag;
*rsp = data.reparse.io.iov;
*rsp_buftype = data.reparse.io.buftype;
memset(&data.reparse.io.iov, 0, sizeof(data.reparse.io.iov));
data.reparse.io.buftype = CIFS_NO_BUFFER;
out:
cifs_free_open_info(&data);
return rc;
}
139 changes: 0 additions & 139 deletions fs/smb/client/smb2ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -2997,145 +2997,6 @@ static int smb2_parse_reparse_point(struct cifs_sb_info *cifs_sb,
return parse_reparse_point(buf, plen, cifs_sb, true, data);
}

static int smb2_query_reparse_point(const unsigned int xid,
struct cifs_tcon *tcon,
struct cifs_sb_info *cifs_sb,
const char *full_path,
u32 *tag, struct kvec *rsp,
int *rsp_buftype)
{
struct smb2_compound_vars *vars;
int rc;
__le16 *utf16_path = NULL;
__u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
struct cifs_open_parms oparms;
struct cifs_fid fid;
struct TCP_Server_Info *server = cifs_pick_channel(tcon->ses);
int flags = CIFS_CP_CREATE_CLOSE_OP;
struct smb_rqst *rqst;
int resp_buftype[3];
struct kvec *rsp_iov;
struct smb2_ioctl_rsp *ioctl_rsp;
struct reparse_data_buffer *reparse_buf;
u32 off, count, len;

cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path);

if (smb3_encryption_required(tcon))
flags |= CIFS_TRANSFORM_REQ;

utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
if (!utf16_path)
return -ENOMEM;

resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER;
vars = kzalloc(sizeof(*vars), GFP_KERNEL);
if (!vars) {
rc = -ENOMEM;
goto out_free_path;
}
rqst = vars->rqst;
rsp_iov = vars->rsp_iov;

/*
* setup smb2open - TODO add optimization to call cifs_get_readable_path
* to see if there is a handle already open that we can use
*/
rqst[0].rq_iov = vars->open_iov;
rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE;

oparms = (struct cifs_open_parms) {
.tcon = tcon,
.path = full_path,
.desired_access = FILE_READ_ATTRIBUTES,
.disposition = FILE_OPEN,
.create_options = cifs_create_options(cifs_sb, OPEN_REPARSE_POINT),
.fid = &fid,
};

rc = SMB2_open_init(tcon, server,
&rqst[0], &oplock, &oparms, utf16_path);
if (rc)
goto query_rp_exit;
smb2_set_next_command(tcon, &rqst[0]);


/* IOCTL */
rqst[1].rq_iov = vars->io_iov;
rqst[1].rq_nvec = SMB2_IOCTL_IOV_SIZE;

rc = SMB2_ioctl_init(tcon, server,
&rqst[1], COMPOUND_FID,
COMPOUND_FID, FSCTL_GET_REPARSE_POINT, NULL, 0,
CIFSMaxBufSize -
MAX_SMB2_CREATE_RESPONSE_SIZE -
MAX_SMB2_CLOSE_RESPONSE_SIZE);
if (rc)
goto query_rp_exit;

smb2_set_next_command(tcon, &rqst[1]);
smb2_set_related(&rqst[1]);

/* Close */
rqst[2].rq_iov = &vars->close_iov;
rqst[2].rq_nvec = 1;

rc = SMB2_close_init(tcon, server,
&rqst[2], COMPOUND_FID, COMPOUND_FID, false);
if (rc)
goto query_rp_exit;

smb2_set_related(&rqst[2]);

rc = compound_send_recv(xid, tcon->ses, server,
flags, 3, rqst,
resp_buftype, rsp_iov);

ioctl_rsp = rsp_iov[1].iov_base;

/*
* Open was successful and we got an ioctl response.
*/
if (rc == 0) {
/* See MS-FSCC 2.3.23 */
off = le32_to_cpu(ioctl_rsp->OutputOffset);
count = le32_to_cpu(ioctl_rsp->OutputCount);
if (check_add_overflow(off, count, &len) ||
len > rsp_iov[1].iov_len) {
cifs_tcon_dbg(VFS, "%s: invalid ioctl: off=%d count=%d\n",
__func__, off, count);
rc = -EIO;
goto query_rp_exit;
}

reparse_buf = (void *)((u8 *)ioctl_rsp + off);
len = sizeof(*reparse_buf);
if (count < len ||
count < le16_to_cpu(reparse_buf->ReparseDataLength) + len) {
cifs_tcon_dbg(VFS, "%s: invalid ioctl: off=%d count=%d\n",
__func__, off, count);
rc = -EIO;
goto query_rp_exit;
}
*tag = le32_to_cpu(reparse_buf->ReparseTag);
*rsp = rsp_iov[1];
*rsp_buftype = resp_buftype[1];
resp_buftype[1] = CIFS_NO_BUFFER;
}

query_rp_exit:
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);
kfree(vars);
out_free_path:
kfree(utf16_path);
return rc;
}

static struct cifs_ntsd *
get_smb2_acl_by_fid(struct cifs_sb_info *cifs_sb,
const struct cifs_fid *cifsfid, u32 *pacllen, u32 info)
Expand Down
6 changes: 6 additions & 0 deletions fs/smb/client/smb2proto.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ struct inode *smb2_get_reparse_inode(struct cifs_open_info_data *data,
struct cifs_tcon *tcon,
const char *full_path,
struct kvec *iov);
int smb2_query_reparse_point(const unsigned int xid,
struct cifs_tcon *tcon,
struct cifs_sb_info *cifs_sb,
const char *full_path,
u32 *tag, struct kvec *rsp,
int *rsp_buftype);
int smb2_query_path_info(const unsigned int xid,
struct cifs_tcon *tcon,
struct cifs_sb_info *cifs_sb,
Expand Down

0 comments on commit 3ded18a

Please sign in to comment.