mirror of
https://git.proxmox.com/git/mirror_ubuntu-kernels.git
synced 2025-11-25 16:33:36 +00:00
smb: client: cleanup smb2_query_reparse_point()
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>
This commit is contained in:
parent
514d793e27
commit
3ded18a9e9
@ -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;
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user