mirror of
https://git.proxmox.com/git/mirror_ubuntu-kernels.git
synced 2025-11-25 22:29:43 +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;
|
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);
|
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 *
|
static struct cifs_ntsd *
|
||||||
get_smb2_acl_by_fid(struct cifs_sb_info *cifs_sb,
|
get_smb2_acl_by_fid(struct cifs_sb_info *cifs_sb,
|
||||||
const struct cifs_fid *cifsfid, u32 *pacllen, u32 info)
|
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,
|
struct cifs_tcon *tcon,
|
||||||
const char *full_path,
|
const char *full_path,
|
||||||
struct kvec *iov);
|
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,
|
int smb2_query_path_info(const unsigned int xid,
|
||||||
struct cifs_tcon *tcon,
|
struct cifs_tcon *tcon,
|
||||||
struct cifs_sb_info *cifs_sb,
|
struct cifs_sb_info *cifs_sb,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user