mirror of
https://github.com/torvalds/linux.git
synced 2024-12-11 05:33:09 +00:00
Merge branch 'for-next' of git://git.samba.org/sfrench/cifs-2.6
Pull CIFS fixes from Steve French. * 'for-next' of git://git.samba.org/sfrench/cifs-2.6: (40 commits) cifs: ensure that we always do cifsFileInfo_get under the spinlock CIFS: Make CAP_* checks protocol independent CIFS: Allow SMB2 statistics to be tracked CIFS: Move clear/print_stats code to ops struct CIFS: Add echo request support for SMB2 CIFS: Move echo code to osp struct CIFS: Add SMB2 support for async requests CIFS: Setup async request in ops struct CIFS: Add SMB2 support for build_path_to_root CIFS: Move building path to root to ops struct CIFS: Query SMB2 inode info CIFS: Move query inode info code to ops struct CIFS: Add SMB2 support for is_path_accessible CIFS: Move is_path_accessible to ops struct CIFS: Move informational tcon calls to ops struct CIFS: Move getting dfs referalls to ops struct CIFS: Process reconnects for SMB2 shares CIFS: Add tree connect/disconnect capability for SMB2 CIFS: Add session setup/logoff capability for SMB2 CIFS: Add capability to send SMB2 negotiate message ...
This commit is contained in:
commit
98077a7205
@ -16,4 +16,5 @@ cifs-$(CONFIG_CIFS_DFS_UPCALL) += dns_resolve.o cifs_dfs_ref.o
|
||||
|
||||
cifs-$(CONFIG_CIFS_FSCACHE) += fscache.o cache.o
|
||||
|
||||
cifs-$(CONFIG_CIFS_SMB2) += smb2ops.o
|
||||
cifs-$(CONFIG_CIFS_SMB2) += smb2ops.o smb2maperror.o smb2transport.o \
|
||||
smb2misc.o smb2pdu.o smb2inode.o
|
||||
|
@ -152,7 +152,7 @@ static uint16_t cifs_super_get_key(const void *cookie_netfs_data, void *buffer,
|
||||
|
||||
sharename = extract_sharename(tcon->treeName);
|
||||
if (IS_ERR(sharename)) {
|
||||
cFYI(1, "%s: couldn't extract sharename\n", __func__);
|
||||
cFYI(1, "%s: couldn't extract sharename", __func__);
|
||||
sharename = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ void cifs_dump_detail(void *buf)
|
||||
cERROR(1, "Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d",
|
||||
smb->Command, smb->Status.CifsError,
|
||||
smb->Flags, smb->Flags2, smb->Mid, smb->Pid);
|
||||
cERROR(1, "smb buf %p len %d", smb, smbCalcSize(smb));
|
||||
cERROR(1, "smb buf %p len %u", smb, smbCalcSize(smb));
|
||||
#endif /* CONFIG_CIFS_DEBUG2 */
|
||||
}
|
||||
|
||||
@ -282,24 +282,8 @@ static ssize_t cifs_stats_proc_write(struct file *file,
|
||||
struct cifs_tcon,
|
||||
tcon_list);
|
||||
atomic_set(&tcon->num_smbs_sent, 0);
|
||||
atomic_set(&tcon->num_writes, 0);
|
||||
atomic_set(&tcon->num_reads, 0);
|
||||
atomic_set(&tcon->num_oplock_brks, 0);
|
||||
atomic_set(&tcon->num_opens, 0);
|
||||
atomic_set(&tcon->num_posixopens, 0);
|
||||
atomic_set(&tcon->num_posixmkdirs, 0);
|
||||
atomic_set(&tcon->num_closes, 0);
|
||||
atomic_set(&tcon->num_deletes, 0);
|
||||
atomic_set(&tcon->num_mkdirs, 0);
|
||||
atomic_set(&tcon->num_rmdirs, 0);
|
||||
atomic_set(&tcon->num_renames, 0);
|
||||
atomic_set(&tcon->num_t2renames, 0);
|
||||
atomic_set(&tcon->num_ffirst, 0);
|
||||
atomic_set(&tcon->num_fnext, 0);
|
||||
atomic_set(&tcon->num_fclose, 0);
|
||||
atomic_set(&tcon->num_hardlinks, 0);
|
||||
atomic_set(&tcon->num_symlinks, 0);
|
||||
atomic_set(&tcon->num_locks, 0);
|
||||
if (server->ops->clear_stats)
|
||||
server->ops->clear_stats(tcon);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -358,42 +342,10 @@ static int cifs_stats_proc_show(struct seq_file *m, void *v)
|
||||
seq_printf(m, "\n%d) %s", i, tcon->treeName);
|
||||
if (tcon->need_reconnect)
|
||||
seq_puts(m, "\tDISCONNECTED ");
|
||||
seq_printf(m, "\nSMBs: %d Oplock Breaks: %d",
|
||||
atomic_read(&tcon->num_smbs_sent),
|
||||
atomic_read(&tcon->num_oplock_brks));
|
||||
seq_printf(m, "\nReads: %d Bytes: %lld",
|
||||
atomic_read(&tcon->num_reads),
|
||||
(long long)(tcon->bytes_read));
|
||||
seq_printf(m, "\nWrites: %d Bytes: %lld",
|
||||
atomic_read(&tcon->num_writes),
|
||||
(long long)(tcon->bytes_written));
|
||||
seq_printf(m, "\nFlushes: %d",
|
||||
atomic_read(&tcon->num_flushes));
|
||||
seq_printf(m, "\nLocks: %d HardLinks: %d "
|
||||
"Symlinks: %d",
|
||||
atomic_read(&tcon->num_locks),
|
||||
atomic_read(&tcon->num_hardlinks),
|
||||
atomic_read(&tcon->num_symlinks));
|
||||
seq_printf(m, "\nOpens: %d Closes: %d "
|
||||
"Deletes: %d",
|
||||
atomic_read(&tcon->num_opens),
|
||||
atomic_read(&tcon->num_closes),
|
||||
atomic_read(&tcon->num_deletes));
|
||||
seq_printf(m, "\nPosix Opens: %d "
|
||||
"Posix Mkdirs: %d",
|
||||
atomic_read(&tcon->num_posixopens),
|
||||
atomic_read(&tcon->num_posixmkdirs));
|
||||
seq_printf(m, "\nMkdirs: %d Rmdirs: %d",
|
||||
atomic_read(&tcon->num_mkdirs),
|
||||
atomic_read(&tcon->num_rmdirs));
|
||||
seq_printf(m, "\nRenames: %d T2 Renames %d",
|
||||
atomic_read(&tcon->num_renames),
|
||||
atomic_read(&tcon->num_t2renames));
|
||||
seq_printf(m, "\nFindFirst: %d FNext %d "
|
||||
"FClose %d",
|
||||
atomic_read(&tcon->num_ffirst),
|
||||
atomic_read(&tcon->num_fnext),
|
||||
atomic_read(&tcon->num_fclose));
|
||||
seq_printf(m, "\nSMBs: %d",
|
||||
atomic_read(&tcon->num_smbs_sent));
|
||||
if (server->ops->print_stats)
|
||||
server->ops->print_stats(m, tcon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -275,7 +275,8 @@ static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt)
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
struct cifs_ses *ses;
|
||||
char *full_path;
|
||||
int xid, i;
|
||||
unsigned int xid;
|
||||
int i;
|
||||
int rc;
|
||||
struct vfsmount *mnt;
|
||||
struct tcon_link *tlink;
|
||||
@ -302,11 +303,11 @@ static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt)
|
||||
}
|
||||
ses = tlink_tcon(tlink)->ses;
|
||||
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
rc = get_dfs_path(xid, ses, full_path + 1, cifs_sb->local_nls,
|
||||
&num_referrals, &referrals,
|
||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
|
||||
cifs_put_tlink(tlink);
|
||||
|
||||
|
@ -331,3 +331,63 @@ ctoUTF16_out:
|
||||
return i;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CIFS_SMB2
|
||||
/*
|
||||
* cifs_local_to_utf16_bytes - how long will a string be after conversion?
|
||||
* @from - pointer to input string
|
||||
* @maxbytes - don't go past this many bytes of input string
|
||||
* @codepage - source codepage
|
||||
*
|
||||
* Walk a string and return the number of bytes that the string will
|
||||
* be after being converted to the given charset, not including any null
|
||||
* termination required. Don't walk past maxbytes in the source buffer.
|
||||
*/
|
||||
|
||||
static int
|
||||
cifs_local_to_utf16_bytes(const char *from, int len,
|
||||
const struct nls_table *codepage)
|
||||
{
|
||||
int charlen;
|
||||
int i;
|
||||
wchar_t wchar_to;
|
||||
|
||||
for (i = 0; len && *from; i++, from += charlen, len -= charlen) {
|
||||
charlen = codepage->char2uni(from, len, &wchar_to);
|
||||
/* Failed conversion defaults to a question mark */
|
||||
if (charlen < 1)
|
||||
charlen = 1;
|
||||
}
|
||||
return 2 * i; /* UTF16 characters are two bytes */
|
||||
}
|
||||
|
||||
/*
|
||||
* cifs_strndup_to_utf16 - copy a string to wire format from the local codepage
|
||||
* @src - source string
|
||||
* @maxlen - don't walk past this many bytes in the source string
|
||||
* @utf16_len - the length of the allocated string in bytes (including null)
|
||||
* @cp - source codepage
|
||||
* @remap - map special chars
|
||||
*
|
||||
* Take a string convert it from the local codepage to UTF16 and
|
||||
* put it in a new buffer. Returns a pointer to the new string or NULL on
|
||||
* error.
|
||||
*/
|
||||
__le16 *
|
||||
cifs_strndup_to_utf16(const char *src, const int maxlen, int *utf16_len,
|
||||
const struct nls_table *cp, int remap)
|
||||
{
|
||||
int len;
|
||||
__le16 *dst;
|
||||
|
||||
len = cifs_local_to_utf16_bytes(src, maxlen, cp);
|
||||
len += 2; /* NULL */
|
||||
dst = kmalloc(len, GFP_KERNEL);
|
||||
if (!dst) {
|
||||
*utf16_len = 0;
|
||||
return NULL;
|
||||
}
|
||||
cifsConvertToUTF16(dst, src, strlen(src), cp, remap);
|
||||
*utf16_len = len;
|
||||
return dst;
|
||||
}
|
||||
#endif /* CONFIG_CIFS_SMB2 */
|
||||
|
@ -84,7 +84,11 @@ char *cifs_strndup_from_utf16(const char *src, const int maxlen,
|
||||
const struct nls_table *codepage);
|
||||
extern int cifsConvertToUTF16(__le16 *target, const char *source, int maxlen,
|
||||
const struct nls_table *cp, int mapChars);
|
||||
|
||||
#ifdef CONFIG_CIFS_SMB2
|
||||
extern __le16 *cifs_strndup_to_utf16(const char *src, const int maxlen,
|
||||
int *utf16_len, const struct nls_table *cp,
|
||||
int remap);
|
||||
#endif /* CONFIG_CIFS_SMB2 */
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -525,7 +525,7 @@ init_cifs_idmap(void)
|
||||
struct key *keyring;
|
||||
int ret;
|
||||
|
||||
cFYI(1, "Registering the %s key type\n", cifs_idmap_key_type.name);
|
||||
cFYI(1, "Registering the %s key type", cifs_idmap_key_type.name);
|
||||
|
||||
/* create an override credential set with a special thread keyring in
|
||||
* which requests are cached
|
||||
@ -572,7 +572,7 @@ init_cifs_idmap(void)
|
||||
sidgidtree = RB_ROOT;
|
||||
register_shrinker(&cifs_shrinker);
|
||||
|
||||
cFYI(1, "cifs idmap keyring: %d\n", key_serial(keyring));
|
||||
cFYI(1, "cifs idmap keyring: %d", key_serial(keyring));
|
||||
return 0;
|
||||
|
||||
failed_put_key:
|
||||
@ -589,7 +589,7 @@ exit_cifs_idmap(void)
|
||||
unregister_key_type(&cifs_idmap_key_type);
|
||||
put_cred(root_cred);
|
||||
unregister_shrinker(&cifs_shrinker);
|
||||
cFYI(1, "Unregistered %s key type\n", cifs_idmap_key_type.name);
|
||||
cFYI(1, "Unregistered %s key type", cifs_idmap_key_type.name);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1153,15 +1153,16 @@ static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
|
||||
__u16 fid, u32 *pacllen)
|
||||
{
|
||||
struct cifs_ntsd *pntsd = NULL;
|
||||
int xid, rc;
|
||||
unsigned int xid;
|
||||
int rc;
|
||||
struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
|
||||
|
||||
if (IS_ERR(tlink))
|
||||
return ERR_CAST(tlink);
|
||||
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), fid, &pntsd, pacllen);
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
|
||||
cifs_put_tlink(tlink);
|
||||
|
||||
@ -1176,7 +1177,8 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
|
||||
{
|
||||
struct cifs_ntsd *pntsd = NULL;
|
||||
int oplock = 0;
|
||||
int xid, rc, create_options = 0;
|
||||
unsigned int xid;
|
||||
int rc, create_options = 0;
|
||||
__u16 fid;
|
||||
struct cifs_tcon *tcon;
|
||||
struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
|
||||
@ -1185,7 +1187,7 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
|
||||
return ERR_CAST(tlink);
|
||||
|
||||
tcon = tlink_tcon(tlink);
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
|
||||
if (backup_cred(cifs_sb))
|
||||
create_options |= CREATE_OPEN_BACKUP_INTENT;
|
||||
@ -1199,7 +1201,7 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
|
||||
}
|
||||
|
||||
cifs_put_tlink(tlink);
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
|
||||
cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen);
|
||||
if (rc)
|
||||
@ -1230,7 +1232,8 @@ int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
|
||||
struct inode *inode, const char *path, int aclflag)
|
||||
{
|
||||
int oplock = 0;
|
||||
int xid, rc, access_flags, create_options = 0;
|
||||
unsigned int xid;
|
||||
int rc, access_flags, create_options = 0;
|
||||
__u16 fid;
|
||||
struct cifs_tcon *tcon;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
@ -1240,7 +1243,7 @@ int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
|
||||
return PTR_ERR(tlink);
|
||||
|
||||
tcon = tlink_tcon(tlink);
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
|
||||
if (backup_cred(cifs_sb))
|
||||
create_options |= CREATE_OPEN_BACKUP_INTENT;
|
||||
@ -1263,7 +1266,7 @@ int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
|
||||
|
||||
CIFSSMBClose(xid, tcon, fid);
|
||||
out:
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
cifs_put_tlink(tlink);
|
||||
return rc;
|
||||
}
|
||||
|
@ -47,20 +47,20 @@ static int cifs_calc_signature(const struct kvec *iov, int n_vec,
|
||||
return -EINVAL;
|
||||
|
||||
if (!server->secmech.sdescmd5) {
|
||||
cERROR(1, "%s: Can't generate signature\n", __func__);
|
||||
cERROR(1, "%s: Can't generate signature", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = crypto_shash_init(&server->secmech.sdescmd5->shash);
|
||||
if (rc) {
|
||||
cERROR(1, "%s: Could not init md5\n", __func__);
|
||||
cERROR(1, "%s: Could not init md5", __func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = crypto_shash_update(&server->secmech.sdescmd5->shash,
|
||||
server->session_key.response, server->session_key.len);
|
||||
if (rc) {
|
||||
cERROR(1, "%s: Could not update with response\n", __func__);
|
||||
cERROR(1, "%s: Could not update with response", __func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -85,7 +85,7 @@ static int cifs_calc_signature(const struct kvec *iov, int n_vec,
|
||||
iov[i].iov_base, iov[i].iov_len);
|
||||
}
|
||||
if (rc) {
|
||||
cERROR(1, "%s: Could not update with payload\n",
|
||||
cERROR(1, "%s: Could not update with payload",
|
||||
__func__);
|
||||
return rc;
|
||||
}
|
||||
@ -93,13 +93,13 @@ static int cifs_calc_signature(const struct kvec *iov, int n_vec,
|
||||
|
||||
rc = crypto_shash_final(&server->secmech.sdescmd5->shash, signature);
|
||||
if (rc)
|
||||
cERROR(1, "%s: Could not generate md5 hash\n", __func__);
|
||||
cERROR(1, "%s: Could not generate md5 hash", __func__);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* must be called with server->srv_mutex held */
|
||||
int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
|
||||
int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
|
||||
__u32 *pexpected_response_sequence_number)
|
||||
{
|
||||
int rc = 0;
|
||||
@ -143,7 +143,7 @@ int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
|
||||
iov.iov_base = cifs_pdu;
|
||||
iov.iov_len = be32_to_cpu(cifs_pdu->smb_buf_length) + 4;
|
||||
|
||||
return cifs_sign_smb2(&iov, 1, server,
|
||||
return cifs_sign_smbv(&iov, 1, server,
|
||||
pexpected_response_sequence_number);
|
||||
}
|
||||
|
||||
@ -399,7 +399,7 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
|
||||
wchar_t *server;
|
||||
|
||||
if (!ses->server->secmech.sdeschmacmd5) {
|
||||
cERROR(1, "calc_ntlmv2_hash: can't generate ntlmv2 hash\n");
|
||||
cERROR(1, "calc_ntlmv2_hash: can't generate ntlmv2 hash");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -415,7 +415,7 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
|
||||
|
||||
rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
|
||||
if (rc) {
|
||||
cERROR(1, "calc_ntlmv2_hash: could not init hmacmd5\n");
|
||||
cERROR(1, "calc_ntlmv2_hash: could not init hmacmd5");
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -423,7 +423,7 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
|
||||
len = ses->user_name ? strlen(ses->user_name) : 0;
|
||||
user = kmalloc(2 + (len * 2), GFP_KERNEL);
|
||||
if (user == NULL) {
|
||||
cERROR(1, "calc_ntlmv2_hash: user mem alloc failure\n");
|
||||
cERROR(1, "calc_ntlmv2_hash: user mem alloc failure");
|
||||
rc = -ENOMEM;
|
||||
return rc;
|
||||
}
|
||||
@ -439,7 +439,7 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
|
||||
(char *)user, 2 * len);
|
||||
kfree(user);
|
||||
if (rc) {
|
||||
cERROR(1, "%s: Could not update with user\n", __func__);
|
||||
cERROR(1, "%s: Could not update with user", __func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -460,7 +460,7 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
|
||||
(char *)domain, 2 * len);
|
||||
kfree(domain);
|
||||
if (rc) {
|
||||
cERROR(1, "%s: Could not update with domain\n",
|
||||
cERROR(1, "%s: Could not update with domain",
|
||||
__func__);
|
||||
return rc;
|
||||
}
|
||||
@ -480,7 +480,7 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
|
||||
(char *)server, 2 * len);
|
||||
kfree(server);
|
||||
if (rc) {
|
||||
cERROR(1, "%s: Could not update with server\n",
|
||||
cERROR(1, "%s: Could not update with server",
|
||||
__func__);
|
||||
return rc;
|
||||
}
|
||||
@ -489,7 +489,7 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
|
||||
rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
|
||||
ntlmv2_hash);
|
||||
if (rc)
|
||||
cERROR(1, "%s: Could not generate md5 hash\n", __func__);
|
||||
cERROR(1, "%s: Could not generate md5 hash", __func__);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@ -501,7 +501,7 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash)
|
||||
unsigned int offset = CIFS_SESS_KEY_SIZE + 8;
|
||||
|
||||
if (!ses->server->secmech.sdeschmacmd5) {
|
||||
cERROR(1, "calc_ntlmv2_hash: can't generate ntlmv2 hash\n");
|
||||
cERROR(1, "calc_ntlmv2_hash: can't generate ntlmv2 hash");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -527,14 +527,14 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash)
|
||||
rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
|
||||
ses->auth_key.response + offset, ses->auth_key.len - offset);
|
||||
if (rc) {
|
||||
cERROR(1, "%s: Could not update with response\n", __func__);
|
||||
cERROR(1, "%s: Could not update with response", __func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
|
||||
ses->auth_key.response + CIFS_SESS_KEY_SIZE);
|
||||
if (rc)
|
||||
cERROR(1, "%s: Could not generate md5 hash\n", __func__);
|
||||
cERROR(1, "%s: Could not generate md5 hash", __func__);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@ -613,7 +613,7 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
|
||||
|
||||
rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
|
||||
if (rc) {
|
||||
cERROR(1, "%s: Could not init hmacmd5\n", __func__);
|
||||
cERROR(1, "%s: Could not init hmacmd5", __func__);
|
||||
goto setup_ntlmv2_rsp_ret;
|
||||
}
|
||||
|
||||
@ -621,14 +621,14 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
|
||||
ses->auth_key.response + CIFS_SESS_KEY_SIZE,
|
||||
CIFS_HMAC_MD5_HASH_SIZE);
|
||||
if (rc) {
|
||||
cERROR(1, "%s: Could not update with response\n", __func__);
|
||||
cERROR(1, "%s: Could not update with response", __func__);
|
||||
goto setup_ntlmv2_rsp_ret;
|
||||
}
|
||||
|
||||
rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
|
||||
ses->auth_key.response);
|
||||
if (rc)
|
||||
cERROR(1, "%s: Could not generate md5 hash\n", __func__);
|
||||
cERROR(1, "%s: Could not generate md5 hash", __func__);
|
||||
|
||||
setup_ntlmv2_rsp_ret:
|
||||
kfree(tiblob);
|
||||
@ -650,7 +650,7 @@ calc_seckey(struct cifs_ses *ses)
|
||||
tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
|
||||
if (IS_ERR(tfm_arc4)) {
|
||||
rc = PTR_ERR(tfm_arc4);
|
||||
cERROR(1, "could not allocate crypto API arc4\n");
|
||||
cERROR(1, "could not allocate crypto API arc4");
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -668,7 +668,7 @@ calc_seckey(struct cifs_ses *ses)
|
||||
|
||||
rc = crypto_blkcipher_encrypt(&desc, &sgout, &sgin, CIFS_CPHTXT_SIZE);
|
||||
if (rc) {
|
||||
cERROR(1, "could not encrypt session key rc: %d\n", rc);
|
||||
cERROR(1, "could not encrypt session key rc: %d", rc);
|
||||
crypto_free_blkcipher(tfm_arc4);
|
||||
return rc;
|
||||
}
|
||||
@ -705,13 +705,13 @@ cifs_crypto_shash_allocate(struct TCP_Server_Info *server)
|
||||
|
||||
server->secmech.hmacmd5 = crypto_alloc_shash("hmac(md5)", 0, 0);
|
||||
if (IS_ERR(server->secmech.hmacmd5)) {
|
||||
cERROR(1, "could not allocate crypto hmacmd5\n");
|
||||
cERROR(1, "could not allocate crypto hmacmd5");
|
||||
return PTR_ERR(server->secmech.hmacmd5);
|
||||
}
|
||||
|
||||
server->secmech.md5 = crypto_alloc_shash("md5", 0, 0);
|
||||
if (IS_ERR(server->secmech.md5)) {
|
||||
cERROR(1, "could not allocate crypto md5\n");
|
||||
cERROR(1, "could not allocate crypto md5");
|
||||
rc = PTR_ERR(server->secmech.md5);
|
||||
goto crypto_allocate_md5_fail;
|
||||
}
|
||||
@ -720,7 +720,7 @@ cifs_crypto_shash_allocate(struct TCP_Server_Info *server)
|
||||
crypto_shash_descsize(server->secmech.hmacmd5);
|
||||
server->secmech.sdeschmacmd5 = kmalloc(size, GFP_KERNEL);
|
||||
if (!server->secmech.sdeschmacmd5) {
|
||||
cERROR(1, "cifs_crypto_shash_allocate: can't alloc hmacmd5\n");
|
||||
cERROR(1, "cifs_crypto_shash_allocate: can't alloc hmacmd5");
|
||||
rc = -ENOMEM;
|
||||
goto crypto_allocate_hmacmd5_sdesc_fail;
|
||||
}
|
||||
@ -732,7 +732,7 @@ cifs_crypto_shash_allocate(struct TCP_Server_Info *server)
|
||||
crypto_shash_descsize(server->secmech.md5);
|
||||
server->secmech.sdescmd5 = kmalloc(size, GFP_KERNEL);
|
||||
if (!server->secmech.sdescmd5) {
|
||||
cERROR(1, "cifs_crypto_shash_allocate: can't alloc md5\n");
|
||||
cERROR(1, "cifs_crypto_shash_allocate: can't alloc md5");
|
||||
rc = -ENOMEM;
|
||||
goto crypto_allocate_md5_sdesc_fail;
|
||||
}
|
||||
|
@ -48,6 +48,9 @@
|
||||
#include <linux/key-type.h>
|
||||
#include "cifs_spnego.h"
|
||||
#include "fscache.h"
|
||||
#ifdef CONFIG_CIFS_SMB2
|
||||
#include "smb2pdu.h"
|
||||
#endif
|
||||
#define CIFS_MAGIC_NUMBER 0xFF534D42 /* the first four bytes of SMB PDUs */
|
||||
|
||||
int cifsFYI = 0;
|
||||
@ -158,9 +161,9 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
|
||||
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
|
||||
int rc = -EOPNOTSUPP;
|
||||
int xid;
|
||||
unsigned int xid;
|
||||
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
|
||||
buf->f_type = CIFS_MAGIC_NUMBER;
|
||||
|
||||
@ -197,7 +200,7 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
|
||||
if (rc)
|
||||
rc = SMBOldQFSInfo(xid, tcon, buf);
|
||||
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -546,8 +549,8 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb)
|
||||
char *s, *p;
|
||||
char sep;
|
||||
|
||||
full_path = cifs_build_path_to_root(vol, cifs_sb,
|
||||
cifs_sb_master_tcon(cifs_sb));
|
||||
full_path = build_path_to_root(vol, cifs_sb,
|
||||
cifs_sb_master_tcon(cifs_sb));
|
||||
if (full_path == NULL)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
@ -980,6 +983,14 @@ cifs_destroy_inodecache(void)
|
||||
static int
|
||||
cifs_init_request_bufs(void)
|
||||
{
|
||||
size_t max_hdr_size = MAX_CIFS_HDR_SIZE;
|
||||
#ifdef CONFIG_CIFS_SMB2
|
||||
/*
|
||||
* SMB2 maximum header size is bigger than CIFS one - no problems to
|
||||
* allocate some more bytes for CIFS.
|
||||
*/
|
||||
max_hdr_size = MAX_SMB2_HDR_SIZE;
|
||||
#endif
|
||||
if (CIFSMaxBufSize < 8192) {
|
||||
/* Buffer size can not be smaller than 2 * PATH_MAX since maximum
|
||||
Unicode path name has to fit in any SMB/CIFS path based frames */
|
||||
@ -991,8 +1002,7 @@ cifs_init_request_bufs(void)
|
||||
}
|
||||
/* cERROR(1, "CIFSMaxBufSize %d 0x%x",CIFSMaxBufSize,CIFSMaxBufSize); */
|
||||
cifs_req_cachep = kmem_cache_create("cifs_request",
|
||||
CIFSMaxBufSize +
|
||||
MAX_CIFS_HDR_SIZE, 0,
|
||||
CIFSMaxBufSize + max_hdr_size, 0,
|
||||
SLAB_HWCACHE_ALIGN, NULL);
|
||||
if (cifs_req_cachep == NULL)
|
||||
return -ENOMEM;
|
||||
|
@ -22,11 +22,15 @@
|
||||
#include <linux/in.h>
|
||||
#include <linux/in6.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mempool.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include "cifs_fs_sb.h"
|
||||
#include "cifsacl.h"
|
||||
#include <crypto/internal/hash.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#ifdef CONFIG_CIFS_SMB2
|
||||
#include "smb2pdu.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The sizes of various internal tables and strings
|
||||
@ -72,6 +76,9 @@
|
||||
/* (max path length + 1 for null) * 2 for unicode */
|
||||
#define MAX_NAME 514
|
||||
|
||||
/* SMB echo "timeout" -- FIXME: tunable? */
|
||||
#define SMB_ECHO_INTERVAL (60 * HZ)
|
||||
|
||||
#include "cifspdu.h"
|
||||
|
||||
#ifndef XATTR_DOS_ATTRIB
|
||||
@ -160,6 +167,10 @@ struct mid_q_entry;
|
||||
struct TCP_Server_Info;
|
||||
struct cifsFileInfo;
|
||||
struct cifs_ses;
|
||||
struct cifs_tcon;
|
||||
struct dfs_info3_param;
|
||||
struct cifs_fattr;
|
||||
struct smb_vol;
|
||||
|
||||
struct smb_version_operations {
|
||||
int (*send_cancel)(struct TCP_Server_Info *, void *,
|
||||
@ -168,12 +179,17 @@ struct smb_version_operations {
|
||||
/* setup request: allocate mid, sign message */
|
||||
int (*setup_request)(struct cifs_ses *, struct kvec *, unsigned int,
|
||||
struct mid_q_entry **);
|
||||
/* setup async request: allocate mid, sign message */
|
||||
int (*setup_async_request)(struct TCP_Server_Info *, struct kvec *,
|
||||
unsigned int, struct mid_q_entry **);
|
||||
/* check response: verify signature, map error */
|
||||
int (*check_receive)(struct mid_q_entry *, struct TCP_Server_Info *,
|
||||
bool);
|
||||
void (*add_credits)(struct TCP_Server_Info *, const unsigned int);
|
||||
void (*add_credits)(struct TCP_Server_Info *, const unsigned int,
|
||||
const int);
|
||||
void (*set_credits)(struct TCP_Server_Info *, const int);
|
||||
int * (*get_credits_field)(struct TCP_Server_Info *);
|
||||
int * (*get_credits_field)(struct TCP_Server_Info *, const int);
|
||||
unsigned int (*get_credits)(struct mid_q_entry *);
|
||||
__u64 (*get_next_mid)(struct TCP_Server_Info *);
|
||||
/* data offset from read response message */
|
||||
unsigned int (*read_data_offset)(char *);
|
||||
@ -184,9 +200,52 @@ struct smb_version_operations {
|
||||
/* find mid corresponding to the response message */
|
||||
struct mid_q_entry * (*find_mid)(struct TCP_Server_Info *, char *);
|
||||
void (*dump_detail)(void *);
|
||||
void (*clear_stats)(struct cifs_tcon *);
|
||||
void (*print_stats)(struct seq_file *m, struct cifs_tcon *);
|
||||
/* verify the message */
|
||||
int (*check_message)(char *, unsigned int);
|
||||
bool (*is_oplock_break)(char *, struct TCP_Server_Info *);
|
||||
/* process transaction2 response */
|
||||
bool (*check_trans2)(struct mid_q_entry *, struct TCP_Server_Info *,
|
||||
char *, int);
|
||||
/* check if we need to negotiate */
|
||||
bool (*need_neg)(struct TCP_Server_Info *);
|
||||
/* negotiate to the server */
|
||||
int (*negotiate)(const unsigned int, struct cifs_ses *);
|
||||
/* setup smb sessionn */
|
||||
int (*sess_setup)(const unsigned int, struct cifs_ses *,
|
||||
const struct nls_table *);
|
||||
/* close smb session */
|
||||
int (*logoff)(const unsigned int, struct cifs_ses *);
|
||||
/* connect to a server share */
|
||||
int (*tree_connect)(const unsigned int, struct cifs_ses *, const char *,
|
||||
struct cifs_tcon *, const struct nls_table *);
|
||||
/* close tree connecion */
|
||||
int (*tree_disconnect)(const unsigned int, struct cifs_tcon *);
|
||||
/* get DFS referrals */
|
||||
int (*get_dfs_refer)(const unsigned int, struct cifs_ses *,
|
||||
const char *, struct dfs_info3_param **,
|
||||
unsigned int *, const struct nls_table *, int);
|
||||
/* informational QFS call */
|
||||
void (*qfs_tcon)(const unsigned int, struct cifs_tcon *);
|
||||
/* check if a path is accessible or not */
|
||||
int (*is_path_accessible)(const unsigned int, struct cifs_tcon *,
|
||||
struct cifs_sb_info *, const char *);
|
||||
/* query path data from the server */
|
||||
int (*query_path_info)(const unsigned int, struct cifs_tcon *,
|
||||
struct cifs_sb_info *, const char *,
|
||||
FILE_ALL_INFO *, bool *);
|
||||
/* get server index number */
|
||||
int (*get_srv_inum)(const unsigned int, struct cifs_tcon *,
|
||||
struct cifs_sb_info *, const char *,
|
||||
u64 *uniqueid, FILE_ALL_INFO *);
|
||||
/* build a full path to the root of the mount */
|
||||
char * (*build_path_to_root)(struct smb_vol *, struct cifs_sb_info *,
|
||||
struct cifs_tcon *);
|
||||
/* check if we can send an echo or nor */
|
||||
bool (*can_echo)(struct TCP_Server_Info *);
|
||||
/* send echo request */
|
||||
int (*echo)(struct TCP_Server_Info *);
|
||||
};
|
||||
|
||||
struct smb_version_values {
|
||||
@ -198,6 +257,10 @@ struct smb_version_values {
|
||||
size_t header_size;
|
||||
size_t max_header_size;
|
||||
size_t read_rsp_size;
|
||||
__le16 lock_cmd;
|
||||
unsigned int cap_unix;
|
||||
unsigned int cap_nt_find;
|
||||
unsigned int cap_large_files;
|
||||
};
|
||||
|
||||
#define HEADER_SIZE(server) (server->vals->header_size)
|
||||
@ -291,6 +354,12 @@ get_rfc1002_length(void *buf)
|
||||
return be32_to_cpu(*((__be32 *)buf));
|
||||
}
|
||||
|
||||
static inline void
|
||||
inc_rfc1001_len(void *buf, int count)
|
||||
{
|
||||
be32_add_cpu((__be32 *)buf, count);
|
||||
}
|
||||
|
||||
struct TCP_Server_Info {
|
||||
struct list_head tcp_ses_list;
|
||||
struct list_head smb_ses_list;
|
||||
@ -319,8 +388,13 @@ struct TCP_Server_Info {
|
||||
struct mutex srv_mutex;
|
||||
struct task_struct *tsk;
|
||||
char server_GUID[16];
|
||||
char sec_mode;
|
||||
__u16 sec_mode;
|
||||
bool session_estab; /* mark when very first sess is established */
|
||||
#ifdef CONFIG_CIFS_SMB2
|
||||
int echo_credits; /* echo reserved slots */
|
||||
int oplock_credits; /* oplock break reserved slots */
|
||||
bool echoes:1; /* enable echoes */
|
||||
#endif
|
||||
u16 dialect; /* dialect index that server chose */
|
||||
enum securityEnum secType;
|
||||
bool oplocks:1; /* enable oplocks */
|
||||
@ -337,7 +411,7 @@ struct TCP_Server_Info {
|
||||
unsigned int max_vcs; /* maximum number of smb sessions, at least
|
||||
those that can be specified uniquely with
|
||||
vcnumbers */
|
||||
int capabilities; /* allow selective disabling of caps by smb sess */
|
||||
unsigned int capabilities; /* selective disabling of caps by smb sess */
|
||||
int timeAdj; /* Adjust for difference in server time zone in sec */
|
||||
__u64 CurrentMid; /* multiplex id - rotating counter */
|
||||
char cryptkey[CIFS_CRYPTO_KEY_SIZE]; /* used by ntlm, ntlmv2 etc */
|
||||
@ -366,6 +440,10 @@ struct TCP_Server_Info {
|
||||
atomic_t in_send; /* requests trying to send */
|
||||
atomic_t num_waiters; /* blocked waiting to get in sendrecv */
|
||||
#endif
|
||||
#ifdef CONFIG_CIFS_SMB2
|
||||
unsigned int max_read;
|
||||
unsigned int max_write;
|
||||
#endif /* CONFIG_CIFS_SMB2 */
|
||||
};
|
||||
|
||||
static inline unsigned int
|
||||
@ -389,9 +467,10 @@ has_credits(struct TCP_Server_Info *server, int *credits)
|
||||
}
|
||||
|
||||
static inline void
|
||||
add_credits(struct TCP_Server_Info *server, const unsigned int add)
|
||||
add_credits(struct TCP_Server_Info *server, const unsigned int add,
|
||||
const int optype)
|
||||
{
|
||||
server->ops->add_credits(server, add);
|
||||
server->ops->add_credits(server, add, optype);
|
||||
}
|
||||
|
||||
static inline void
|
||||
@ -453,10 +532,10 @@ struct cifs_ses {
|
||||
char *serverOS; /* name of operating system underlying server */
|
||||
char *serverNOS; /* name of network operating system of server */
|
||||
char *serverDomain; /* security realm of server */
|
||||
int Suid; /* remote smb uid */
|
||||
__u64 Suid; /* remote smb uid */
|
||||
uid_t linux_uid; /* overriding owner of files on the mount */
|
||||
uid_t cred_uid; /* owner of credentials */
|
||||
int capabilities;
|
||||
unsigned int capabilities;
|
||||
char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for
|
||||
TCP names - will ipv6 and sctp addresses fit? */
|
||||
char *user_name; /* must not be null except during init of sess
|
||||
@ -466,6 +545,9 @@ struct cifs_ses {
|
||||
struct session_key auth_key;
|
||||
struct ntlmssp_auth *ntlmssp; /* ciphertext, flags, server challenge */
|
||||
bool need_reconnect:1; /* connection reset, uid now invalid */
|
||||
#ifdef CONFIG_CIFS_SMB2
|
||||
__u16 session_flags;
|
||||
#endif /* CONFIG_CIFS_SMB2 */
|
||||
};
|
||||
/* no more than one of the following three session flags may be set */
|
||||
#define CIFS_SES_NT4 1
|
||||
@ -475,6 +557,13 @@ struct cifs_ses {
|
||||
which do not negotiate NTLM or POSIX dialects, but instead
|
||||
negotiate one of the older LANMAN dialects */
|
||||
#define CIFS_SES_LANMAN 8
|
||||
|
||||
static inline bool
|
||||
cap_unix(struct cifs_ses *ses)
|
||||
{
|
||||
return ses->server->vals->cap_unix & ses->capabilities;
|
||||
}
|
||||
|
||||
/*
|
||||
* there is one of these for each connection to a resource on a particular
|
||||
* session
|
||||
@ -487,32 +576,42 @@ struct cifs_tcon {
|
||||
char treeName[MAX_TREE_SIZE + 1]; /* UNC name of resource in ASCII */
|
||||
char *nativeFileSystem;
|
||||
char *password; /* for share-level security */
|
||||
__u16 tid; /* The 2 byte tree id */
|
||||
__u32 tid; /* The 4 byte tree id */
|
||||
__u16 Flags; /* optional support bits */
|
||||
enum statusEnum tidStatus;
|
||||
#ifdef CONFIG_CIFS_STATS
|
||||
atomic_t num_smbs_sent;
|
||||
atomic_t num_writes;
|
||||
atomic_t num_reads;
|
||||
atomic_t num_flushes;
|
||||
atomic_t num_oplock_brks;
|
||||
atomic_t num_opens;
|
||||
atomic_t num_closes;
|
||||
atomic_t num_deletes;
|
||||
atomic_t num_mkdirs;
|
||||
atomic_t num_posixopens;
|
||||
atomic_t num_posixmkdirs;
|
||||
atomic_t num_rmdirs;
|
||||
atomic_t num_renames;
|
||||
atomic_t num_t2renames;
|
||||
atomic_t num_ffirst;
|
||||
atomic_t num_fnext;
|
||||
atomic_t num_fclose;
|
||||
atomic_t num_hardlinks;
|
||||
atomic_t num_symlinks;
|
||||
atomic_t num_locks;
|
||||
atomic_t num_acl_get;
|
||||
atomic_t num_acl_set;
|
||||
union {
|
||||
struct {
|
||||
atomic_t num_writes;
|
||||
atomic_t num_reads;
|
||||
atomic_t num_flushes;
|
||||
atomic_t num_oplock_brks;
|
||||
atomic_t num_opens;
|
||||
atomic_t num_closes;
|
||||
atomic_t num_deletes;
|
||||
atomic_t num_mkdirs;
|
||||
atomic_t num_posixopens;
|
||||
atomic_t num_posixmkdirs;
|
||||
atomic_t num_rmdirs;
|
||||
atomic_t num_renames;
|
||||
atomic_t num_t2renames;
|
||||
atomic_t num_ffirst;
|
||||
atomic_t num_fnext;
|
||||
atomic_t num_fclose;
|
||||
atomic_t num_hardlinks;
|
||||
atomic_t num_symlinks;
|
||||
atomic_t num_locks;
|
||||
atomic_t num_acl_get;
|
||||
atomic_t num_acl_set;
|
||||
} cifs_stats;
|
||||
#ifdef CONFIG_CIFS_SMB2
|
||||
struct {
|
||||
atomic_t smb2_com_sent[NUMBER_OF_SMB2_COMMANDS];
|
||||
atomic_t smb2_com_failed[NUMBER_OF_SMB2_COMMANDS];
|
||||
} smb2_stats;
|
||||
#endif /* CONFIG_CIFS_SMB2 */
|
||||
} stats;
|
||||
#ifdef CONFIG_CIFS_STATS2
|
||||
unsigned long long time_writes;
|
||||
unsigned long long time_reads;
|
||||
@ -543,6 +642,15 @@ struct cifs_tcon {
|
||||
bool local_lease:1; /* check leases (only) on local system not remote */
|
||||
bool broken_posix_open; /* e.g. Samba server versions < 3.3.2, 3.2.9 */
|
||||
bool need_reconnect:1; /* connection reset, tid now invalid */
|
||||
#ifdef CONFIG_CIFS_SMB2
|
||||
bool print:1; /* set if connection to printer share */
|
||||
bool bad_network_name:1; /* set if ret status STATUS_BAD_NETWORK_NAME */
|
||||
__u32 capabilities;
|
||||
__u32 share_flags;
|
||||
__u32 maximal_access;
|
||||
__u32 vol_serial_number;
|
||||
__le64 vol_create_time;
|
||||
#endif /* CONFIG_CIFS_SMB2 */
|
||||
#ifdef CONFIG_CIFS_FSCACHE
|
||||
u64 resource_id; /* server resource id */
|
||||
struct fscache_cookie *fscache; /* cookie for share */
|
||||
@ -657,13 +765,13 @@ struct cifs_io_parms {
|
||||
* Take a reference on the file private data. Must be called with
|
||||
* cifs_file_list_lock held.
|
||||
*/
|
||||
static inline
|
||||
struct cifsFileInfo *cifsFileInfo_get(struct cifsFileInfo *cifs_file)
|
||||
static inline void
|
||||
cifsFileInfo_get_locked(struct cifsFileInfo *cifs_file)
|
||||
{
|
||||
++cifs_file->count;
|
||||
return cifs_file;
|
||||
}
|
||||
|
||||
struct cifsFileInfo *cifsFileInfo_get(struct cifsFileInfo *cifs_file);
|
||||
void cifsFileInfo_put(struct cifsFileInfo *cifs_file);
|
||||
|
||||
/*
|
||||
@ -734,6 +842,15 @@ convert_delimiter(char *path, char delim)
|
||||
}
|
||||
}
|
||||
|
||||
static inline char *
|
||||
build_path_to_root(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
|
||||
struct cifs_tcon *tcon)
|
||||
{
|
||||
if (!vol->ops->build_path_to_root)
|
||||
return NULL;
|
||||
return vol->ops->build_path_to_root(vol, cifs_sb, tcon);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CIFS_STATS
|
||||
#define cifs_stats_inc atomic_inc
|
||||
|
||||
@ -791,6 +908,7 @@ typedef void (mid_callback_t)(struct mid_q_entry *mid);
|
||||
/* one of these for every pending CIFS request to the server */
|
||||
struct mid_q_entry {
|
||||
struct list_head qhead; /* mids waiting on reply from this server */
|
||||
struct TCP_Server_Info *server; /* server corresponding to this mid */
|
||||
__u64 mid; /* multiplex id */
|
||||
__u32 pid; /* process id */
|
||||
__u32 sequence_number; /* for CIFS signing */
|
||||
@ -954,6 +1072,12 @@ static inline void free_dfs_info_array(struct dfs_info3_param *param,
|
||||
#define CIFS_LARGE_BUF_OP 0x020 /* large request buffer */
|
||||
#define CIFS_NO_RESP 0x040 /* no response buffer required */
|
||||
|
||||
/* Type of request operation */
|
||||
#define CIFS_ECHO_OP 0x080 /* echo request */
|
||||
#define CIFS_OBREAK_OP 0x0100 /* oplock break request */
|
||||
#define CIFS_NEG_OP 0x0200 /* negotiate request */
|
||||
#define CIFS_OP_MASK 0x0380 /* mask request type */
|
||||
|
||||
/* Security Flags: indicate type of session setup needed */
|
||||
#define CIFSSEC_MAY_SIGN 0x00001
|
||||
#define CIFSSEC_MAY_NTLM 0x00002
|
||||
@ -1127,6 +1251,8 @@ void cifs_oplock_break(struct work_struct *work);
|
||||
extern const struct slow_work_ops cifs_oplock_break_ops;
|
||||
extern struct workqueue_struct *cifsiod_wq;
|
||||
|
||||
extern mempool_t *cifs_mid_poolp;
|
||||
|
||||
/* Operations for different SMB versions */
|
||||
#define SMB1_VERSION_STRING "1.0"
|
||||
extern struct smb_version_operations smb1_operations;
|
||||
|
@ -37,29 +37,26 @@ extern struct smb_hdr *cifs_small_buf_get(void);
|
||||
extern void cifs_small_buf_release(void *);
|
||||
extern int smb_send(struct TCP_Server_Info *, struct smb_hdr *,
|
||||
unsigned int /* length */);
|
||||
extern unsigned int _GetXid(void);
|
||||
extern void _FreeXid(unsigned int);
|
||||
#define GetXid() \
|
||||
extern unsigned int _get_xid(void);
|
||||
extern void _free_xid(unsigned int);
|
||||
#define get_xid() \
|
||||
({ \
|
||||
int __xid = (int)_GetXid(); \
|
||||
cFYI(1, "CIFS VFS: in %s as Xid: %d with uid: %d", \
|
||||
unsigned int __xid = _get_xid(); \
|
||||
cFYI(1, "CIFS VFS: in %s as Xid: %u with uid: %d", \
|
||||
__func__, __xid, current_fsuid()); \
|
||||
__xid; \
|
||||
})
|
||||
|
||||
#define FreeXid(curr_xid) \
|
||||
#define free_xid(curr_xid) \
|
||||
do { \
|
||||
_FreeXid(curr_xid); \
|
||||
cFYI(1, "CIFS VFS: leaving %s (xid = %d) rc = %d", \
|
||||
_free_xid(curr_xid); \
|
||||
cFYI(1, "CIFS VFS: leaving %s (xid = %u) rc = %d", \
|
||||
__func__, curr_xid, (int)rc); \
|
||||
} while (0)
|
||||
extern int init_cifs_idmap(void);
|
||||
extern void exit_cifs_idmap(void);
|
||||
extern void cifs_destroy_idmaptrees(void);
|
||||
extern char *build_path_from_dentry(struct dentry *);
|
||||
extern char *cifs_build_path_to_root(struct smb_vol *vol,
|
||||
struct cifs_sb_info *cifs_sb,
|
||||
struct cifs_tcon *tcon);
|
||||
extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
|
||||
extern char *cifs_compose_mount_options(const char *sb_mountdata,
|
||||
const char *fullpath, const struct dfs_info3_param *ref,
|
||||
@ -68,18 +65,21 @@ extern char *cifs_compose_mount_options(const char *sb_mountdata,
|
||||
extern struct mid_q_entry *AllocMidQEntry(const struct smb_hdr *smb_buffer,
|
||||
struct TCP_Server_Info *server);
|
||||
extern void DeleteMidQEntry(struct mid_q_entry *midEntry);
|
||||
extern void cifs_wake_up_task(struct mid_q_entry *mid);
|
||||
extern int cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov,
|
||||
unsigned int nvec, mid_receive_t *receive,
|
||||
mid_callback_t *callback, void *cbdata,
|
||||
bool ignore_pend);
|
||||
const int flags);
|
||||
extern int SendReceive(const unsigned int /* xid */ , struct cifs_ses *,
|
||||
struct smb_hdr * /* input */ ,
|
||||
struct smb_hdr * /* out */ ,
|
||||
int * /* bytes returned */ , const int long_op);
|
||||
int * /* bytes returned */ , const int);
|
||||
extern int SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses,
|
||||
char *in_buf, int flags);
|
||||
extern int cifs_setup_request(struct cifs_ses *, struct kvec *, unsigned int,
|
||||
struct mid_q_entry **);
|
||||
extern int cifs_setup_async_request(struct TCP_Server_Info *, struct kvec *,
|
||||
unsigned int, struct mid_q_entry **);
|
||||
extern int cifs_check_receive(struct mid_q_entry *mid,
|
||||
struct TCP_Server_Info *server, bool log_error);
|
||||
extern int SendReceive2(const unsigned int /* xid */ , struct cifs_ses *,
|
||||
@ -90,6 +90,7 @@ extern int SendReceiveBlockingLock(const unsigned int xid,
|
||||
struct smb_hdr *in_buf ,
|
||||
struct smb_hdr *out_buf,
|
||||
int *bytes_returned);
|
||||
extern int cifs_reconnect(struct TCP_Server_Info *server);
|
||||
extern int checkSMB(char *buf, unsigned int length);
|
||||
extern bool is_valid_oplock_break(char *, struct TCP_Server_Info *);
|
||||
extern bool backup_cred(struct cifs_sb_info *);
|
||||
@ -112,8 +113,8 @@ extern void header_assemble(struct smb_hdr *, char /* command */ ,
|
||||
extern int small_smb_init_no_tc(const int smb_cmd, const int wct,
|
||||
struct cifs_ses *ses,
|
||||
void **request_buf);
|
||||
extern int CIFS_SessSetup(unsigned int xid, struct cifs_ses *ses,
|
||||
const struct nls_table *nls_cp);
|
||||
extern int CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses,
|
||||
const struct nls_table *nls_cp);
|
||||
extern struct timespec cifs_NTtimeToUnix(__le64 utc_nanoseconds_since_1601);
|
||||
extern u64 cifs_UnixTimeToNT(struct timespec);
|
||||
extern struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time,
|
||||
@ -123,10 +124,10 @@ extern void cifs_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock);
|
||||
extern struct cifsFileInfo *cifs_new_fileinfo(__u16 fileHandle,
|
||||
struct file *file, struct tcon_link *tlink,
|
||||
__u32 oplock);
|
||||
extern int cifs_posix_open(char *full_path, struct inode **pinode,
|
||||
struct super_block *sb,
|
||||
int mode, unsigned int f_flags,
|
||||
__u32 *poplock, __u16 *pnetfid, int xid);
|
||||
extern int cifs_posix_open(char *full_path, struct inode **inode,
|
||||
struct super_block *sb, int mode,
|
||||
unsigned int f_flags, __u32 *oplock, __u16 *netfid,
|
||||
unsigned int xid);
|
||||
void cifs_fill_uniqueid(struct super_block *sb, struct cifs_fattr *fattr);
|
||||
extern void cifs_unix_basic_to_fattr(struct cifs_fattr *fattr,
|
||||
FILE_UNIX_BASIC_INFO *info,
|
||||
@ -136,14 +137,13 @@ extern struct inode *cifs_iget(struct super_block *sb,
|
||||
struct cifs_fattr *fattr);
|
||||
|
||||
extern int cifs_get_file_info(struct file *filp);
|
||||
extern int cifs_get_inode_info(struct inode **pinode,
|
||||
const unsigned char *search_path,
|
||||
FILE_ALL_INFO *pfile_info,
|
||||
struct super_block *sb, int xid, const __u16 *pfid);
|
||||
extern int cifs_get_inode_info(struct inode **inode, const char *full_path,
|
||||
FILE_ALL_INFO *data, struct super_block *sb,
|
||||
int xid, const __u16 *fid);
|
||||
extern int cifs_get_file_info_unix(struct file *filp);
|
||||
extern int cifs_get_inode_info_unix(struct inode **pinode,
|
||||
const unsigned char *search_path,
|
||||
struct super_block *sb, int xid);
|
||||
struct super_block *sb, unsigned int xid);
|
||||
extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb,
|
||||
struct cifs_fattr *fattr, struct inode *inode,
|
||||
const char *path, const __u16 *pfid);
|
||||
@ -168,6 +168,7 @@ extern struct smb_vol *cifs_get_volume_info(char *mount_data,
|
||||
const char *devname);
|
||||
extern int cifs_mount(struct cifs_sb_info *, struct smb_vol *);
|
||||
extern void cifs_umount(struct cifs_sb_info *);
|
||||
extern void cifs_mark_open_files_invalid(struct cifs_tcon *tcon);
|
||||
|
||||
#if IS_ENABLED(CONFIG_CIFS_DFS_UPCALL)
|
||||
extern void cifs_dfs_release_automount_timer(void);
|
||||
@ -178,98 +179,97 @@ extern void cifs_dfs_release_automount_timer(void);
|
||||
void cifs_proc_init(void);
|
||||
void cifs_proc_clean(void);
|
||||
|
||||
extern int cifs_negotiate_protocol(unsigned int xid,
|
||||
struct cifs_ses *ses);
|
||||
extern int cifs_setup_session(unsigned int xid, struct cifs_ses *ses,
|
||||
struct nls_table *nls_info);
|
||||
extern int CIFSSMBNegotiate(unsigned int xid, struct cifs_ses *ses);
|
||||
extern int cifs_negotiate_protocol(const unsigned int xid,
|
||||
struct cifs_ses *ses);
|
||||
extern int cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
|
||||
struct nls_table *nls_info);
|
||||
extern int CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses);
|
||||
|
||||
extern int CIFSTCon(unsigned int xid, struct cifs_ses *ses,
|
||||
const char *tree, struct cifs_tcon *tcon,
|
||||
const struct nls_table *);
|
||||
extern int CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
|
||||
const char *tree, struct cifs_tcon *tcon,
|
||||
const struct nls_table *);
|
||||
|
||||
extern int CIFSFindFirst(const int xid, struct cifs_tcon *tcon,
|
||||
extern int CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
const char *searchName, const struct nls_table *nls_codepage,
|
||||
__u16 *searchHandle, __u16 search_flags,
|
||||
struct cifs_search_info *psrch_inf,
|
||||
int map, const char dirsep);
|
||||
|
||||
extern int CIFSFindNext(const int xid, struct cifs_tcon *tcon,
|
||||
extern int CIFSFindNext(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
__u16 searchHandle, __u16 search_flags,
|
||||
struct cifs_search_info *psrch_inf);
|
||||
|
||||
extern int CIFSFindClose(const int, struct cifs_tcon *tcon,
|
||||
extern int CIFSFindClose(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
const __u16 search_handle);
|
||||
|
||||
extern int CIFSSMBQFileInfo(const int xid, struct cifs_tcon *tcon,
|
||||
extern int CIFSSMBQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
u16 netfid, FILE_ALL_INFO *pFindData);
|
||||
extern int CIFSSMBQPathInfo(const int xid, struct cifs_tcon *tcon,
|
||||
const unsigned char *searchName,
|
||||
FILE_ALL_INFO *findData,
|
||||
int legacy /* whether to use old info level */,
|
||||
const struct nls_table *nls_codepage, int remap);
|
||||
extern int SMBQueryInformation(const int xid, struct cifs_tcon *tcon,
|
||||
const unsigned char *searchName,
|
||||
FILE_ALL_INFO *findData,
|
||||
const struct nls_table *nls_codepage, int remap);
|
||||
extern int CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
const char *search_Name, FILE_ALL_INFO *data,
|
||||
int legacy /* whether to use old info level */,
|
||||
const struct nls_table *nls_codepage, int remap);
|
||||
extern int SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
const char *search_name, FILE_ALL_INFO *data,
|
||||
const struct nls_table *nls_codepage, int remap);
|
||||
|
||||
extern int CIFSSMBUnixQFileInfo(const int xid, struct cifs_tcon *tcon,
|
||||
extern int CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
u16 netfid, FILE_UNIX_BASIC_INFO *pFindData);
|
||||
extern int CIFSSMBUnixQPathInfo(const int xid,
|
||||
extern int CIFSSMBUnixQPathInfo(const unsigned int xid,
|
||||
struct cifs_tcon *tcon,
|
||||
const unsigned char *searchName,
|
||||
FILE_UNIX_BASIC_INFO *pFindData,
|
||||
const struct nls_table *nls_codepage, int remap);
|
||||
|
||||
extern int CIFSGetDFSRefer(const int xid, struct cifs_ses *ses,
|
||||
const unsigned char *searchName,
|
||||
struct dfs_info3_param **target_nodes,
|
||||
unsigned int *number_of_nodes_in_array,
|
||||
const struct nls_table *nls_codepage, int remap);
|
||||
extern int CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
|
||||
const char *search_name,
|
||||
struct dfs_info3_param **target_nodes,
|
||||
unsigned int *num_of_nodes,
|
||||
const struct nls_table *nls_codepage, int remap);
|
||||
|
||||
extern int get_dfs_path(int xid, struct cifs_ses *pSesInfo,
|
||||
extern int get_dfs_path(const unsigned int xid, struct cifs_ses *ses,
|
||||
const char *old_path,
|
||||
const struct nls_table *nls_codepage,
|
||||
unsigned int *pnum_referrals,
|
||||
struct dfs_info3_param **preferrals,
|
||||
int remap);
|
||||
extern void reset_cifs_unix_caps(int xid, struct cifs_tcon *tcon,
|
||||
unsigned int *num_referrals,
|
||||
struct dfs_info3_param **referrals, int remap);
|
||||
extern void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
|
||||
struct cifs_sb_info *cifs_sb,
|
||||
struct smb_vol *vol);
|
||||
extern int CIFSSMBQFSInfo(const int xid, struct cifs_tcon *tcon,
|
||||
extern int CIFSSMBQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
struct kstatfs *FSData);
|
||||
extern int SMBOldQFSInfo(const int xid, struct cifs_tcon *tcon,
|
||||
extern int SMBOldQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
struct kstatfs *FSData);
|
||||
extern int CIFSSMBSetFSUnixInfo(const int xid, struct cifs_tcon *tcon,
|
||||
extern int CIFSSMBSetFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
__u64 cap);
|
||||
|
||||
extern int CIFSSMBQFSAttributeInfo(const int xid,
|
||||
extern int CIFSSMBQFSAttributeInfo(const unsigned int xid,
|
||||
struct cifs_tcon *tcon);
|
||||
extern int CIFSSMBQFSDeviceInfo(const int xid, struct cifs_tcon *tcon);
|
||||
extern int CIFSSMBQFSUnixInfo(const int xid, struct cifs_tcon *tcon);
|
||||
extern int CIFSSMBQFSPosixInfo(const int xid, struct cifs_tcon *tcon,
|
||||
extern int CIFSSMBQFSDeviceInfo(const unsigned int xid, struct cifs_tcon *tcon);
|
||||
extern int CIFSSMBQFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon);
|
||||
extern int CIFSSMBQFSPosixInfo(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
struct kstatfs *FSData);
|
||||
|
||||
extern int CIFSSMBSetPathInfo(const int xid, struct cifs_tcon *tcon,
|
||||
extern int CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
const char *fileName, const FILE_BASIC_INFO *data,
|
||||
const struct nls_table *nls_codepage,
|
||||
int remap_special_chars);
|
||||
extern int CIFSSMBSetFileInfo(const int xid, struct cifs_tcon *tcon,
|
||||
extern int CIFSSMBSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
const FILE_BASIC_INFO *data, __u16 fid,
|
||||
__u32 pid_of_opener);
|
||||
extern int CIFSSMBSetFileDisposition(const int xid, struct cifs_tcon *tcon,
|
||||
bool delete_file, __u16 fid, __u32 pid_of_opener);
|
||||
extern int CIFSSMBSetFileDisposition(const unsigned int xid,
|
||||
struct cifs_tcon *tcon,
|
||||
bool delete_file, __u16 fid,
|
||||
__u32 pid_of_opener);
|
||||
#if 0
|
||||
extern int CIFSSMBSetAttrLegacy(int xid, struct cifs_tcon *tcon,
|
||||
extern int CIFSSMBSetAttrLegacy(unsigned int xid, struct cifs_tcon *tcon,
|
||||
char *fileName, __u16 dos_attributes,
|
||||
const struct nls_table *nls_codepage);
|
||||
#endif /* possibly unneeded function */
|
||||
extern int CIFSSMBSetEOF(const int xid, struct cifs_tcon *tcon,
|
||||
extern int CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
const char *fileName, __u64 size,
|
||||
bool setAllocationSizeFlag,
|
||||
const struct nls_table *nls_codepage,
|
||||
int remap_special_chars);
|
||||
extern int CIFSSMBSetFileSize(const int xid, struct cifs_tcon *tcon,
|
||||
extern int CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
__u64 size, __u16 fileHandle, __u32 opener_pid,
|
||||
bool AllocSizeFlag);
|
||||
|
||||
@ -283,114 +283,117 @@ struct cifs_unix_set_info_args {
|
||||
dev_t device;
|
||||
};
|
||||
|
||||
extern int CIFSSMBUnixSetFileInfo(const int xid, struct cifs_tcon *tcon,
|
||||
extern int CIFSSMBUnixSetFileInfo(const unsigned int xid,
|
||||
struct cifs_tcon *tcon,
|
||||
const struct cifs_unix_set_info_args *args,
|
||||
u16 fid, u32 pid_of_opener);
|
||||
|
||||
extern int CIFSSMBUnixSetPathInfo(const int xid, struct cifs_tcon *pTcon,
|
||||
char *fileName,
|
||||
const struct cifs_unix_set_info_args *args,
|
||||
const struct nls_table *nls_codepage,
|
||||
int remap_special_chars);
|
||||
extern int CIFSSMBUnixSetPathInfo(const unsigned int xid,
|
||||
struct cifs_tcon *tcon, char *file_name,
|
||||
const struct cifs_unix_set_info_args *args,
|
||||
const struct nls_table *nls_codepage,
|
||||
int remap_special_chars);
|
||||
|
||||
extern int CIFSSMBMkDir(const int xid, struct cifs_tcon *tcon,
|
||||
extern int CIFSSMBMkDir(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
const char *newName,
|
||||
const struct nls_table *nls_codepage,
|
||||
int remap_special_chars);
|
||||
extern int CIFSSMBRmDir(const int xid, struct cifs_tcon *tcon,
|
||||
extern int CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
const char *name, const struct nls_table *nls_codepage,
|
||||
int remap_special_chars);
|
||||
extern int CIFSPOSIXDelFile(const int xid, struct cifs_tcon *tcon,
|
||||
extern int CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
const char *name, __u16 type,
|
||||
const struct nls_table *nls_codepage,
|
||||
int remap_special_chars);
|
||||
extern int CIFSSMBDelFile(const int xid, struct cifs_tcon *tcon,
|
||||
extern int CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
const char *name,
|
||||
const struct nls_table *nls_codepage,
|
||||
int remap_special_chars);
|
||||
extern int CIFSSMBRename(const int xid, struct cifs_tcon *tcon,
|
||||
extern int CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
const char *fromName, const char *toName,
|
||||
const struct nls_table *nls_codepage,
|
||||
int remap_special_chars);
|
||||
extern int CIFSSMBRenameOpenFile(const int xid, struct cifs_tcon *pTcon,
|
||||
int netfid, const char *target_name,
|
||||
const struct nls_table *nls_codepage,
|
||||
int remap_special_chars);
|
||||
extern int CIFSCreateHardLink(const int xid,
|
||||
extern int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
int netfid, const char *target_name,
|
||||
const struct nls_table *nls_codepage,
|
||||
int remap_special_chars);
|
||||
extern int CIFSCreateHardLink(const unsigned int xid,
|
||||
struct cifs_tcon *tcon,
|
||||
const char *fromName, const char *toName,
|
||||
const struct nls_table *nls_codepage,
|
||||
int remap_special_chars);
|
||||
extern int CIFSUnixCreateHardLink(const int xid,
|
||||
extern int CIFSUnixCreateHardLink(const unsigned int xid,
|
||||
struct cifs_tcon *tcon,
|
||||
const char *fromName, const char *toName,
|
||||
const struct nls_table *nls_codepage,
|
||||
int remap_special_chars);
|
||||
extern int CIFSUnixCreateSymLink(const int xid,
|
||||
extern int CIFSUnixCreateSymLink(const unsigned int xid,
|
||||
struct cifs_tcon *tcon,
|
||||
const char *fromName, const char *toName,
|
||||
const struct nls_table *nls_codepage);
|
||||
extern int CIFSSMBUnixQuerySymLink(const int xid,
|
||||
extern int CIFSSMBUnixQuerySymLink(const unsigned int xid,
|
||||
struct cifs_tcon *tcon,
|
||||
const unsigned char *searchName, char **syminfo,
|
||||
const struct nls_table *nls_codepage);
|
||||
#ifdef CONFIG_CIFS_SYMLINK_EXPERIMENTAL
|
||||
extern int CIFSSMBQueryReparseLinkInfo(const int xid,
|
||||
extern int CIFSSMBQueryReparseLinkInfo(const unsigned int xid,
|
||||
struct cifs_tcon *tcon,
|
||||
const unsigned char *searchName,
|
||||
char *symlinkinfo, const int buflen, __u16 fid,
|
||||
const struct nls_table *nls_codepage);
|
||||
#endif /* temporarily unused until cifs_symlink fixed */
|
||||
extern int CIFSSMBOpen(const int xid, struct cifs_tcon *tcon,
|
||||
extern int CIFSSMBOpen(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
const char *fileName, const int disposition,
|
||||
const int access_flags, const int omode,
|
||||
__u16 *netfid, int *pOplock, FILE_ALL_INFO *,
|
||||
const struct nls_table *nls_codepage, int remap);
|
||||
extern int SMBLegacyOpen(const int xid, struct cifs_tcon *tcon,
|
||||
extern int SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
const char *fileName, const int disposition,
|
||||
const int access_flags, const int omode,
|
||||
__u16 *netfid, int *pOplock, FILE_ALL_INFO *,
|
||||
const struct nls_table *nls_codepage, int remap);
|
||||
extern int CIFSPOSIXCreate(const int xid, struct cifs_tcon *tcon,
|
||||
extern int CIFSPOSIXCreate(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
u32 posix_flags, __u64 mode, __u16 *netfid,
|
||||
FILE_UNIX_BASIC_INFO *pRetData,
|
||||
__u32 *pOplock, const char *name,
|
||||
const struct nls_table *nls_codepage, int remap);
|
||||
extern int CIFSSMBClose(const int xid, struct cifs_tcon *tcon,
|
||||
extern int CIFSSMBClose(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
const int smb_file_id);
|
||||
|
||||
extern int CIFSSMBFlush(const int xid, struct cifs_tcon *tcon,
|
||||
extern int CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
const int smb_file_id);
|
||||
|
||||
extern int CIFSSMBRead(const int xid, struct cifs_io_parms *io_parms,
|
||||
extern int CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms,
|
||||
unsigned int *nbytes, char **buf,
|
||||
int *return_buf_type);
|
||||
extern int CIFSSMBWrite(const int xid, struct cifs_io_parms *io_parms,
|
||||
extern int CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,
|
||||
unsigned int *nbytes, const char *buf,
|
||||
const char __user *ubuf, const int long_op);
|
||||
extern int CIFSSMBWrite2(const int xid, struct cifs_io_parms *io_parms,
|
||||
extern int CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
|
||||
unsigned int *nbytes, struct kvec *iov, const int nvec,
|
||||
const int long_op);
|
||||
extern int CIFSGetSrvInodeNumber(const int xid, struct cifs_tcon *tcon,
|
||||
const unsigned char *searchName, __u64 *inode_number,
|
||||
const struct nls_table *nls_codepage,
|
||||
int remap_special_chars);
|
||||
extern int CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
const char *search_name, __u64 *inode_number,
|
||||
const struct nls_table *nls_codepage,
|
||||
int remap);
|
||||
|
||||
extern int cifs_lockv(const int xid, struct cifs_tcon *tcon, const __u16 netfid,
|
||||
const __u8 lock_type, const __u32 num_unlock,
|
||||
const __u32 num_lock, LOCKING_ANDX_RANGE *buf);
|
||||
extern int CIFSSMBLock(const int xid, struct cifs_tcon *tcon,
|
||||
extern int cifs_lockv(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
const __u16 netfid, const __u8 lock_type,
|
||||
const __u32 num_unlock, const __u32 num_lock,
|
||||
LOCKING_ANDX_RANGE *buf);
|
||||
extern int CIFSSMBLock(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
const __u16 netfid, const __u32 netpid, const __u64 len,
|
||||
const __u64 offset, const __u32 numUnlock,
|
||||
const __u32 numLock, const __u8 lockType,
|
||||
const bool waitFlag, const __u8 oplock_level);
|
||||
extern int CIFSSMBPosixLock(const int xid, struct cifs_tcon *tcon,
|
||||
extern int CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
const __u16 smb_file_id, const __u32 netpid,
|
||||
const int get_flag, const __u64 len, struct file_lock *,
|
||||
const __u16 lock_type, const bool waitFlag);
|
||||
extern int CIFSSMBTDis(const int xid, struct cifs_tcon *tcon);
|
||||
const loff_t start_offset, const __u64 len,
|
||||
struct file_lock *, const __u16 lock_type,
|
||||
const bool waitFlag);
|
||||
extern int CIFSSMBTDis(const unsigned int xid, struct cifs_tcon *tcon);
|
||||
extern int CIFSSMBEcho(struct TCP_Server_Info *server);
|
||||
extern int CIFSSMBLogoff(const int xid, struct cifs_ses *ses);
|
||||
extern int CIFSSMBLogoff(const unsigned int xid, struct cifs_ses *ses);
|
||||
|
||||
extern struct cifs_ses *sesInfoAlloc(void);
|
||||
extern void sesInfoFree(struct cifs_ses *);
|
||||
@ -398,7 +401,7 @@ extern struct cifs_tcon *tconInfoAlloc(void);
|
||||
extern void tconInfoFree(struct cifs_tcon *);
|
||||
|
||||
extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *, __u32 *);
|
||||
extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *,
|
||||
extern int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *,
|
||||
__u32 *);
|
||||
extern int cifs_verify_signature(struct kvec *iov, unsigned int nr_iov,
|
||||
struct TCP_Server_Info *server,
|
||||
@ -416,46 +419,46 @@ extern int calc_lanman_hash(const char *password, const char *cryptkey,
|
||||
bool encrypt, char *lnm_session_key);
|
||||
#endif /* CIFS_WEAK_PW_HASH */
|
||||
#ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* unused temporarily */
|
||||
extern int CIFSSMBNotify(const int xid, struct cifs_tcon *tcon,
|
||||
extern int CIFSSMBNotify(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
const int notify_subdirs, const __u16 netfid,
|
||||
__u32 filter, struct file *file, int multishot,
|
||||
const struct nls_table *nls_codepage);
|
||||
#endif /* was needed for dnotify, and will be needed for inotify when VFS fix */
|
||||
extern int CIFSSMBCopy(int xid,
|
||||
extern int CIFSSMBCopy(unsigned int xid,
|
||||
struct cifs_tcon *source_tcon,
|
||||
const char *fromName,
|
||||
const __u16 target_tid,
|
||||
const char *toName, const int flags,
|
||||
const struct nls_table *nls_codepage,
|
||||
int remap_special_chars);
|
||||
extern ssize_t CIFSSMBQAllEAs(const int xid, struct cifs_tcon *tcon,
|
||||
extern ssize_t CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
const unsigned char *searchName,
|
||||
const unsigned char *ea_name, char *EAData,
|
||||
size_t bufsize, const struct nls_table *nls_codepage,
|
||||
int remap_special_chars);
|
||||
extern int CIFSSMBSetEA(const int xid, struct cifs_tcon *tcon,
|
||||
extern int CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
const char *fileName, const char *ea_name,
|
||||
const void *ea_value, const __u16 ea_value_len,
|
||||
const struct nls_table *nls_codepage, int remap_special_chars);
|
||||
extern int CIFSSMBGetCIFSACL(const int xid, struct cifs_tcon *tcon,
|
||||
extern int CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
__u16 fid, struct cifs_ntsd **acl_inf, __u32 *buflen);
|
||||
extern int CIFSSMBSetCIFSACL(const int, struct cifs_tcon *, __u16,
|
||||
extern int CIFSSMBSetCIFSACL(const unsigned int, struct cifs_tcon *, __u16,
|
||||
struct cifs_ntsd *, __u32, int);
|
||||
extern int CIFSSMBGetPosixACL(const int xid, struct cifs_tcon *tcon,
|
||||
extern int CIFSSMBGetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
const unsigned char *searchName,
|
||||
char *acl_inf, const int buflen, const int acl_type,
|
||||
const struct nls_table *nls_codepage, int remap_special_chars);
|
||||
extern int CIFSSMBSetPosixACL(const int xid, struct cifs_tcon *tcon,
|
||||
extern int CIFSSMBSetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
const unsigned char *fileName,
|
||||
const char *local_acl, const int buflen, const int acl_type,
|
||||
const struct nls_table *nls_codepage, int remap_special_chars);
|
||||
extern int CIFSGetExtAttr(const int xid, struct cifs_tcon *tcon,
|
||||
extern int CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
const int netfid, __u64 *pExtAttrBits, __u64 *pMask);
|
||||
extern void cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb);
|
||||
extern bool CIFSCouldBeMFSymlink(const struct cifs_fattr *fattr);
|
||||
extern int CIFSCheckMFSymlink(struct cifs_fattr *fattr,
|
||||
const unsigned char *path,
|
||||
struct cifs_sb_info *cifs_sb, int xid);
|
||||
struct cifs_sb_info *cifs_sb, unsigned int xid);
|
||||
extern int mdfour(unsigned char *, unsigned char *, int);
|
||||
extern int E_md4hash(const unsigned char *passwd, unsigned char *p16,
|
||||
const struct nls_table *codepage);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -56,9 +56,6 @@
|
||||
#define CIFS_PORT 445
|
||||
#define RFC1001_PORT 139
|
||||
|
||||
/* SMB echo "timeout" -- FIXME: tunable? */
|
||||
#define SMB_ECHO_INTERVAL (60 * HZ)
|
||||
|
||||
extern mempool_t *cifs_req_poolp;
|
||||
|
||||
/* FIXME: should these be tunable? */
|
||||
@ -238,8 +235,8 @@ static const match_table_t cifs_mount_option_tokens = {
|
||||
enum {
|
||||
Opt_sec_krb5, Opt_sec_krb5i, Opt_sec_krb5p,
|
||||
Opt_sec_ntlmsspi, Opt_sec_ntlmssp,
|
||||
Opt_ntlm, Opt_sec_ntlmi, Opt_sec_ntlmv2i,
|
||||
Opt_sec_nontlm, Opt_sec_lanman,
|
||||
Opt_ntlm, Opt_sec_ntlmi, Opt_sec_ntlmv2,
|
||||
Opt_sec_ntlmv2i, Opt_sec_lanman,
|
||||
Opt_sec_none,
|
||||
|
||||
Opt_sec_err
|
||||
@ -253,8 +250,9 @@ static const match_table_t cifs_secflavor_tokens = {
|
||||
{ Opt_sec_ntlmssp, "ntlmssp" },
|
||||
{ Opt_ntlm, "ntlm" },
|
||||
{ Opt_sec_ntlmi, "ntlmi" },
|
||||
{ Opt_sec_ntlmv2, "nontlm" },
|
||||
{ Opt_sec_ntlmv2, "ntlmv2" },
|
||||
{ Opt_sec_ntlmv2i, "ntlmv2i" },
|
||||
{ Opt_sec_nontlm, "nontlm" },
|
||||
{ Opt_sec_lanman, "lanman" },
|
||||
{ Opt_sec_none, "none" },
|
||||
|
||||
@ -296,7 +294,7 @@ static int cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
|
||||
* reconnect tcp session
|
||||
* wake up waiters on reconnection? - (not needed currently)
|
||||
*/
|
||||
static int
|
||||
int
|
||||
cifs_reconnect(struct TCP_Server_Info *server)
|
||||
{
|
||||
int rc = 0;
|
||||
@ -316,6 +314,9 @@ cifs_reconnect(struct TCP_Server_Info *server)
|
||||
server->tcpStatus = CifsNeedReconnect;
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
server->maxBuf = 0;
|
||||
#ifdef CONFIG_CIFS_SMB2
|
||||
server->max_read = 0;
|
||||
#endif
|
||||
|
||||
cFYI(1, "Reconnecting tcp session");
|
||||
|
||||
@ -394,143 +395,6 @@ cifs_reconnect(struct TCP_Server_Info *server)
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
return codes:
|
||||
0 not a transact2, or all data present
|
||||
>0 transact2 with that much data missing
|
||||
-EINVAL = invalid transact2
|
||||
|
||||
*/
|
||||
static int check2ndT2(char *buf)
|
||||
{
|
||||
struct smb_hdr *pSMB = (struct smb_hdr *)buf;
|
||||
struct smb_t2_rsp *pSMBt;
|
||||
int remaining;
|
||||
__u16 total_data_size, data_in_this_rsp;
|
||||
|
||||
if (pSMB->Command != SMB_COM_TRANSACTION2)
|
||||
return 0;
|
||||
|
||||
/* check for plausible wct, bcc and t2 data and parm sizes */
|
||||
/* check for parm and data offset going beyond end of smb */
|
||||
if (pSMB->WordCount != 10) { /* coalesce_t2 depends on this */
|
||||
cFYI(1, "invalid transact2 word count");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pSMBt = (struct smb_t2_rsp *)pSMB;
|
||||
|
||||
total_data_size = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount);
|
||||
data_in_this_rsp = get_unaligned_le16(&pSMBt->t2_rsp.DataCount);
|
||||
|
||||
if (total_data_size == data_in_this_rsp)
|
||||
return 0;
|
||||
else if (total_data_size < data_in_this_rsp) {
|
||||
cFYI(1, "total data %d smaller than data in frame %d",
|
||||
total_data_size, data_in_this_rsp);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
remaining = total_data_size - data_in_this_rsp;
|
||||
|
||||
cFYI(1, "missing %d bytes from transact2, check next response",
|
||||
remaining);
|
||||
if (total_data_size > CIFSMaxBufSize) {
|
||||
cERROR(1, "TotalDataSize %d is over maximum buffer %d",
|
||||
total_data_size, CIFSMaxBufSize);
|
||||
return -EINVAL;
|
||||
}
|
||||
return remaining;
|
||||
}
|
||||
|
||||
static int coalesce_t2(char *second_buf, struct smb_hdr *target_hdr)
|
||||
{
|
||||
struct smb_t2_rsp *pSMBs = (struct smb_t2_rsp *)second_buf;
|
||||
struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)target_hdr;
|
||||
char *data_area_of_tgt;
|
||||
char *data_area_of_src;
|
||||
int remaining;
|
||||
unsigned int byte_count, total_in_tgt;
|
||||
__u16 tgt_total_cnt, src_total_cnt, total_in_src;
|
||||
|
||||
src_total_cnt = get_unaligned_le16(&pSMBs->t2_rsp.TotalDataCount);
|
||||
tgt_total_cnt = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount);
|
||||
|
||||
if (tgt_total_cnt != src_total_cnt)
|
||||
cFYI(1, "total data count of primary and secondary t2 differ "
|
||||
"source=%hu target=%hu", src_total_cnt, tgt_total_cnt);
|
||||
|
||||
total_in_tgt = get_unaligned_le16(&pSMBt->t2_rsp.DataCount);
|
||||
|
||||
remaining = tgt_total_cnt - total_in_tgt;
|
||||
|
||||
if (remaining < 0) {
|
||||
cFYI(1, "Server sent too much data. tgt_total_cnt=%hu "
|
||||
"total_in_tgt=%hu", tgt_total_cnt, total_in_tgt);
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
if (remaining == 0) {
|
||||
/* nothing to do, ignore */
|
||||
cFYI(1, "no more data remains");
|
||||
return 0;
|
||||
}
|
||||
|
||||
total_in_src = get_unaligned_le16(&pSMBs->t2_rsp.DataCount);
|
||||
if (remaining < total_in_src)
|
||||
cFYI(1, "transact2 2nd response contains too much data");
|
||||
|
||||
/* find end of first SMB data area */
|
||||
data_area_of_tgt = (char *)&pSMBt->hdr.Protocol +
|
||||
get_unaligned_le16(&pSMBt->t2_rsp.DataOffset);
|
||||
|
||||
/* validate target area */
|
||||
data_area_of_src = (char *)&pSMBs->hdr.Protocol +
|
||||
get_unaligned_le16(&pSMBs->t2_rsp.DataOffset);
|
||||
|
||||
data_area_of_tgt += total_in_tgt;
|
||||
|
||||
total_in_tgt += total_in_src;
|
||||
/* is the result too big for the field? */
|
||||
if (total_in_tgt > USHRT_MAX) {
|
||||
cFYI(1, "coalesced DataCount too large (%u)", total_in_tgt);
|
||||
return -EPROTO;
|
||||
}
|
||||
put_unaligned_le16(total_in_tgt, &pSMBt->t2_rsp.DataCount);
|
||||
|
||||
/* fix up the BCC */
|
||||
byte_count = get_bcc(target_hdr);
|
||||
byte_count += total_in_src;
|
||||
/* is the result too big for the field? */
|
||||
if (byte_count > USHRT_MAX) {
|
||||
cFYI(1, "coalesced BCC too large (%u)", byte_count);
|
||||
return -EPROTO;
|
||||
}
|
||||
put_bcc(byte_count, target_hdr);
|
||||
|
||||
byte_count = be32_to_cpu(target_hdr->smb_buf_length);
|
||||
byte_count += total_in_src;
|
||||
/* don't allow buffer to overflow */
|
||||
if (byte_count > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
|
||||
cFYI(1, "coalesced BCC exceeds buffer size (%u)", byte_count);
|
||||
return -ENOBUFS;
|
||||
}
|
||||
target_hdr->smb_buf_length = cpu_to_be32(byte_count);
|
||||
|
||||
/* copy second buffer into end of first buffer */
|
||||
memcpy(data_area_of_tgt, data_area_of_src, total_in_src);
|
||||
|
||||
if (remaining != total_in_src) {
|
||||
/* more responses to go */
|
||||
cFYI(1, "waiting for more secondary responses");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* we are done */
|
||||
cFYI(1, "found the last secondary response");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
cifs_echo_request(struct work_struct *work)
|
||||
{
|
||||
@ -539,15 +403,17 @@ cifs_echo_request(struct work_struct *work)
|
||||
struct TCP_Server_Info, echo.work);
|
||||
|
||||
/*
|
||||
* We cannot send an echo until the NEGOTIATE_PROTOCOL request is
|
||||
* done, which is indicated by maxBuf != 0. Also, no need to ping if
|
||||
* we got a response recently
|
||||
* We cannot send an echo if it is disabled or until the
|
||||
* NEGOTIATE_PROTOCOL request is done, which is indicated by
|
||||
* server->ops->need_neg() == true. Also, no need to ping if
|
||||
* we got a response recently.
|
||||
*/
|
||||
if (server->maxBuf == 0 ||
|
||||
if (!server->ops->need_neg || server->ops->need_neg(server) ||
|
||||
(server->ops->can_echo && !server->ops->can_echo(server)) ||
|
||||
time_before(jiffies, server->lstrp + SMB_ECHO_INTERVAL - HZ))
|
||||
goto requeue_echo;
|
||||
|
||||
rc = CIFSSMBEcho(server);
|
||||
rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS;
|
||||
if (rc)
|
||||
cFYI(1, "Unable to send echo request to server: %s",
|
||||
server->hostname);
|
||||
@ -803,29 +669,9 @@ static void
|
||||
handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server,
|
||||
char *buf, int malformed)
|
||||
{
|
||||
if (malformed == 0 && check2ndT2(buf) > 0) {
|
||||
mid->multiRsp = true;
|
||||
if (mid->resp_buf) {
|
||||
/* merge response - fix up 1st*/
|
||||
malformed = coalesce_t2(buf, mid->resp_buf);
|
||||
if (malformed > 0)
|
||||
return;
|
||||
|
||||
/* All parts received or packet is malformed. */
|
||||
mid->multiEnd = true;
|
||||
return dequeue_mid(mid, malformed);
|
||||
}
|
||||
if (!server->large_buf) {
|
||||
/*FIXME: switch to already allocated largebuf?*/
|
||||
cERROR(1, "1st trans2 resp needs bigbuf");
|
||||
} else {
|
||||
/* Have first buffer */
|
||||
mid->resp_buf = buf;
|
||||
mid->large_buf = true;
|
||||
server->bigbuf = NULL;
|
||||
}
|
||||
if (server->ops->check_trans2 &&
|
||||
server->ops->check_trans2(mid, server, buf, malformed))
|
||||
return;
|
||||
}
|
||||
mid->resp_buf = buf;
|
||||
mid->large_buf = server->large_buf;
|
||||
/* Was previous buf put in mpx struct for multi-rsp? */
|
||||
@ -1167,7 +1013,7 @@ static int cifs_parse_security_flavors(char *value,
|
||||
case Opt_sec_ntlmi:
|
||||
vol->secFlg |= CIFSSEC_MAY_NTLM | CIFSSEC_MUST_SIGN;
|
||||
break;
|
||||
case Opt_sec_nontlm:
|
||||
case Opt_sec_ntlmv2:
|
||||
vol->secFlg |= CIFSSEC_MAY_NTLMV2;
|
||||
break;
|
||||
case Opt_sec_ntlmv2i:
|
||||
@ -2409,10 +2255,10 @@ cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
|
||||
static void
|
||||
cifs_put_smb_ses(struct cifs_ses *ses)
|
||||
{
|
||||
int xid;
|
||||
unsigned int xid;
|
||||
struct TCP_Server_Info *server = ses->server;
|
||||
|
||||
cFYI(1, "%s: ses_count=%d\n", __func__, ses->ses_count);
|
||||
cFYI(1, "%s: ses_count=%d", __func__, ses->ses_count);
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
if (--ses->ses_count > 0) {
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
@ -2422,10 +2268,10 @@ cifs_put_smb_ses(struct cifs_ses *ses)
|
||||
list_del_init(&ses->smb_ses_list);
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
|
||||
if (ses->status == CifsGood) {
|
||||
xid = GetXid();
|
||||
CIFSSMBLogoff(xid, ses);
|
||||
_FreeXid(xid);
|
||||
if (ses->status == CifsGood && server->ops->logoff) {
|
||||
xid = get_xid();
|
||||
server->ops->logoff(xid, ses);
|
||||
_free_xid(xid);
|
||||
}
|
||||
sesInfoFree(ses);
|
||||
cifs_put_tcp_session(server);
|
||||
@ -2562,12 +2408,13 @@ static bool warned_on_ntlm; /* globals init to false automatically */
|
||||
static struct cifs_ses *
|
||||
cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
|
||||
{
|
||||
int rc = -ENOMEM, xid;
|
||||
int rc = -ENOMEM;
|
||||
unsigned int xid;
|
||||
struct cifs_ses *ses;
|
||||
struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
|
||||
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
|
||||
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
|
||||
ses = cifs_find_smb_ses(server, volume_info);
|
||||
if (ses) {
|
||||
@ -2579,7 +2426,7 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
|
||||
mutex_unlock(&ses->session_mutex);
|
||||
/* problem -- put our ses reference */
|
||||
cifs_put_smb_ses(ses);
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return ERR_PTR(rc);
|
||||
}
|
||||
if (ses->need_reconnect) {
|
||||
@ -2590,7 +2437,7 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
|
||||
mutex_unlock(&ses->session_mutex);
|
||||
/* problem -- put our reference */
|
||||
cifs_put_smb_ses(ses);
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return ERR_PTR(rc);
|
||||
}
|
||||
}
|
||||
@ -2598,7 +2445,7 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
|
||||
|
||||
/* existing SMB ses has a server reference already */
|
||||
cifs_put_tcp_session(server);
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return ses;
|
||||
}
|
||||
|
||||
@ -2657,12 +2504,12 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
|
||||
list_add(&ses->smb_ses_list, &server->smb_ses_list);
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return ses;
|
||||
|
||||
get_ses_fail:
|
||||
sesInfoFree(ses);
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return ERR_PTR(rc);
|
||||
}
|
||||
|
||||
@ -2697,10 +2544,10 @@ cifs_find_tcon(struct cifs_ses *ses, const char *unc)
|
||||
static void
|
||||
cifs_put_tcon(struct cifs_tcon *tcon)
|
||||
{
|
||||
int xid;
|
||||
unsigned int xid;
|
||||
struct cifs_ses *ses = tcon->ses;
|
||||
|
||||
cFYI(1, "%s: tc_count=%d\n", __func__, tcon->tc_count);
|
||||
cFYI(1, "%s: tc_count=%d", __func__, tcon->tc_count);
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
if (--tcon->tc_count > 0) {
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
@ -2710,9 +2557,10 @@ cifs_put_tcon(struct cifs_tcon *tcon)
|
||||
list_del_init(&tcon->tcon_list);
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
|
||||
xid = GetXid();
|
||||
CIFSSMBTDis(xid, tcon);
|
||||
_FreeXid(xid);
|
||||
xid = get_xid();
|
||||
if (ses->server->ops->tree_disconnect)
|
||||
ses->server->ops->tree_disconnect(xid, tcon);
|
||||
_free_xid(xid);
|
||||
|
||||
cifs_fscache_release_super_cookie(tcon);
|
||||
tconInfoFree(tcon);
|
||||
@ -2736,6 +2584,11 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
|
||||
return tcon;
|
||||
}
|
||||
|
||||
if (!ses->server->ops->tree_connect) {
|
||||
rc = -ENOSYS;
|
||||
goto out_fail;
|
||||
}
|
||||
|
||||
tcon = tconInfoAlloc();
|
||||
if (tcon == NULL) {
|
||||
rc = -ENOMEM;
|
||||
@ -2758,13 +2611,15 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
|
||||
goto out_fail;
|
||||
}
|
||||
|
||||
/* BB Do we need to wrap session_mutex around
|
||||
* this TCon call and Unix SetFS as
|
||||
* we do on SessSetup and reconnect? */
|
||||
xid = GetXid();
|
||||
rc = CIFSTCon(xid, ses, volume_info->UNC, tcon, volume_info->local_nls);
|
||||
FreeXid(xid);
|
||||
cFYI(1, "CIFS Tcon rc = %d", rc);
|
||||
/*
|
||||
* BB Do we need to wrap session_mutex around this TCon call and Unix
|
||||
* SetFS as we do on SessSetup and reconnect?
|
||||
*/
|
||||
xid = get_xid();
|
||||
rc = ses->server->ops->tree_connect(xid, ses, volume_info->UNC, tcon,
|
||||
volume_info->local_nls);
|
||||
free_xid(xid);
|
||||
cFYI(1, "Tcon rc = %d", rc);
|
||||
if (rc)
|
||||
goto out_fail;
|
||||
|
||||
@ -2773,10 +2628,11 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
|
||||
cFYI(1, "DFS disabled (%d)", tcon->Flags);
|
||||
}
|
||||
tcon->seal = volume_info->seal;
|
||||
/* we can have only one retry value for a connection
|
||||
to a share so for resources mounted more than once
|
||||
to the same server share the last value passed in
|
||||
for the retry flag is used */
|
||||
/*
|
||||
* We can have only one retry value for a connection to a share so for
|
||||
* resources mounted more than once to the same server share the last
|
||||
* value passed in for the retry flag is used.
|
||||
*/
|
||||
tcon->retry = volume_info->retry;
|
||||
tcon->nocase = volume_info->nocase;
|
||||
tcon->local_lease = volume_info->local_lease;
|
||||
@ -2910,37 +2766,42 @@ out:
|
||||
}
|
||||
|
||||
int
|
||||
get_dfs_path(int xid, struct cifs_ses *pSesInfo, const char *old_path,
|
||||
const struct nls_table *nls_codepage, unsigned int *pnum_referrals,
|
||||
struct dfs_info3_param **preferrals, int remap)
|
||||
get_dfs_path(const unsigned int xid, struct cifs_ses *ses, const char *old_path,
|
||||
const struct nls_table *nls_codepage, unsigned int *num_referrals,
|
||||
struct dfs_info3_param **referrals, int remap)
|
||||
{
|
||||
char *temp_unc;
|
||||
int rc = 0;
|
||||
|
||||
*pnum_referrals = 0;
|
||||
*preferrals = NULL;
|
||||
if (!ses->server->ops->tree_connect || !ses->server->ops->get_dfs_refer)
|
||||
return -ENOSYS;
|
||||
|
||||
if (pSesInfo->ipc_tid == 0) {
|
||||
*num_referrals = 0;
|
||||
*referrals = NULL;
|
||||
|
||||
if (ses->ipc_tid == 0) {
|
||||
temp_unc = kmalloc(2 /* for slashes */ +
|
||||
strnlen(pSesInfo->serverName,
|
||||
SERVER_NAME_LEN_WITH_NULL * 2)
|
||||
+ 1 + 4 /* slash IPC$ */ + 2,
|
||||
GFP_KERNEL);
|
||||
strnlen(ses->serverName, SERVER_NAME_LEN_WITH_NULL * 2)
|
||||
+ 1 + 4 /* slash IPC$ */ + 2, GFP_KERNEL);
|
||||
if (temp_unc == NULL)
|
||||
return -ENOMEM;
|
||||
temp_unc[0] = '\\';
|
||||
temp_unc[1] = '\\';
|
||||
strcpy(temp_unc + 2, pSesInfo->serverName);
|
||||
strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
|
||||
rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
|
||||
cFYI(1, "CIFS Tcon rc = %d ipc_tid = %d", rc, pSesInfo->ipc_tid);
|
||||
strcpy(temp_unc + 2, ses->serverName);
|
||||
strcpy(temp_unc + 2 + strlen(ses->serverName), "\\IPC$");
|
||||
rc = ses->server->ops->tree_connect(xid, ses, temp_unc, NULL,
|
||||
nls_codepage);
|
||||
cFYI(1, "Tcon rc = %d ipc_tid = %d", rc, ses->ipc_tid);
|
||||
kfree(temp_unc);
|
||||
}
|
||||
if (rc == 0)
|
||||
rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
|
||||
pnum_referrals, nls_codepage, remap);
|
||||
/* BB map targetUNCs to dfs_info3 structures, here or
|
||||
in CIFSGetDFSRefer BB */
|
||||
rc = ses->server->ops->get_dfs_refer(xid, ses, old_path,
|
||||
referrals, num_referrals,
|
||||
nls_codepage, remap);
|
||||
/*
|
||||
* BB - map targetUNCs to dfs_info3 structures, here or in
|
||||
* ses->server->ops->get_dfs_refer.
|
||||
*/
|
||||
|
||||
return rc;
|
||||
}
|
||||
@ -3009,11 +2870,11 @@ bind_socket(struct TCP_Server_Info *server)
|
||||
saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
|
||||
if (saddr6->sin6_family == AF_INET6)
|
||||
cERROR(1, "cifs: "
|
||||
"Failed to bind to: %pI6c, error: %d\n",
|
||||
"Failed to bind to: %pI6c, error: %d",
|
||||
&saddr6->sin6_addr, rc);
|
||||
else
|
||||
cERROR(1, "cifs: "
|
||||
"Failed to bind to: %pI4, error: %d\n",
|
||||
"Failed to bind to: %pI4, error: %d",
|
||||
&saddr4->sin_addr.s_addr, rc);
|
||||
}
|
||||
}
|
||||
@ -3209,7 +3070,7 @@ ip_connect(struct TCP_Server_Info *server)
|
||||
return generic_ip_connect(server);
|
||||
}
|
||||
|
||||
void reset_cifs_unix_caps(int xid, struct cifs_tcon *tcon,
|
||||
void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
|
||||
struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info)
|
||||
{
|
||||
/* if we are reconnecting then should we check to see if
|
||||
@ -3304,9 +3165,9 @@ void reset_cifs_unix_caps(int xid, struct cifs_tcon *tcon,
|
||||
cFYI(1, "resetting capabilities failed");
|
||||
} else
|
||||
cERROR(1, "Negotiating Unix capabilities "
|
||||
"with the server failed. Consider "
|
||||
"mounting with the Unix Extensions\n"
|
||||
"disabled, if problems are found, "
|
||||
"with the server failed. Consider "
|
||||
"mounting with the Unix Extensions "
|
||||
"disabled if problems are found "
|
||||
"by specifying the nounix mount "
|
||||
"option.");
|
||||
|
||||
@ -3540,30 +3401,6 @@ cifs_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
|
||||
return rsize;
|
||||
}
|
||||
|
||||
static int
|
||||
is_path_accessible(int xid, struct cifs_tcon *tcon,
|
||||
struct cifs_sb_info *cifs_sb, const char *full_path)
|
||||
{
|
||||
int rc;
|
||||
FILE_ALL_INFO *pfile_info;
|
||||
|
||||
pfile_info = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
|
||||
if (pfile_info == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
rc = CIFSSMBQPathInfo(xid, tcon, full_path, pfile_info,
|
||||
0 /* not legacy */, cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
|
||||
if (rc == -EOPNOTSUPP || rc == -EINVAL)
|
||||
rc = SMBQueryInformation(xid, tcon, full_path, pfile_info,
|
||||
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
kfree(pfile_info);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void
|
||||
cleanup_volume_info_contents(struct smb_vol *volume_info)
|
||||
{
|
||||
@ -3627,7 +3464,7 @@ build_unc_path_to_root(const struct smb_vol *vol,
|
||||
* determine whether there were referrals.
|
||||
*/
|
||||
static int
|
||||
expand_dfs_referral(int xid, struct cifs_ses *pSesInfo,
|
||||
expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses,
|
||||
struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb,
|
||||
int check_prefix)
|
||||
{
|
||||
@ -3643,7 +3480,7 @@ expand_dfs_referral(int xid, struct cifs_ses *pSesInfo,
|
||||
/* For DFS paths, skip the first '\' of the UNC */
|
||||
ref_path = check_prefix ? full_path + 1 : volume_info->UNC + 1;
|
||||
|
||||
rc = get_dfs_path(xid, pSesInfo , ref_path, cifs_sb->local_nls,
|
||||
rc = get_dfs_path(xid, ses, ref_path, cifs_sb->local_nls,
|
||||
&num_referrals, &referrals,
|
||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
|
||||
@ -3737,10 +3574,10 @@ int
|
||||
cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
|
||||
{
|
||||
int rc;
|
||||
int xid;
|
||||
struct cifs_ses *pSesInfo;
|
||||
unsigned int xid;
|
||||
struct cifs_ses *ses;
|
||||
struct cifs_tcon *tcon;
|
||||
struct TCP_Server_Info *srvTcp;
|
||||
struct TCP_Server_Info *server;
|
||||
char *full_path;
|
||||
struct tcon_link *tlink;
|
||||
#ifdef CONFIG_CIFS_DFS_UPCALL
|
||||
@ -3757,39 +3594,39 @@ try_mount_again:
|
||||
if (referral_walks_count) {
|
||||
if (tcon)
|
||||
cifs_put_tcon(tcon);
|
||||
else if (pSesInfo)
|
||||
cifs_put_smb_ses(pSesInfo);
|
||||
else if (ses)
|
||||
cifs_put_smb_ses(ses);
|
||||
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
}
|
||||
#endif
|
||||
rc = 0;
|
||||
tcon = NULL;
|
||||
pSesInfo = NULL;
|
||||
srvTcp = NULL;
|
||||
ses = NULL;
|
||||
server = NULL;
|
||||
full_path = NULL;
|
||||
tlink = NULL;
|
||||
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
|
||||
/* get a reference to a tcp session */
|
||||
srvTcp = cifs_get_tcp_session(volume_info);
|
||||
if (IS_ERR(srvTcp)) {
|
||||
rc = PTR_ERR(srvTcp);
|
||||
server = cifs_get_tcp_session(volume_info);
|
||||
if (IS_ERR(server)) {
|
||||
rc = PTR_ERR(server);
|
||||
bdi_destroy(&cifs_sb->bdi);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* get a reference to a SMB session */
|
||||
pSesInfo = cifs_get_smb_ses(srvTcp, volume_info);
|
||||
if (IS_ERR(pSesInfo)) {
|
||||
rc = PTR_ERR(pSesInfo);
|
||||
pSesInfo = NULL;
|
||||
ses = cifs_get_smb_ses(server, volume_info);
|
||||
if (IS_ERR(ses)) {
|
||||
rc = PTR_ERR(ses);
|
||||
ses = NULL;
|
||||
goto mount_fail_check;
|
||||
}
|
||||
|
||||
/* search for existing tcon to this server share */
|
||||
tcon = cifs_get_tcon(pSesInfo, volume_info);
|
||||
tcon = cifs_get_tcon(ses, volume_info);
|
||||
if (IS_ERR(tcon)) {
|
||||
rc = PTR_ERR(tcon);
|
||||
tcon = NULL;
|
||||
@ -3797,7 +3634,7 @@ try_mount_again:
|
||||
}
|
||||
|
||||
/* tell server which Unix caps we support */
|
||||
if (tcon->ses->capabilities & CAP_UNIX) {
|
||||
if (cap_unix(tcon->ses)) {
|
||||
/* reset of caps checks mount to see if unix extensions
|
||||
disabled for just this mount */
|
||||
reset_cifs_unix_caps(xid, tcon, cifs_sb, volume_info);
|
||||
@ -3810,11 +3647,9 @@ try_mount_again:
|
||||
} else
|
||||
tcon->unix_ext = 0; /* server does not support them */
|
||||
|
||||
/* do not care if following two calls succeed - informational */
|
||||
if (!tcon->ipc) {
|
||||
CIFSSMBQFSDeviceInfo(xid, tcon);
|
||||
CIFSSMBQFSAttributeInfo(xid, tcon);
|
||||
}
|
||||
/* do not care if a following call succeed - informational */
|
||||
if (!tcon->ipc && server->ops->qfs_tcon)
|
||||
server->ops->qfs_tcon(xid, tcon);
|
||||
|
||||
cifs_sb->wsize = cifs_negotiate_wsize(tcon, volume_info);
|
||||
cifs_sb->rsize = cifs_negotiate_rsize(tcon, volume_info);
|
||||
@ -3832,8 +3667,8 @@ remote_path_check:
|
||||
* Chase the referral if found, otherwise continue normally.
|
||||
*/
|
||||
if (referral_walks_count == 0) {
|
||||
int refrc = expand_dfs_referral(xid, pSesInfo, volume_info,
|
||||
cifs_sb, false);
|
||||
int refrc = expand_dfs_referral(xid, ses, volume_info, cifs_sb,
|
||||
false);
|
||||
if (!refrc) {
|
||||
referral_walks_count++;
|
||||
goto try_mount_again;
|
||||
@ -3843,13 +3678,18 @@ remote_path_check:
|
||||
|
||||
/* check if a whole path is not remote */
|
||||
if (!rc && tcon) {
|
||||
if (!server->ops->is_path_accessible) {
|
||||
rc = -ENOSYS;
|
||||
goto mount_fail_check;
|
||||
}
|
||||
/* build_path_to_root works only when we have a valid tcon */
|
||||
full_path = cifs_build_path_to_root(volume_info, cifs_sb, tcon);
|
||||
full_path = build_path_to_root(volume_info, cifs_sb, tcon);
|
||||
if (full_path == NULL) {
|
||||
rc = -ENOMEM;
|
||||
goto mount_fail_check;
|
||||
}
|
||||
rc = is_path_accessible(xid, tcon, cifs_sb, full_path);
|
||||
rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
|
||||
full_path);
|
||||
if (rc != 0 && rc != -EREMOTE) {
|
||||
kfree(full_path);
|
||||
goto mount_fail_check;
|
||||
@ -3871,8 +3711,7 @@ remote_path_check:
|
||||
goto mount_fail_check;
|
||||
}
|
||||
|
||||
rc = expand_dfs_referral(xid, pSesInfo, volume_info, cifs_sb,
|
||||
true);
|
||||
rc = expand_dfs_referral(xid, ses, volume_info, cifs_sb, true);
|
||||
|
||||
if (!rc) {
|
||||
referral_walks_count++;
|
||||
@ -3894,7 +3733,7 @@ remote_path_check:
|
||||
goto mount_fail_check;
|
||||
}
|
||||
|
||||
tlink->tl_uid = pSesInfo->linux_uid;
|
||||
tlink->tl_uid = ses->linux_uid;
|
||||
tlink->tl_tcon = tcon;
|
||||
tlink->tl_time = jiffies;
|
||||
set_bit(TCON_LINK_MASTER, &tlink->tl_flags);
|
||||
@ -3915,15 +3754,15 @@ mount_fail_check:
|
||||
/* up accidentally freeing someone elses tcon struct */
|
||||
if (tcon)
|
||||
cifs_put_tcon(tcon);
|
||||
else if (pSesInfo)
|
||||
cifs_put_smb_ses(pSesInfo);
|
||||
else if (ses)
|
||||
cifs_put_smb_ses(ses);
|
||||
else
|
||||
cifs_put_tcp_session(srvTcp);
|
||||
cifs_put_tcp_session(server);
|
||||
bdi_destroy(&cifs_sb->bdi);
|
||||
}
|
||||
|
||||
out:
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -3932,7 +3771,7 @@ out:
|
||||
* pointer may be NULL.
|
||||
*/
|
||||
int
|
||||
CIFSTCon(unsigned int xid, struct cifs_ses *ses,
|
||||
CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
|
||||
const char *tree, struct cifs_tcon *tcon,
|
||||
const struct nls_table *nls_codepage)
|
||||
{
|
||||
@ -4116,24 +3955,22 @@ cifs_umount(struct cifs_sb_info *cifs_sb)
|
||||
kfree(cifs_sb);
|
||||
}
|
||||
|
||||
int cifs_negotiate_protocol(unsigned int xid, struct cifs_ses *ses)
|
||||
int
|
||||
cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses)
|
||||
{
|
||||
int rc = 0;
|
||||
struct TCP_Server_Info *server = ses->server;
|
||||
|
||||
if (!server->ops->need_neg || !server->ops->negotiate)
|
||||
return -ENOSYS;
|
||||
|
||||
/* only send once per connect */
|
||||
if (server->maxBuf != 0)
|
||||
if (!server->ops->need_neg(server))
|
||||
return 0;
|
||||
|
||||
set_credits(server, 1);
|
||||
rc = CIFSSMBNegotiate(xid, ses);
|
||||
if (rc == -EAGAIN) {
|
||||
/* retry only once on 1st time connection */
|
||||
set_credits(server, 1);
|
||||
rc = CIFSSMBNegotiate(xid, ses);
|
||||
if (rc == -EAGAIN)
|
||||
rc = -EHOSTDOWN;
|
||||
}
|
||||
|
||||
rc = server->ops->negotiate(xid, ses);
|
||||
if (rc == 0) {
|
||||
spin_lock(&GlobalMid_Lock);
|
||||
if (server->tcpStatus == CifsNeedNegotiate)
|
||||
@ -4141,28 +3978,29 @@ int cifs_negotiate_protocol(unsigned int xid, struct cifs_ses *ses)
|
||||
else
|
||||
rc = -EHOSTDOWN;
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int cifs_setup_session(unsigned int xid, struct cifs_ses *ses,
|
||||
struct nls_table *nls_info)
|
||||
int
|
||||
cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
|
||||
struct nls_table *nls_info)
|
||||
{
|
||||
int rc = 0;
|
||||
int rc = -ENOSYS;
|
||||
struct TCP_Server_Info *server = ses->server;
|
||||
|
||||
ses->flags = 0;
|
||||
ses->capabilities = server->capabilities;
|
||||
if (linuxExtEnabled == 0)
|
||||
ses->capabilities &= (~CAP_UNIX);
|
||||
ses->capabilities &= (~server->vals->cap_unix);
|
||||
|
||||
cFYI(1, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d",
|
||||
server->sec_mode, server->capabilities, server->timeAdj);
|
||||
|
||||
rc = CIFS_SessSetup(xid, ses, nls_info);
|
||||
if (server->ops->sess_setup)
|
||||
rc = server->ops->sess_setup(xid, ses, nls_info);
|
||||
|
||||
if (rc) {
|
||||
cERROR(1, "Send error in SessSetup = %d", rc);
|
||||
} else {
|
||||
@ -4262,7 +4100,7 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ses->capabilities & CAP_UNIX)
|
||||
if (cap_unix(ses))
|
||||
reset_cifs_unix_caps(0, tcon, NULL, vol_info);
|
||||
out:
|
||||
kfree(vol_info->username);
|
||||
|
@ -157,10 +157,10 @@ check_name(struct dentry *direntry)
|
||||
|
||||
/* Inode operations in similar order to how they appear in Linux file fs.h */
|
||||
|
||||
static int cifs_do_create(struct inode *inode, struct dentry *direntry,
|
||||
int xid, struct tcon_link *tlink, unsigned oflags,
|
||||
umode_t mode, __u32 *oplock, __u16 *fileHandle,
|
||||
int *created)
|
||||
static int
|
||||
cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
|
||||
struct tcon_link *tlink, unsigned oflags, umode_t mode,
|
||||
__u32 *oplock, __u16 *fileHandle, int *created)
|
||||
{
|
||||
int rc = -ENOENT;
|
||||
int create_options = CREATE_NOT_DIR;
|
||||
@ -182,8 +182,7 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
|
||||
!tcon->broken_posix_open &&
|
||||
if (tcon->unix_ext && cap_unix(tcon->ses) && !tcon->broken_posix_open &&
|
||||
(CIFS_UNIX_POSIX_PATH_OPS_CAP &
|
||||
le64_to_cpu(tcon->fsUnixInfo.Capability))) {
|
||||
rc = cifs_posix_open(full_path, &newinode,
|
||||
@ -382,12 +381,11 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
|
||||
int *opened)
|
||||
{
|
||||
int rc;
|
||||
int xid;
|
||||
unsigned int xid;
|
||||
struct tcon_link *tlink;
|
||||
struct cifs_tcon *tcon;
|
||||
__u16 fileHandle;
|
||||
__u32 oplock;
|
||||
struct file *filp;
|
||||
struct cifsFileInfo *pfile_info;
|
||||
|
||||
/* Posix open is only called (at lookup time) for file create now. For
|
||||
@ -412,15 +410,14 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
|
||||
cFYI(1, "parent inode = 0x%p name is: %s and dentry = 0x%p",
|
||||
inode, direntry->d_name.name, direntry);
|
||||
|
||||
tlink = cifs_sb_tlink(CIFS_SB(inode->i_sb));
|
||||
filp = ERR_CAST(tlink);
|
||||
if (IS_ERR(tlink))
|
||||
goto free_xid;
|
||||
goto out_free_xid;
|
||||
|
||||
tcon = tlink_tcon(tlink);
|
||||
|
||||
@ -436,17 +433,16 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
|
||||
goto out;
|
||||
}
|
||||
|
||||
pfile_info = cifs_new_fileinfo(fileHandle, filp, tlink, oplock);
|
||||
pfile_info = cifs_new_fileinfo(fileHandle, file, tlink, oplock);
|
||||
if (pfile_info == NULL) {
|
||||
CIFSSMBClose(xid, tcon, fileHandle);
|
||||
fput(filp);
|
||||
rc = -ENOMEM;
|
||||
}
|
||||
|
||||
out:
|
||||
cifs_put_tlink(tlink);
|
||||
free_xid:
|
||||
FreeXid(xid);
|
||||
out_free_xid:
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -454,7 +450,7 @@ int cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode,
|
||||
bool excl)
|
||||
{
|
||||
int rc;
|
||||
int xid = GetXid();
|
||||
unsigned int xid = get_xid();
|
||||
/*
|
||||
* BB below access is probably too much for mknod to request
|
||||
* but we have to do query and setpathinfo so requesting
|
||||
@ -474,7 +470,7 @@ int cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode,
|
||||
tlink = cifs_sb_tlink(CIFS_SB(inode->i_sb));
|
||||
rc = PTR_ERR(tlink);
|
||||
if (IS_ERR(tlink))
|
||||
goto free_xid;
|
||||
goto out_free_xid;
|
||||
|
||||
rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode,
|
||||
&oplock, &fileHandle, &created);
|
||||
@ -482,9 +478,8 @@ int cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode,
|
||||
CIFSSMBClose(xid, tlink_tcon(tlink), fileHandle);
|
||||
|
||||
cifs_put_tlink(tlink);
|
||||
free_xid:
|
||||
FreeXid(xid);
|
||||
|
||||
out_free_xid:
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -492,7 +487,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
|
||||
dev_t device_number)
|
||||
{
|
||||
int rc = -EPERM;
|
||||
int xid;
|
||||
unsigned int xid;
|
||||
int create_options = CREATE_NOT_DIR | CREATE_OPTION_SPECIAL;
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
struct tcon_link *tlink;
|
||||
@ -516,7 +511,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
|
||||
|
||||
pTcon = tlink_tcon(tlink);
|
||||
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
|
||||
full_path = build_path_from_dentry(direntry);
|
||||
if (full_path == NULL) {
|
||||
@ -564,7 +559,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
|
||||
if (buf == NULL) {
|
||||
kfree(full_path);
|
||||
rc = -ENOMEM;
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -614,7 +609,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
|
||||
mknod_out:
|
||||
kfree(full_path);
|
||||
kfree(buf);
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
cifs_put_tlink(tlink);
|
||||
return rc;
|
||||
}
|
||||
@ -623,7 +618,7 @@ struct dentry *
|
||||
cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
|
||||
unsigned int flags)
|
||||
{
|
||||
int xid;
|
||||
unsigned int xid;
|
||||
int rc = 0; /* to get around spurious gcc warning, set to zero here */
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
struct tcon_link *tlink;
|
||||
@ -631,7 +626,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
|
||||
struct inode *newInode = NULL;
|
||||
char *full_path = NULL;
|
||||
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
|
||||
cFYI(1, "parent inode = 0x%p name is: %s and dentry = 0x%p",
|
||||
parent_dir_inode, direntry->d_name.name, direntry);
|
||||
@ -641,7 +636,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
|
||||
cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
|
||||
tlink = cifs_sb_tlink(cifs_sb);
|
||||
if (IS_ERR(tlink)) {
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return (struct dentry *)tlink;
|
||||
}
|
||||
pTcon = tlink_tcon(tlink);
|
||||
@ -695,7 +690,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
|
||||
lookup_out:
|
||||
kfree(full_path);
|
||||
cifs_put_tlink(tlink);
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return ERR_PTR(rc);
|
||||
}
|
||||
|
||||
|
193
fs/cifs/file.c
193
fs/cifs/file.c
@ -107,7 +107,7 @@ static inline int cifs_get_disposition(unsigned int flags)
|
||||
|
||||
int cifs_posix_open(char *full_path, struct inode **pinode,
|
||||
struct super_block *sb, int mode, unsigned int f_flags,
|
||||
__u32 *poplock, __u16 *pnetfid, int xid)
|
||||
__u32 *poplock, __u16 *pnetfid, unsigned int xid)
|
||||
{
|
||||
int rc;
|
||||
FILE_UNIX_BASIC_INFO *presp_data;
|
||||
@ -170,7 +170,7 @@ posix_open_ret:
|
||||
static int
|
||||
cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb,
|
||||
struct cifs_tcon *tcon, unsigned int f_flags, __u32 *poplock,
|
||||
__u16 *pnetfid, int xid)
|
||||
__u16 *pnetfid, unsigned int xid)
|
||||
{
|
||||
int rc;
|
||||
int desiredAccess;
|
||||
@ -284,6 +284,15 @@ cifs_new_fileinfo(__u16 fileHandle, struct file *file,
|
||||
|
||||
static void cifs_del_lock_waiters(struct cifsLockInfo *lock);
|
||||
|
||||
struct cifsFileInfo *
|
||||
cifsFileInfo_get(struct cifsFileInfo *cifs_file)
|
||||
{
|
||||
spin_lock(&cifs_file_list_lock);
|
||||
cifsFileInfo_get_locked(cifs_file);
|
||||
spin_unlock(&cifs_file_list_lock);
|
||||
return cifs_file;
|
||||
}
|
||||
|
||||
/*
|
||||
* Release a reference on the file private data. This may involve closing
|
||||
* the filehandle out on the server. Must be called without holding
|
||||
@ -324,11 +333,11 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
|
||||
cancel_work_sync(&cifs_file->oplock_break);
|
||||
|
||||
if (!tcon->need_reconnect && !cifs_file->invalidHandle) {
|
||||
int xid, rc;
|
||||
|
||||
xid = GetXid();
|
||||
unsigned int xid;
|
||||
int rc;
|
||||
xid = get_xid();
|
||||
rc = CIFSSMBClose(xid, tcon, cifs_file->netfid);
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
}
|
||||
|
||||
/* Delete any outstanding lock records. We'll lose them when the file
|
||||
@ -350,7 +359,7 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
|
||||
int cifs_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
int rc = -EACCES;
|
||||
int xid;
|
||||
unsigned int xid;
|
||||
__u32 oplock;
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
struct cifs_tcon *tcon;
|
||||
@ -360,12 +369,12 @@ int cifs_open(struct inode *inode, struct file *file)
|
||||
bool posix_open_ok = false;
|
||||
__u16 netfid;
|
||||
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
|
||||
cifs_sb = CIFS_SB(inode->i_sb);
|
||||
tlink = cifs_sb_tlink(cifs_sb);
|
||||
if (IS_ERR(tlink)) {
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return PTR_ERR(tlink);
|
||||
}
|
||||
tcon = tlink_tcon(tlink);
|
||||
@ -385,9 +394,8 @@ int cifs_open(struct inode *inode, struct file *file)
|
||||
oplock = 0;
|
||||
|
||||
if (!tcon->broken_posix_open && tcon->unix_ext &&
|
||||
(tcon->ses->capabilities & CAP_UNIX) &&
|
||||
(CIFS_UNIX_POSIX_PATH_OPS_CAP &
|
||||
le64_to_cpu(tcon->fsUnixInfo.Capability))) {
|
||||
cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
|
||||
le64_to_cpu(tcon->fsUnixInfo.Capability))) {
|
||||
/* can not refresh inode info since size could be stale */
|
||||
rc = cifs_posix_open(full_path, &inode, inode->i_sb,
|
||||
cifs_sb->mnt_file_mode /* ignored */,
|
||||
@ -445,7 +453,7 @@ int cifs_open(struct inode *inode, struct file *file)
|
||||
|
||||
out:
|
||||
kfree(full_path);
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
cifs_put_tlink(tlink);
|
||||
return rc;
|
||||
}
|
||||
@ -464,7 +472,7 @@ static int cifs_relock_file(struct cifsFileInfo *cifsFile)
|
||||
static int cifs_reopen_file(struct cifsFileInfo *pCifsFile, bool can_flush)
|
||||
{
|
||||
int rc = -EACCES;
|
||||
int xid;
|
||||
unsigned int xid;
|
||||
__u32 oplock;
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
struct cifs_tcon *tcon;
|
||||
@ -476,12 +484,12 @@ static int cifs_reopen_file(struct cifsFileInfo *pCifsFile, bool can_flush)
|
||||
int create_options = CREATE_NOT_DIR;
|
||||
__u16 netfid;
|
||||
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
mutex_lock(&pCifsFile->fh_mutex);
|
||||
if (!pCifsFile->invalidHandle) {
|
||||
mutex_unlock(&pCifsFile->fh_mutex);
|
||||
rc = 0;
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -497,7 +505,7 @@ static int cifs_reopen_file(struct cifsFileInfo *pCifsFile, bool can_flush)
|
||||
if (full_path == NULL) {
|
||||
rc = -ENOMEM;
|
||||
mutex_unlock(&pCifsFile->fh_mutex);
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -509,10 +517,9 @@ static int cifs_reopen_file(struct cifsFileInfo *pCifsFile, bool can_flush)
|
||||
else
|
||||
oplock = 0;
|
||||
|
||||
if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
|
||||
if (tcon->unix_ext && cap_unix(tcon->ses) &&
|
||||
(CIFS_UNIX_POSIX_PATH_OPS_CAP &
|
||||
le64_to_cpu(tcon->fsUnixInfo.Capability))) {
|
||||
|
||||
le64_to_cpu(tcon->fsUnixInfo.Capability))) {
|
||||
/*
|
||||
* O_CREAT, O_EXCL and O_TRUNC already had their effect on the
|
||||
* original open. Must mask them off for a reopen.
|
||||
@ -583,7 +590,7 @@ reopen_success:
|
||||
|
||||
reopen_error_exit:
|
||||
kfree(full_path);
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -601,13 +608,13 @@ int cifs_close(struct inode *inode, struct file *file)
|
||||
int cifs_closedir(struct inode *inode, struct file *file)
|
||||
{
|
||||
int rc = 0;
|
||||
int xid;
|
||||
unsigned int xid;
|
||||
struct cifsFileInfo *pCFileStruct = file->private_data;
|
||||
char *ptmp;
|
||||
|
||||
cFYI(1, "Closedir inode = 0x%p", inode);
|
||||
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
|
||||
if (pCFileStruct) {
|
||||
struct cifs_tcon *pTcon = tlink_tcon(pCFileStruct->tlink);
|
||||
@ -639,7 +646,7 @@ int cifs_closedir(struct inode *inode, struct file *file)
|
||||
file->private_data = NULL;
|
||||
}
|
||||
/* BB can we lock the filestruct while this is going on? */
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -872,7 +879,8 @@ try_again:
|
||||
static int
|
||||
cifs_push_mandatory_locks(struct cifsFileInfo *cfile)
|
||||
{
|
||||
int xid, rc = 0, stored_rc;
|
||||
unsigned int xid;
|
||||
int rc = 0, stored_rc;
|
||||
struct cifsLockInfo *li, *tmp;
|
||||
struct cifs_tcon *tcon;
|
||||
struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
|
||||
@ -882,13 +890,13 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile)
|
||||
LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES};
|
||||
int i;
|
||||
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
tcon = tlink_tcon(cfile->tlink);
|
||||
|
||||
mutex_lock(&cinode->lock_mutex);
|
||||
if (!cinode->can_cache_brlcks) {
|
||||
mutex_unlock(&cinode->lock_mutex);
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -899,7 +907,7 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile)
|
||||
max_buf = tcon->ses->server->maxBuf;
|
||||
if (!max_buf) {
|
||||
mutex_unlock(&cinode->lock_mutex);
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -908,7 +916,7 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile)
|
||||
buf = kzalloc(max_num * sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL);
|
||||
if (!buf) {
|
||||
mutex_unlock(&cinode->lock_mutex);
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -947,7 +955,7 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile)
|
||||
mutex_unlock(&cinode->lock_mutex);
|
||||
|
||||
kfree(buf);
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -977,12 +985,12 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile)
|
||||
struct lock_to_push *lck, *tmp;
|
||||
__u64 length;
|
||||
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
|
||||
mutex_lock(&cinode->lock_mutex);
|
||||
if (!cinode->can_cache_brlcks) {
|
||||
mutex_unlock(&cinode->lock_mutex);
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -1039,12 +1047,10 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile)
|
||||
unlock_flocks();
|
||||
|
||||
list_for_each_entry_safe(lck, tmp, &locks_to_send, llist) {
|
||||
struct file_lock tmp_lock;
|
||||
int stored_rc;
|
||||
|
||||
tmp_lock.fl_start = lck->offset;
|
||||
stored_rc = CIFSSMBPosixLock(xid, tcon, lck->netfid, lck->pid,
|
||||
0, lck->length, &tmp_lock,
|
||||
lck->offset, lck->length, NULL,
|
||||
lck->type, 0);
|
||||
if (stored_rc)
|
||||
rc = stored_rc;
|
||||
@ -1056,7 +1062,7 @@ out:
|
||||
cinode->can_cache_brlcks = false;
|
||||
mutex_unlock(&cinode->lock_mutex);
|
||||
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
err_out:
|
||||
list_for_each_entry_safe(lck, tmp, &locks_to_send, llist) {
|
||||
@ -1072,7 +1078,7 @@ cifs_push_locks(struct cifsFileInfo *cfile)
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb);
|
||||
struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
|
||||
|
||||
if ((tcon->ses->capabilities & CAP_UNIX) &&
|
||||
if (cap_unix(tcon->ses) &&
|
||||
(CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
|
||||
((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
|
||||
return cifs_push_posix_locks(cfile);
|
||||
@ -1128,7 +1134,7 @@ cifs_read_flock(struct file_lock *flock, __u32 *type, int *lock, int *unlock,
|
||||
}
|
||||
|
||||
static int
|
||||
cifs_mandatory_lock(int xid, struct cifsFileInfo *cfile, __u64 offset,
|
||||
cifs_mandatory_lock(unsigned int xid, struct cifsFileInfo *cfile, __u64 offset,
|
||||
__u64 length, __u32 type, int lock, int unlock, bool wait)
|
||||
{
|
||||
return CIFSSMBLock(xid, tlink_tcon(cfile->tlink), cfile->netfid,
|
||||
@ -1138,7 +1144,7 @@ cifs_mandatory_lock(int xid, struct cifsFileInfo *cfile, __u64 offset,
|
||||
|
||||
static int
|
||||
cifs_getlk(struct file *file, struct file_lock *flock, __u32 type,
|
||||
bool wait_flag, bool posix_lck, int xid)
|
||||
bool wait_flag, bool posix_lck, unsigned int xid)
|
||||
{
|
||||
int rc = 0;
|
||||
__u64 length = 1 + flock->fl_end - flock->fl_start;
|
||||
@ -1159,7 +1165,7 @@ cifs_getlk(struct file *file, struct file_lock *flock, __u32 type,
|
||||
else
|
||||
posix_lock_type = CIFS_WRLCK;
|
||||
rc = CIFSSMBPosixLock(xid, tcon, netfid, current->tgid,
|
||||
1 /* get */, length, flock,
|
||||
flock->fl_start, length, flock,
|
||||
posix_lock_type, wait_flag);
|
||||
return rc;
|
||||
}
|
||||
@ -1223,7 +1229,8 @@ cifs_free_llist(struct list_head *llist)
|
||||
}
|
||||
|
||||
static int
|
||||
cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, int xid)
|
||||
cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock,
|
||||
unsigned int xid)
|
||||
{
|
||||
int rc = 0, stored_rc;
|
||||
int types[] = {LOCKING_ANDX_LARGE_FILES,
|
||||
@ -1328,7 +1335,8 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, int xid)
|
||||
|
||||
static int
|
||||
cifs_setlk(struct file *file, struct file_lock *flock, __u32 type,
|
||||
bool wait_flag, bool posix_lck, int lock, int unlock, int xid)
|
||||
bool wait_flag, bool posix_lck, int lock, int unlock,
|
||||
unsigned int xid)
|
||||
{
|
||||
int rc = 0;
|
||||
__u64 length = 1 + flock->fl_end - flock->fl_start;
|
||||
@ -1353,7 +1361,7 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u32 type,
|
||||
posix_lock_type = CIFS_UNLCK;
|
||||
|
||||
rc = CIFSSMBPosixLock(xid, tcon, netfid, current->tgid,
|
||||
0 /* set */, length, flock,
|
||||
flock->fl_start, length, NULL,
|
||||
posix_lock_type, wait_flag);
|
||||
goto out;
|
||||
}
|
||||
@ -1402,7 +1410,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *flock)
|
||||
__u32 type;
|
||||
|
||||
rc = -EACCES;
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
|
||||
cFYI(1, "Lock parm: 0x%x flockflags: 0x%x flocktype: 0x%x start: %lld "
|
||||
"end: %lld", cmd, flock->fl_flags, flock->fl_type,
|
||||
@ -1418,7 +1426,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *flock)
|
||||
netfid = cfile->netfid;
|
||||
cinode = CIFS_I(file->f_path.dentry->d_inode);
|
||||
|
||||
if ((tcon->ses->capabilities & CAP_UNIX) &&
|
||||
if (cap_unix(tcon->ses) &&
|
||||
(CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
|
||||
((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
|
||||
posix_lck = true;
|
||||
@ -1428,7 +1436,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *flock)
|
||||
*/
|
||||
if (IS_GETLK(cmd)) {
|
||||
rc = cifs_getlk(file, flock, type, wait_flag, posix_lck, xid);
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -1437,13 +1445,13 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *flock)
|
||||
* if no lock or unlock then nothing to do since we do not
|
||||
* know what it is
|
||||
*/
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
rc = cifs_setlk(file, flock, type, wait_flag, posix_lck, lock, unlock,
|
||||
xid);
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -1470,7 +1478,7 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file, __u32 pid,
|
||||
unsigned int total_written;
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
struct cifs_tcon *pTcon;
|
||||
int xid;
|
||||
unsigned int xid;
|
||||
struct dentry *dentry = open_file->dentry;
|
||||
struct cifsInodeInfo *cifsi = CIFS_I(dentry->d_inode);
|
||||
struct cifs_io_parms io_parms;
|
||||
@ -1482,7 +1490,7 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file, __u32 pid,
|
||||
|
||||
pTcon = tlink_tcon(open_file->tlink);
|
||||
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
|
||||
for (total_written = 0; write_size > total_written;
|
||||
total_written += bytes_written) {
|
||||
@ -1518,7 +1526,7 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file, __u32 pid,
|
||||
if (total_written)
|
||||
break;
|
||||
else {
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
} else {
|
||||
@ -1538,7 +1546,7 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file, __u32 pid,
|
||||
spin_unlock(&dentry->d_inode->i_lock);
|
||||
}
|
||||
mark_inode_dirty_sync(dentry->d_inode);
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return total_written;
|
||||
}
|
||||
|
||||
@ -1563,7 +1571,7 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
|
||||
if (!open_file->invalidHandle) {
|
||||
/* found a good file */
|
||||
/* lock it so it will not be closed on us */
|
||||
cifsFileInfo_get(open_file);
|
||||
cifsFileInfo_get_locked(open_file);
|
||||
spin_unlock(&cifs_file_list_lock);
|
||||
return open_file;
|
||||
} /* else might as well continue, and look for
|
||||
@ -1615,7 +1623,7 @@ refind_writable:
|
||||
if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
|
||||
if (!open_file->invalidHandle) {
|
||||
/* found a good writable file */
|
||||
cifsFileInfo_get(open_file);
|
||||
cifsFileInfo_get_locked(open_file);
|
||||
spin_unlock(&cifs_file_list_lock);
|
||||
return open_file;
|
||||
} else {
|
||||
@ -1632,7 +1640,7 @@ refind_writable:
|
||||
|
||||
if (inv_file) {
|
||||
any_available = false;
|
||||
cifsFileInfo_get(inv_file);
|
||||
cifsFileInfo_get_locked(inv_file);
|
||||
}
|
||||
|
||||
spin_unlock(&cifs_file_list_lock);
|
||||
@ -1937,9 +1945,9 @@ static int
|
||||
cifs_writepage_locked(struct page *page, struct writeback_control *wbc)
|
||||
{
|
||||
int rc;
|
||||
int xid;
|
||||
unsigned int xid;
|
||||
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
/* BB add check for wbc flags */
|
||||
page_cache_get(page);
|
||||
if (!PageUptodate(page))
|
||||
@ -1968,7 +1976,7 @@ retry_write:
|
||||
SetPageUptodate(page);
|
||||
end_page_writeback(page);
|
||||
page_cache_release(page);
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -2007,9 +2015,9 @@ static int cifs_write_end(struct file *file, struct address_space *mapping,
|
||||
if (!PageUptodate(page)) {
|
||||
char *page_data;
|
||||
unsigned offset = pos & (PAGE_CACHE_SIZE - 1);
|
||||
int xid;
|
||||
unsigned int xid;
|
||||
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
/* this is probably better than directly calling
|
||||
partialpage_write since in this function the file handle is
|
||||
known which we might as well leverage */
|
||||
@ -2020,7 +2028,7 @@ static int cifs_write_end(struct file *file, struct address_space *mapping,
|
||||
/* if (rc < 0) should we set writebehind rc? */
|
||||
kunmap(page);
|
||||
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
} else {
|
||||
rc = copied;
|
||||
pos += copied;
|
||||
@ -2043,7 +2051,7 @@ static int cifs_write_end(struct file *file, struct address_space *mapping,
|
||||
int cifs_strict_fsync(struct file *file, loff_t start, loff_t end,
|
||||
int datasync)
|
||||
{
|
||||
int xid;
|
||||
unsigned int xid;
|
||||
int rc = 0;
|
||||
struct cifs_tcon *tcon;
|
||||
struct cifsFileInfo *smbfile = file->private_data;
|
||||
@ -2055,7 +2063,7 @@ int cifs_strict_fsync(struct file *file, loff_t start, loff_t end,
|
||||
return rc;
|
||||
mutex_lock(&inode->i_mutex);
|
||||
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
|
||||
cFYI(1, "Sync file - name: %s datasync: 0x%x",
|
||||
file->f_path.dentry->d_name.name, datasync);
|
||||
@ -2072,14 +2080,14 @@ int cifs_strict_fsync(struct file *file, loff_t start, loff_t end,
|
||||
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC))
|
||||
rc = CIFSSMBFlush(xid, tcon, smbfile->netfid);
|
||||
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cifs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
|
||||
{
|
||||
int xid;
|
||||
unsigned int xid;
|
||||
int rc = 0;
|
||||
struct cifs_tcon *tcon;
|
||||
struct cifsFileInfo *smbfile = file->private_data;
|
||||
@ -2091,7 +2099,7 @@ int cifs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
|
||||
return rc;
|
||||
mutex_lock(&inode->i_mutex);
|
||||
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
|
||||
cFYI(1, "Sync file - name: %s datasync: 0x%x",
|
||||
file->f_path.dentry->d_name.name, datasync);
|
||||
@ -2100,7 +2108,7 @@ int cifs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
|
||||
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC))
|
||||
rc = CIFSSMBFlush(xid, tcon, smbfile->netfid);
|
||||
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
return rc;
|
||||
}
|
||||
@ -2744,15 +2752,15 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
|
||||
unsigned int current_read_size;
|
||||
unsigned int rsize;
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
struct cifs_tcon *pTcon;
|
||||
int xid;
|
||||
struct cifs_tcon *tcon;
|
||||
unsigned int xid;
|
||||
char *current_offset;
|
||||
struct cifsFileInfo *open_file;
|
||||
struct cifs_io_parms io_parms;
|
||||
int buf_type = CIFS_NO_BUFFER;
|
||||
__u32 pid;
|
||||
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
|
||||
|
||||
/* FIXME: set up handlers for larger reads and/or convert to async */
|
||||
@ -2760,11 +2768,11 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
|
||||
|
||||
if (file->private_data == NULL) {
|
||||
rc = -EBADF;
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
open_file = file->private_data;
|
||||
pTcon = tlink_tcon(open_file->tlink);
|
||||
tcon = tlink_tcon(open_file->tlink);
|
||||
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
|
||||
pid = open_file->pid;
|
||||
@ -2778,11 +2786,12 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
|
||||
read_size > total_read;
|
||||
total_read += bytes_read, current_offset += bytes_read) {
|
||||
current_read_size = min_t(uint, read_size - total_read, rsize);
|
||||
|
||||
/* For windows me and 9x we do not want to request more
|
||||
than it negotiated since it will refuse the read then */
|
||||
if ((pTcon->ses) &&
|
||||
!(pTcon->ses->capabilities & CAP_LARGE_FILES)) {
|
||||
/*
|
||||
* For windows me and 9x we do not want to request more than it
|
||||
* negotiated since it will refuse the read then.
|
||||
*/
|
||||
if ((tcon->ses) && !(tcon->ses->capabilities &
|
||||
tcon->ses->server->vals->cap_large_files)) {
|
||||
current_read_size = min_t(uint, current_read_size,
|
||||
CIFSMaxBufSize);
|
||||
}
|
||||
@ -2795,7 +2804,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
|
||||
}
|
||||
io_parms.netfid = open_file->netfid;
|
||||
io_parms.pid = pid;
|
||||
io_parms.tcon = pTcon;
|
||||
io_parms.tcon = tcon;
|
||||
io_parms.offset = *poffset;
|
||||
io_parms.length = current_read_size;
|
||||
rc = CIFSSMBRead(xid, &io_parms, &bytes_read,
|
||||
@ -2805,15 +2814,15 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
|
||||
if (total_read) {
|
||||
break;
|
||||
} else {
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
} else {
|
||||
cifs_stats_bytes_read(pTcon, total_read);
|
||||
cifs_stats_bytes_read(tcon, total_read);
|
||||
*poffset += bytes_read;
|
||||
}
|
||||
}
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return total_read;
|
||||
}
|
||||
|
||||
@ -2840,7 +2849,7 @@ int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
int rc, xid;
|
||||
struct inode *inode = file->f_path.dentry->d_inode;
|
||||
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
|
||||
if (!CIFS_I(inode)->clientCanCacheRead) {
|
||||
rc = cifs_invalidate_mapping(inode);
|
||||
@ -2851,7 +2860,7 @@ int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
rc = generic_file_mmap(file, vma);
|
||||
if (rc == 0)
|
||||
vma->vm_ops = &cifs_file_vm_ops;
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -2859,17 +2868,17 @@ int cifs_file_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
{
|
||||
int rc, xid;
|
||||
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
rc = cifs_revalidate_file(file);
|
||||
if (rc) {
|
||||
cFYI(1, "Validation prior to mmap failed, error=%d", rc);
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
rc = generic_file_mmap(file, vma);
|
||||
if (rc == 0)
|
||||
vma->vm_ops = &cifs_file_vm_ops;
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -3082,8 +3091,6 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
|
||||
break;
|
||||
}
|
||||
|
||||
spin_lock(&cifs_file_list_lock);
|
||||
spin_unlock(&cifs_file_list_lock);
|
||||
rdata->cfile = cifsFileInfo_get(open_file);
|
||||
rdata->mapping = mapping;
|
||||
rdata->offset = offset;
|
||||
@ -3159,24 +3166,24 @@ static int cifs_readpage(struct file *file, struct page *page)
|
||||
{
|
||||
loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
|
||||
int rc = -EACCES;
|
||||
int xid;
|
||||
unsigned int xid;
|
||||
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
|
||||
if (file->private_data == NULL) {
|
||||
rc = -EBADF;
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
|
||||
cFYI(1, "readpage %p at offset %d 0x%x\n",
|
||||
cFYI(1, "readpage %p at offset %d 0x%x",
|
||||
page, (int)offset, (int)offset);
|
||||
|
||||
rc = cifs_readpage_worker(file, page, &offset);
|
||||
|
||||
unlock_page(page);
|
||||
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
236
fs/cifs/inode.c
236
fs/cifs/inode.c
@ -289,7 +289,7 @@ cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb)
|
||||
int cifs_get_file_info_unix(struct file *filp)
|
||||
{
|
||||
int rc;
|
||||
int xid;
|
||||
unsigned int xid;
|
||||
FILE_UNIX_BASIC_INFO find_data;
|
||||
struct cifs_fattr fattr;
|
||||
struct inode *inode = filp->f_path.dentry->d_inode;
|
||||
@ -297,7 +297,7 @@ int cifs_get_file_info_unix(struct file *filp)
|
||||
struct cifsFileInfo *cfile = filp->private_data;
|
||||
struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
|
||||
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->netfid, &find_data);
|
||||
if (!rc) {
|
||||
cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
|
||||
@ -307,13 +307,13 @@ int cifs_get_file_info_unix(struct file *filp)
|
||||
}
|
||||
|
||||
cifs_fattr_to_inode(inode, &fattr);
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cifs_get_inode_info_unix(struct inode **pinode,
|
||||
const unsigned char *full_path,
|
||||
struct super_block *sb, int xid)
|
||||
struct super_block *sb, unsigned int xid)
|
||||
{
|
||||
int rc;
|
||||
FILE_UNIX_BASIC_INFO find_data;
|
||||
@ -367,7 +367,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
|
||||
|
||||
static int
|
||||
cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
|
||||
struct cifs_sb_info *cifs_sb, int xid)
|
||||
struct cifs_sb_info *cifs_sb, unsigned int xid)
|
||||
{
|
||||
int rc;
|
||||
int oplock = 0;
|
||||
@ -466,7 +466,7 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
|
||||
* FIXME: Doesn't this clobber the type bit we got from cifs_sfu_type ?
|
||||
*/
|
||||
static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
|
||||
struct cifs_sb_info *cifs_sb, int xid)
|
||||
struct cifs_sb_info *cifs_sb, unsigned int xid)
|
||||
{
|
||||
#ifdef CONFIG_CIFS_XATTR
|
||||
ssize_t rc;
|
||||
@ -557,7 +557,7 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
|
||||
int cifs_get_file_info(struct file *filp)
|
||||
{
|
||||
int rc;
|
||||
int xid;
|
||||
unsigned int xid;
|
||||
FILE_ALL_INFO find_data;
|
||||
struct cifs_fattr fattr;
|
||||
struct inode *inode = filp->f_path.dentry->d_inode;
|
||||
@ -565,7 +565,7 @@ int cifs_get_file_info(struct file *filp)
|
||||
struct cifsFileInfo *cfile = filp->private_data;
|
||||
struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
|
||||
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
rc = CIFSSMBQFileInfo(xid, tcon, cfile->netfid, &find_data);
|
||||
switch (rc) {
|
||||
case 0:
|
||||
@ -596,65 +596,58 @@ int cifs_get_file_info(struct file *filp)
|
||||
fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
|
||||
cifs_fattr_to_inode(inode, &fattr);
|
||||
cgfi_exit:
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cifs_get_inode_info(struct inode **pinode,
|
||||
const unsigned char *full_path, FILE_ALL_INFO *pfindData,
|
||||
struct super_block *sb, int xid, const __u16 *pfid)
|
||||
int
|
||||
cifs_get_inode_info(struct inode **inode, const char *full_path,
|
||||
FILE_ALL_INFO *data, struct super_block *sb, int xid,
|
||||
const __u16 *fid)
|
||||
{
|
||||
int rc = 0, tmprc;
|
||||
struct cifs_tcon *pTcon;
|
||||
struct cifs_tcon *tcon;
|
||||
struct TCP_Server_Info *server;
|
||||
struct tcon_link *tlink;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
|
||||
char *buf = NULL;
|
||||
bool adjustTZ = false;
|
||||
bool adjust_tz = false;
|
||||
struct cifs_fattr fattr;
|
||||
|
||||
tlink = cifs_sb_tlink(cifs_sb);
|
||||
if (IS_ERR(tlink))
|
||||
return PTR_ERR(tlink);
|
||||
pTcon = tlink_tcon(tlink);
|
||||
tcon = tlink_tcon(tlink);
|
||||
server = tcon->ses->server;
|
||||
|
||||
cFYI(1, "Getting info on %s", full_path);
|
||||
|
||||
if ((pfindData == NULL) && (*pinode != NULL)) {
|
||||
if (CIFS_I(*pinode)->clientCanCacheRead) {
|
||||
if ((data == NULL) && (*inode != NULL)) {
|
||||
if (CIFS_I(*inode)->clientCanCacheRead) {
|
||||
cFYI(1, "No need to revalidate cached inode sizes");
|
||||
goto cgii_exit;
|
||||
}
|
||||
}
|
||||
|
||||
/* if file info not passed in then get it from server */
|
||||
if (pfindData == NULL) {
|
||||
/* if inode info is not passed, get it from server */
|
||||
if (data == NULL) {
|
||||
if (!server->ops->query_path_info) {
|
||||
rc = -ENOSYS;
|
||||
goto cgii_exit;
|
||||
}
|
||||
buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
|
||||
if (buf == NULL) {
|
||||
rc = -ENOMEM;
|
||||
goto cgii_exit;
|
||||
}
|
||||
pfindData = (FILE_ALL_INFO *)buf;
|
||||
|
||||
/* could do find first instead but this returns more info */
|
||||
rc = CIFSSMBQPathInfo(xid, pTcon, full_path, pfindData,
|
||||
0 /* not legacy */,
|
||||
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
/* BB optimize code so we do not make the above call
|
||||
when server claims no NT SMB support and the above call
|
||||
failed at least once - set flag in tcon or mount */
|
||||
if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) {
|
||||
rc = SMBQueryInformation(xid, pTcon, full_path,
|
||||
pfindData, cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
adjustTZ = true;
|
||||
}
|
||||
data = (FILE_ALL_INFO *)buf;
|
||||
rc = server->ops->query_path_info(xid, tcon, cifs_sb, full_path,
|
||||
data, &adjust_tz);
|
||||
}
|
||||
|
||||
if (!rc) {
|
||||
cifs_all_info_to_fattr(&fattr, (FILE_ALL_INFO *) pfindData,
|
||||
cifs_sb, adjustTZ);
|
||||
cifs_all_info_to_fattr(&fattr, (FILE_ALL_INFO *)data, cifs_sb,
|
||||
adjust_tz);
|
||||
} else if (rc == -EREMOTE) {
|
||||
cifs_create_dfs_fattr(&fattr, sb);
|
||||
rc = 0;
|
||||
@ -668,28 +661,17 @@ int cifs_get_inode_info(struct inode **pinode,
|
||||
* Is an i_ino of zero legal? Can we use that to check if the server
|
||||
* supports returning inode numbers? Are there other sanity checks we
|
||||
* can use to ensure that the server is really filling in that field?
|
||||
*
|
||||
* We can not use the IndexNumber field by default from Windows or
|
||||
* Samba (in ALL_INFO buf) but we can request it explicitly. The SNIA
|
||||
* CIFS spec claims that this value is unique within the scope of a
|
||||
* share, and the windows docs hint that it's actually unique
|
||||
* per-machine.
|
||||
*
|
||||
* There may be higher info levels that work but are there Windows
|
||||
* server or network appliances for which IndexNumber field is not
|
||||
* guaranteed unique?
|
||||
*/
|
||||
if (*pinode == NULL) {
|
||||
if (*inode == NULL) {
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
|
||||
int rc1 = 0;
|
||||
|
||||
rc1 = CIFSGetSrvInodeNumber(xid, pTcon,
|
||||
full_path, &fattr.cf_uniqueid,
|
||||
cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
if (rc1 || !fattr.cf_uniqueid) {
|
||||
cFYI(1, "GetSrvInodeNum rc %d", rc1);
|
||||
if (server->ops->get_srv_inum)
|
||||
tmprc = server->ops->get_srv_inum(xid, tcon,
|
||||
cifs_sb, full_path, &fattr.cf_uniqueid,
|
||||
data);
|
||||
else
|
||||
tmprc = -ENOSYS;
|
||||
if (tmprc || !fattr.cf_uniqueid) {
|
||||
cFYI(1, "GetSrvInodeNum rc %d", tmprc);
|
||||
fattr.cf_uniqueid = iunique(sb, ROOT_I);
|
||||
cifs_autodisable_serverino(cifs_sb);
|
||||
}
|
||||
@ -697,7 +679,7 @@ int cifs_get_inode_info(struct inode **pinode,
|
||||
fattr.cf_uniqueid = iunique(sb, ROOT_I);
|
||||
}
|
||||
} else {
|
||||
fattr.cf_uniqueid = CIFS_I(*pinode)->uniqueid;
|
||||
fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid;
|
||||
}
|
||||
|
||||
/* query for SFU type info if supported and needed */
|
||||
@ -711,8 +693,7 @@ int cifs_get_inode_info(struct inode **pinode,
|
||||
#ifdef CONFIG_CIFS_ACL
|
||||
/* fill in 0777 bits from ACL */
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
|
||||
rc = cifs_acl_to_fattr(cifs_sb, &fattr, *pinode, full_path,
|
||||
pfid);
|
||||
rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, full_path, fid);
|
||||
if (rc) {
|
||||
cFYI(1, "%s: Getting ACL failed with error: %d",
|
||||
__func__, rc);
|
||||
@ -732,12 +713,12 @@ int cifs_get_inode_info(struct inode **pinode,
|
||||
cFYI(1, "CIFSCheckMFSymlink: %d", tmprc);
|
||||
}
|
||||
|
||||
if (!*pinode) {
|
||||
*pinode = cifs_iget(sb, &fattr);
|
||||
if (!*pinode)
|
||||
if (!*inode) {
|
||||
*inode = cifs_iget(sb, &fattr);
|
||||
if (!*inode)
|
||||
rc = -ENOMEM;
|
||||
} else {
|
||||
cifs_fattr_to_inode(*pinode, &fattr);
|
||||
cifs_fattr_to_inode(*inode, &fattr);
|
||||
}
|
||||
|
||||
cgii_exit:
|
||||
@ -750,38 +731,6 @@ static const struct inode_operations cifs_ipc_inode_ops = {
|
||||
.lookup = cifs_lookup,
|
||||
};
|
||||
|
||||
char *cifs_build_path_to_root(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
|
||||
struct cifs_tcon *tcon)
|
||||
{
|
||||
int pplen = vol->prepath ? strlen(vol->prepath) : 0;
|
||||
int dfsplen;
|
||||
char *full_path = NULL;
|
||||
|
||||
/* if no prefix path, simply set path to the root of share to "" */
|
||||
if (pplen == 0) {
|
||||
full_path = kmalloc(1, GFP_KERNEL);
|
||||
if (full_path)
|
||||
full_path[0] = 0;
|
||||
return full_path;
|
||||
}
|
||||
|
||||
if (tcon->Flags & SMB_SHARE_IS_IN_DFS)
|
||||
dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1);
|
||||
else
|
||||
dfsplen = 0;
|
||||
|
||||
full_path = kmalloc(dfsplen + pplen + 1, GFP_KERNEL);
|
||||
if (full_path == NULL)
|
||||
return full_path;
|
||||
|
||||
if (dfsplen)
|
||||
strncpy(full_path, tcon->treeName, dfsplen);
|
||||
strncpy(full_path + dfsplen, vol->prepath, pplen);
|
||||
convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
|
||||
full_path[dfsplen + pplen] = 0; /* add trailing null */
|
||||
return full_path;
|
||||
}
|
||||
|
||||
static int
|
||||
cifs_find_inode(struct inode *inode, void *opaque)
|
||||
{
|
||||
@ -886,13 +835,13 @@ retry_iget5_locked:
|
||||
/* gets root inode */
|
||||
struct inode *cifs_root_iget(struct super_block *sb)
|
||||
{
|
||||
int xid;
|
||||
unsigned int xid;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
|
||||
struct inode *inode = NULL;
|
||||
long rc;
|
||||
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
|
||||
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
if (tcon->unix_ext)
|
||||
rc = cifs_get_inode_info_unix(&inode, "", sb, xid);
|
||||
else
|
||||
@ -922,15 +871,15 @@ struct inode *cifs_root_iget(struct super_block *sb)
|
||||
}
|
||||
|
||||
out:
|
||||
/* can not call macro FreeXid here since in a void func
|
||||
/* can not call macro free_xid here since in a void func
|
||||
* TODO: This is no longer true
|
||||
*/
|
||||
_FreeXid(xid);
|
||||
_free_xid(xid);
|
||||
return inode;
|
||||
}
|
||||
|
||||
static int
|
||||
cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid,
|
||||
cifs_set_file_info(struct inode *inode, struct iattr *attrs, unsigned int xid,
|
||||
char *full_path, __u32 dosattr)
|
||||
{
|
||||
int rc;
|
||||
@ -1051,7 +1000,8 @@ out:
|
||||
* anything else.
|
||||
*/
|
||||
static int
|
||||
cifs_rename_pending_delete(char *full_path, struct dentry *dentry, int xid)
|
||||
cifs_rename_pending_delete(char *full_path, struct dentry *dentry,
|
||||
unsigned int xid)
|
||||
{
|
||||
int oplock = 0;
|
||||
int rc;
|
||||
@ -1171,7 +1121,7 @@ undo_setattr:
|
||||
int cifs_unlink(struct inode *dir, struct dentry *dentry)
|
||||
{
|
||||
int rc = 0;
|
||||
int xid;
|
||||
unsigned int xid;
|
||||
char *full_path = NULL;
|
||||
struct inode *inode = dentry->d_inode;
|
||||
struct cifsInodeInfo *cifs_inode;
|
||||
@ -1189,7 +1139,7 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry)
|
||||
return PTR_ERR(tlink);
|
||||
tcon = tlink_tcon(tlink);
|
||||
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
|
||||
/* Unlink can be called from rename so we can not take the
|
||||
* sb->s_vfs_rename_mutex here */
|
||||
@ -1199,9 +1149,8 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry)
|
||||
goto unlink_out;
|
||||
}
|
||||
|
||||
if ((tcon->ses->capabilities & CAP_UNIX) &&
|
||||
(CIFS_UNIX_POSIX_PATH_OPS_CAP &
|
||||
le64_to_cpu(tcon->fsUnixInfo.Capability))) {
|
||||
if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
|
||||
le64_to_cpu(tcon->fsUnixInfo.Capability))) {
|
||||
rc = CIFSPOSIXDelFile(xid, tcon, full_path,
|
||||
SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
@ -1265,7 +1214,7 @@ out_reval:
|
||||
unlink_out:
|
||||
kfree(full_path);
|
||||
kfree(attrs);
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
cifs_put_tlink(tlink);
|
||||
return rc;
|
||||
}
|
||||
@ -1273,10 +1222,10 @@ unlink_out:
|
||||
int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
|
||||
{
|
||||
int rc = 0, tmprc;
|
||||
int xid;
|
||||
unsigned int xid;
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
struct tcon_link *tlink;
|
||||
struct cifs_tcon *pTcon;
|
||||
struct cifs_tcon *tcon;
|
||||
char *full_path = NULL;
|
||||
struct inode *newinode = NULL;
|
||||
struct cifs_fattr fattr;
|
||||
@ -1287,9 +1236,9 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
|
||||
tlink = cifs_sb_tlink(cifs_sb);
|
||||
if (IS_ERR(tlink))
|
||||
return PTR_ERR(tlink);
|
||||
pTcon = tlink_tcon(tlink);
|
||||
tcon = tlink_tcon(tlink);
|
||||
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
|
||||
full_path = build_path_from_dentry(direntry);
|
||||
if (full_path == NULL) {
|
||||
@ -1297,9 +1246,8 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
|
||||
goto mkdir_out;
|
||||
}
|
||||
|
||||
if ((pTcon->ses->capabilities & CAP_UNIX) &&
|
||||
(CIFS_UNIX_POSIX_PATH_OPS_CAP &
|
||||
le64_to_cpu(pTcon->fsUnixInfo.Capability))) {
|
||||
if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
|
||||
le64_to_cpu(tcon->fsUnixInfo.Capability))) {
|
||||
u32 oplock = 0;
|
||||
FILE_UNIX_BASIC_INFO *pInfo =
|
||||
kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
|
||||
@ -1309,7 +1257,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
|
||||
}
|
||||
|
||||
mode &= ~current_umask();
|
||||
rc = CIFSPOSIXCreate(xid, pTcon, SMB_O_DIRECTORY | SMB_O_CREAT,
|
||||
rc = CIFSPOSIXCreate(xid, tcon, SMB_O_DIRECTORY | SMB_O_CREAT,
|
||||
mode, NULL /* netfid */, pInfo, &oplock,
|
||||
full_path, cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
@ -1353,14 +1301,14 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
|
||||
}
|
||||
mkdir_retry_old:
|
||||
/* BB add setting the equivalent of mode via CreateX w/ACLs */
|
||||
rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls,
|
||||
rc = CIFSSMBMkDir(xid, tcon, full_path, cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
if (rc) {
|
||||
cFYI(1, "cifs_mkdir returned 0x%x", rc);
|
||||
d_drop(direntry);
|
||||
} else {
|
||||
mkdir_get_info:
|
||||
if (pTcon->unix_ext)
|
||||
if (tcon->unix_ext)
|
||||
rc = cifs_get_inode_info_unix(&newinode, full_path,
|
||||
inode->i_sb, xid);
|
||||
else
|
||||
@ -1378,7 +1326,7 @@ mkdir_get_info:
|
||||
if (inode->i_mode & S_ISGID)
|
||||
mode |= S_ISGID;
|
||||
|
||||
if (pTcon->unix_ext) {
|
||||
if (tcon->unix_ext) {
|
||||
struct cifs_unix_set_info_args args = {
|
||||
.mode = mode,
|
||||
.ctime = NO_CHANGE_64,
|
||||
@ -1396,7 +1344,7 @@ mkdir_get_info:
|
||||
args.uid = NO_CHANGE_64;
|
||||
args.gid = NO_CHANGE_64;
|
||||
}
|
||||
CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args,
|
||||
CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
|
||||
cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
@ -1411,7 +1359,7 @@ mkdir_get_info:
|
||||
cifsInode = CIFS_I(newinode);
|
||||
dosattrs = cifsInode->cifsAttrs|ATTR_READONLY;
|
||||
pInfo.Attributes = cpu_to_le32(dosattrs);
|
||||
tmprc = CIFSSMBSetPathInfo(xid, pTcon,
|
||||
tmprc = CIFSSMBSetPathInfo(xid, tcon,
|
||||
full_path, &pInfo,
|
||||
cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
@ -1446,7 +1394,7 @@ mkdir_out:
|
||||
*/
|
||||
CIFS_I(inode)->time = 0;
|
||||
kfree(full_path);
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
cifs_put_tlink(tlink);
|
||||
return rc;
|
||||
}
|
||||
@ -1454,7 +1402,7 @@ mkdir_out:
|
||||
int cifs_rmdir(struct inode *inode, struct dentry *direntry)
|
||||
{
|
||||
int rc = 0;
|
||||
int xid;
|
||||
unsigned int xid;
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
struct tcon_link *tlink;
|
||||
struct cifs_tcon *pTcon;
|
||||
@ -1463,7 +1411,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
|
||||
|
||||
cFYI(1, "cifs_rmdir, inode = 0x%p", inode);
|
||||
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
|
||||
full_path = build_path_from_dentry(direntry);
|
||||
if (full_path == NULL) {
|
||||
@ -1506,13 +1454,14 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
|
||||
|
||||
rmdir_exit:
|
||||
kfree(full_path);
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
cifs_do_rename(int xid, struct dentry *from_dentry, const char *fromPath,
|
||||
struct dentry *to_dentry, const char *toPath)
|
||||
cifs_do_rename(unsigned int xid, struct dentry *from_dentry,
|
||||
const char *fromPath, struct dentry *to_dentry,
|
||||
const char *toPath)
|
||||
{
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb);
|
||||
struct tcon_link *tlink;
|
||||
@ -1571,7 +1520,8 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
|
||||
struct cifs_tcon *tcon;
|
||||
FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
|
||||
FILE_UNIX_BASIC_INFO *info_buf_target;
|
||||
int xid, rc, tmprc;
|
||||
unsigned int xid;
|
||||
int rc, tmprc;
|
||||
|
||||
cifs_sb = CIFS_SB(source_dir->i_sb);
|
||||
tlink = cifs_sb_tlink(cifs_sb);
|
||||
@ -1579,7 +1529,7 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
|
||||
return PTR_ERR(tlink);
|
||||
tcon = tlink_tcon(tlink);
|
||||
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
|
||||
/*
|
||||
* we already have the rename sem so we do not need to
|
||||
@ -1652,7 +1602,7 @@ cifs_rename_exit:
|
||||
kfree(info_buf_source);
|
||||
kfree(fromName);
|
||||
kfree(toName);
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
cifs_put_tlink(tlink);
|
||||
return rc;
|
||||
}
|
||||
@ -1727,7 +1677,7 @@ int cifs_revalidate_file_attr(struct file *filp)
|
||||
|
||||
int cifs_revalidate_dentry_attr(struct dentry *dentry)
|
||||
{
|
||||
int xid;
|
||||
unsigned int xid;
|
||||
int rc = 0;
|
||||
struct inode *inode = dentry->d_inode;
|
||||
struct super_block *sb = dentry->d_sb;
|
||||
@ -1739,7 +1689,7 @@ int cifs_revalidate_dentry_attr(struct dentry *dentry)
|
||||
if (!cifs_inode_needs_reval(inode))
|
||||
return rc;
|
||||
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
|
||||
/* can not safely grab the rename sem here if rename calls revalidate
|
||||
since that would deadlock */
|
||||
@ -1761,7 +1711,7 @@ int cifs_revalidate_dentry_attr(struct dentry *dentry)
|
||||
|
||||
out:
|
||||
kfree(full_path);
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -1869,7 +1819,7 @@ static void cifs_setsize(struct inode *inode, loff_t offset)
|
||||
|
||||
static int
|
||||
cifs_set_file_size(struct inode *inode, struct iattr *attrs,
|
||||
int xid, char *full_path)
|
||||
unsigned int xid, char *full_path)
|
||||
{
|
||||
int rc;
|
||||
struct cifsFileInfo *open_file;
|
||||
@ -1971,7 +1921,7 @@ static int
|
||||
cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
|
||||
{
|
||||
int rc;
|
||||
int xid;
|
||||
unsigned int xid;
|
||||
char *full_path = NULL;
|
||||
struct inode *inode = direntry->d_inode;
|
||||
struct cifsInodeInfo *cifsInode = CIFS_I(inode);
|
||||
@ -1984,7 +1934,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
|
||||
cFYI(1, "setattr_unix on file %s attrs->ia_valid=0x%x",
|
||||
direntry->d_name.name, attrs->ia_valid);
|
||||
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
|
||||
attrs->ia_valid |= ATTR_FORCE;
|
||||
@ -2104,14 +2054,14 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
|
||||
out:
|
||||
kfree(args);
|
||||
kfree(full_path);
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
|
||||
{
|
||||
int xid;
|
||||
unsigned int xid;
|
||||
uid_t uid = NO_CHANGE_32;
|
||||
gid_t gid = NO_CHANGE_32;
|
||||
struct inode *inode = direntry->d_inode;
|
||||
@ -2122,7 +2072,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
|
||||
__u32 dosattr = 0;
|
||||
__u64 mode = NO_CHANGE_64;
|
||||
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
|
||||
cFYI(1, "setattr on file %s attrs->iavalid 0x%x",
|
||||
direntry->d_name.name, attrs->ia_valid);
|
||||
@ -2132,14 +2082,14 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
|
||||
|
||||
rc = inode_change_ok(inode, attrs);
|
||||
if (rc < 0) {
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
|
||||
full_path = build_path_from_dentry(direntry);
|
||||
if (full_path == NULL) {
|
||||
rc = -ENOMEM;
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -2265,7 +2215,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
|
||||
|
||||
cifs_setattr_exit:
|
||||
kfree(full_path);
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,7 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
|
||||
{
|
||||
struct inode *inode = filep->f_dentry->d_inode;
|
||||
int rc = -ENOTTY; /* strange error - but the precedent */
|
||||
int xid;
|
||||
unsigned int xid;
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
#ifdef CONFIG_CIFS_POSIX
|
||||
struct cifsFileInfo *pSMBFile = filep->private_data;
|
||||
@ -44,7 +44,7 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
|
||||
__u64 caps;
|
||||
#endif /* CONFIG_CIFS_POSIX */
|
||||
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
|
||||
cFYI(1, "ioctl file %p cmd %u arg %lu", filep, command, arg);
|
||||
|
||||
@ -105,6 +105,6 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
|
||||
break;
|
||||
}
|
||||
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
|
@ -56,14 +56,14 @@ symlink_hash(unsigned int link_len, const char *link_str, u8 *md5_hash)
|
||||
md5 = crypto_alloc_shash("md5", 0, 0);
|
||||
if (IS_ERR(md5)) {
|
||||
rc = PTR_ERR(md5);
|
||||
cERROR(1, "%s: Crypto md5 allocation error %d\n", __func__, rc);
|
||||
cERROR(1, "%s: Crypto md5 allocation error %d", __func__, rc);
|
||||
return rc;
|
||||
}
|
||||
size = sizeof(struct shash_desc) + crypto_shash_descsize(md5);
|
||||
sdescmd5 = kmalloc(size, GFP_KERNEL);
|
||||
if (!sdescmd5) {
|
||||
rc = -ENOMEM;
|
||||
cERROR(1, "%s: Memory allocation failure\n", __func__);
|
||||
cERROR(1, "%s: Memory allocation failure", __func__);
|
||||
goto symlink_hash_err;
|
||||
}
|
||||
sdescmd5->shash.tfm = md5;
|
||||
@ -71,17 +71,17 @@ symlink_hash(unsigned int link_len, const char *link_str, u8 *md5_hash)
|
||||
|
||||
rc = crypto_shash_init(&sdescmd5->shash);
|
||||
if (rc) {
|
||||
cERROR(1, "%s: Could not init md5 shash\n", __func__);
|
||||
cERROR(1, "%s: Could not init md5 shash", __func__);
|
||||
goto symlink_hash_err;
|
||||
}
|
||||
rc = crypto_shash_update(&sdescmd5->shash, link_str, link_len);
|
||||
if (rc) {
|
||||
cERROR(1, "%s: Could not update iwth link_str\n", __func__);
|
||||
cERROR(1, "%s: Could not update iwth link_str", __func__);
|
||||
goto symlink_hash_err;
|
||||
}
|
||||
rc = crypto_shash_final(&sdescmd5->shash, md5_hash);
|
||||
if (rc)
|
||||
cERROR(1, "%s: Could not generate md5 hash\n", __func__);
|
||||
cERROR(1, "%s: Could not generate md5 hash", __func__);
|
||||
|
||||
symlink_hash_err:
|
||||
crypto_free_shash(md5);
|
||||
@ -115,7 +115,7 @@ CIFSParseMFSymlink(const u8 *buf,
|
||||
|
||||
rc = symlink_hash(link_len, link_str, md5_hash);
|
||||
if (rc) {
|
||||
cFYI(1, "%s: MD5 hash failure: %d\n", __func__, rc);
|
||||
cFYI(1, "%s: MD5 hash failure: %d", __func__, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -154,7 +154,7 @@ CIFSFormatMFSymlink(u8 *buf, unsigned int buf_len, const char *link_str)
|
||||
|
||||
rc = symlink_hash(link_len, link_str, md5_hash);
|
||||
if (rc) {
|
||||
cFYI(1, "%s: MD5 hash failure: %d\n", __func__, rc);
|
||||
cFYI(1, "%s: MD5 hash failure: %d", __func__, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -181,7 +181,7 @@ CIFSFormatMFSymlink(u8 *buf, unsigned int buf_len, const char *link_str)
|
||||
}
|
||||
|
||||
static int
|
||||
CIFSCreateMFSymLink(const int xid, struct cifs_tcon *tcon,
|
||||
CIFSCreateMFSymLink(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
const char *fromName, const char *toName,
|
||||
struct cifs_sb_info *cifs_sb)
|
||||
{
|
||||
@ -238,7 +238,7 @@ CIFSCreateMFSymLink(const int xid, struct cifs_tcon *tcon,
|
||||
}
|
||||
|
||||
static int
|
||||
CIFSQueryMFSymLink(const int xid, struct cifs_tcon *tcon,
|
||||
CIFSQueryMFSymLink(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
const unsigned char *searchName, char **symlinkinfo,
|
||||
const struct nls_table *nls_codepage, int remap)
|
||||
{
|
||||
@ -307,7 +307,7 @@ CIFSCouldBeMFSymlink(const struct cifs_fattr *fattr)
|
||||
int
|
||||
CIFSCheckMFSymlink(struct cifs_fattr *fattr,
|
||||
const unsigned char *path,
|
||||
struct cifs_sb_info *cifs_sb, int xid)
|
||||
struct cifs_sb_info *cifs_sb, unsigned int xid)
|
||||
{
|
||||
int rc;
|
||||
int oplock = 0;
|
||||
@ -390,7 +390,7 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
|
||||
struct dentry *direntry)
|
||||
{
|
||||
int rc = -EACCES;
|
||||
int xid;
|
||||
unsigned int xid;
|
||||
char *fromName = NULL;
|
||||
char *toName = NULL;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
@ -403,7 +403,7 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
|
||||
return PTR_ERR(tlink);
|
||||
pTcon = tlink_tcon(tlink);
|
||||
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
|
||||
fromName = build_path_from_dentry(old_file);
|
||||
toName = build_path_from_dentry(direntry);
|
||||
@ -455,7 +455,7 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
|
||||
cifs_hl_exit:
|
||||
kfree(fromName);
|
||||
kfree(toName);
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
cifs_put_tlink(tlink);
|
||||
return rc;
|
||||
}
|
||||
@ -465,14 +465,14 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
|
||||
{
|
||||
struct inode *inode = direntry->d_inode;
|
||||
int rc = -ENOMEM;
|
||||
int xid;
|
||||
unsigned int xid;
|
||||
char *full_path = NULL;
|
||||
char *target_path = NULL;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
struct tcon_link *tlink = NULL;
|
||||
struct cifs_tcon *tcon;
|
||||
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
|
||||
tlink = cifs_sb_tlink(cifs_sb);
|
||||
if (IS_ERR(tlink)) {
|
||||
@ -495,8 +495,8 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
|
||||
* but there doesn't seem to be any harm in allowing the client to
|
||||
* read them.
|
||||
*/
|
||||
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
|
||||
&& !(tcon->ses->capabilities & CAP_UNIX)) {
|
||||
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) &&
|
||||
!cap_unix(tcon->ses)) {
|
||||
rc = -EACCES;
|
||||
goto out;
|
||||
}
|
||||
@ -518,7 +518,7 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
|
||||
if ((rc != 0) && (tcon->ses->capabilities & CAP_UNIX))
|
||||
if ((rc != 0) && cap_unix(tcon->ses))
|
||||
rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, &target_path,
|
||||
cifs_sb->local_nls);
|
||||
|
||||
@ -529,7 +529,7 @@ out:
|
||||
target_path = ERR_PTR(rc);
|
||||
}
|
||||
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
if (tlink)
|
||||
cifs_put_tlink(tlink);
|
||||
nd_set_link(nd, target_path);
|
||||
@ -540,14 +540,14 @@ int
|
||||
cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
|
||||
{
|
||||
int rc = -EOPNOTSUPP;
|
||||
int xid;
|
||||
unsigned int xid;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
struct tcon_link *tlink;
|
||||
struct cifs_tcon *pTcon;
|
||||
char *full_path = NULL;
|
||||
struct inode *newinode = NULL;
|
||||
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
|
||||
tlink = cifs_sb_tlink(cifs_sb);
|
||||
if (IS_ERR(tlink)) {
|
||||
@ -594,7 +594,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
|
||||
symlink_exit:
|
||||
kfree(full_path);
|
||||
cifs_put_tlink(tlink);
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,9 @@
|
||||
#include "smberr.h"
|
||||
#include "nterr.h"
|
||||
#include "cifs_unicode.h"
|
||||
#ifdef CONFIG_CIFS_SMB2
|
||||
#include "smb2pdu.h"
|
||||
#endif
|
||||
|
||||
extern mempool_t *cifs_sm_req_poolp;
|
||||
extern mempool_t *cifs_req_poolp;
|
||||
@ -40,7 +43,7 @@ extern mempool_t *cifs_req_poolp;
|
||||
since the cifs fs was mounted */
|
||||
|
||||
unsigned int
|
||||
_GetXid(void)
|
||||
_get_xid(void)
|
||||
{
|
||||
unsigned int xid;
|
||||
|
||||
@ -58,7 +61,7 @@ _GetXid(void)
|
||||
}
|
||||
|
||||
void
|
||||
_FreeXid(unsigned int xid)
|
||||
_free_xid(unsigned int xid)
|
||||
{
|
||||
spin_lock(&GlobalMid_Lock);
|
||||
/* if (GlobalTotalActiveXid == 0)
|
||||
@ -143,17 +146,27 @@ struct smb_hdr *
|
||||
cifs_buf_get(void)
|
||||
{
|
||||
struct smb_hdr *ret_buf = NULL;
|
||||
size_t buf_size = sizeof(struct smb_hdr);
|
||||
|
||||
/* We could use negotiated size instead of max_msgsize -
|
||||
but it may be more efficient to always alloc same size
|
||||
albeit slightly larger than necessary and maxbuffersize
|
||||
defaults to this and can not be bigger */
|
||||
#ifdef CONFIG_CIFS_SMB2
|
||||
/*
|
||||
* SMB2 header is bigger than CIFS one - no problems to clean some
|
||||
* more bytes for CIFS.
|
||||
*/
|
||||
buf_size = sizeof(struct smb2_hdr);
|
||||
#endif
|
||||
/*
|
||||
* We could use negotiated size instead of max_msgsize -
|
||||
* but it may be more efficient to always alloc same size
|
||||
* albeit slightly larger than necessary and maxbuffersize
|
||||
* defaults to this and can not be bigger.
|
||||
*/
|
||||
ret_buf = mempool_alloc(cifs_req_poolp, GFP_NOFS);
|
||||
|
||||
/* clear the first few header bytes */
|
||||
/* for most paths, more is cleared in header_assemble */
|
||||
if (ret_buf) {
|
||||
memset(ret_buf, 0, sizeof(struct smb_hdr) + 3);
|
||||
memset(ret_buf, 0, buf_size + 3);
|
||||
atomic_inc(&bufAllocCount);
|
||||
#ifdef CONFIG_CIFS_STATS2
|
||||
atomic_inc(&totBufAllocCount);
|
||||
@ -448,7 +461,7 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
|
||||
if (tcon->tid != buf->Tid)
|
||||
continue;
|
||||
|
||||
cifs_stats_inc(&tcon->num_oplock_brks);
|
||||
cifs_stats_inc(&tcon->stats.cifs_stats.num_oplock_brks);
|
||||
spin_lock(&cifs_file_list_lock);
|
||||
list_for_each(tmp2, &tcon->openFileList) {
|
||||
netfile = list_entry(tmp2, struct cifsFileInfo,
|
||||
|
@ -31,7 +31,7 @@ const struct nt_err_code_struct nt_errs[] = {
|
||||
{"NT_STATUS_INVALID_INFO_CLASS", NT_STATUS_INVALID_INFO_CLASS},
|
||||
{"NT_STATUS_INFO_LENGTH_MISMATCH", NT_STATUS_INFO_LENGTH_MISMATCH},
|
||||
{"NT_STATUS_ACCESS_VIOLATION", NT_STATUS_ACCESS_VIOLATION},
|
||||
{"STATUS_BUFFER_OVERFLOW", STATUS_BUFFER_OVERFLOW},
|
||||
{"NT_STATUS_BUFFER_OVERFLOW", NT_STATUS_BUFFER_OVERFLOW},
|
||||
{"NT_STATUS_IN_PAGE_ERROR", NT_STATUS_IN_PAGE_ERROR},
|
||||
{"NT_STATUS_PAGEFILE_QUOTA", NT_STATUS_PAGEFILE_QUOTA},
|
||||
{"NT_STATUS_INVALID_HANDLE", NT_STATUS_INVALID_HANDLE},
|
||||
@ -681,7 +681,7 @@ const struct nt_err_code_struct nt_errs[] = {
|
||||
NT_STATUS_QUOTA_LIST_INCONSISTENT},
|
||||
{"NT_STATUS_FILE_IS_OFFLINE", NT_STATUS_FILE_IS_OFFLINE},
|
||||
{"NT_STATUS_NO_MORE_ENTRIES", NT_STATUS_NO_MORE_ENTRIES},
|
||||
{"STATUS_MORE_ENTRIES", STATUS_MORE_ENTRIES},
|
||||
{"STATUS_SOME_UNMAPPED", STATUS_SOME_UNMAPPED},
|
||||
{"NT_STATUS_MORE_ENTRIES", NT_STATUS_MORE_ENTRIES},
|
||||
{"NT_STATUS_SOME_UNMAPPED", NT_STATUS_SOME_UNMAPPED},
|
||||
{NULL, 0}
|
||||
};
|
||||
|
@ -35,18 +35,20 @@ struct nt_err_code_struct {
|
||||
extern const struct nt_err_code_struct nt_errs[];
|
||||
|
||||
/* Win32 Status codes. */
|
||||
#define STATUS_MORE_ENTRIES 0x0105
|
||||
#define ERROR_INVALID_PARAMETER 0x0057
|
||||
#define ERROR_INSUFFICIENT_BUFFER 0x007a
|
||||
#define STATUS_1804 0x070c
|
||||
#define STATUS_NOTIFY_ENUM_DIR 0x010c
|
||||
#define NT_STATUS_MORE_ENTRIES 0x0105
|
||||
#define NT_ERROR_INVALID_PARAMETER 0x0057
|
||||
#define NT_ERROR_INSUFFICIENT_BUFFER 0x007a
|
||||
#define NT_STATUS_1804 0x070c
|
||||
#define NT_STATUS_NOTIFY_ENUM_DIR 0x010c
|
||||
|
||||
/* Win32 Error codes extracted using a loop in smbclient then printing a
|
||||
netmon sniff to a file. */
|
||||
/*
|
||||
* Win32 Error codes extracted using a loop in smbclient then printing a netmon
|
||||
* sniff to a file.
|
||||
*/
|
||||
|
||||
#define NT_STATUS_OK 0x0000
|
||||
#define STATUS_SOME_UNMAPPED 0x0107
|
||||
#define STATUS_BUFFER_OVERFLOW 0x80000005
|
||||
#define NT_STATUS_OK 0x0000
|
||||
#define NT_STATUS_SOME_UNMAPPED 0x0107
|
||||
#define NT_STATUS_BUFFER_OVERFLOW 0x80000005
|
||||
#define NT_STATUS_NO_MORE_ENTRIES 0x8000001a
|
||||
#define NT_STATUS_MEDIA_CHANGED 0x8000001c
|
||||
#define NT_STATUS_END_OF_MEDIA 0x8000001e
|
||||
|
@ -126,3 +126,13 @@ typedef struct _AUTHENTICATE_MESSAGE {
|
||||
do not set the version is present flag */
|
||||
char UserString[0];
|
||||
} __attribute__((packed)) AUTHENTICATE_MESSAGE, *PAUTHENTICATE_MESSAGE;
|
||||
|
||||
/*
|
||||
* Size of the session key (crypto key encrypted with the password
|
||||
*/
|
||||
|
||||
int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, struct cifs_ses *ses);
|
||||
void build_ntlmssp_negotiate_blob(unsigned char *pbuffer, struct cifs_ses *ses);
|
||||
int build_ntlmssp_auth_blob(unsigned char *pbuffer, u16 *buflen,
|
||||
struct cifs_ses *ses,
|
||||
const struct nls_table *nls_cp);
|
||||
|
@ -193,7 +193,7 @@ cifs_std_info_to_fattr(struct cifs_fattr *fattr, FIND_FILE_STANDARD_INFO *info,
|
||||
we try to do FindFirst on (NTFS) directory symlinks */
|
||||
/*
|
||||
int get_symlink_reparse_path(char *full_path, struct cifs_sb_info *cifs_sb,
|
||||
int xid)
|
||||
unsigned int xid)
|
||||
{
|
||||
__u16 fid;
|
||||
int len;
|
||||
@ -220,7 +220,7 @@ int get_symlink_reparse_path(char *full_path, struct cifs_sb_info *cifs_sb,
|
||||
}
|
||||
*/
|
||||
|
||||
static int initiate_cifs_search(const int xid, struct file *file)
|
||||
static int initiate_cifs_search(const unsigned int xid, struct file *file)
|
||||
{
|
||||
__u16 search_flags;
|
||||
int rc = 0;
|
||||
@ -228,7 +228,7 @@ static int initiate_cifs_search(const int xid, struct file *file)
|
||||
struct cifsFileInfo *cifsFile;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
|
||||
struct tcon_link *tlink = NULL;
|
||||
struct cifs_tcon *pTcon;
|
||||
struct cifs_tcon *tcon;
|
||||
|
||||
if (file->private_data == NULL) {
|
||||
tlink = cifs_sb_tlink(cifs_sb);
|
||||
@ -242,10 +242,10 @@ static int initiate_cifs_search(const int xid, struct file *file)
|
||||
}
|
||||
file->private_data = cifsFile;
|
||||
cifsFile->tlink = cifs_get_tlink(tlink);
|
||||
pTcon = tlink_tcon(tlink);
|
||||
tcon = tlink_tcon(tlink);
|
||||
} else {
|
||||
cifsFile = file->private_data;
|
||||
pTcon = tlink_tcon(cifsFile->tlink);
|
||||
tcon = tlink_tcon(cifsFile->tlink);
|
||||
}
|
||||
|
||||
cifsFile->invalidHandle = true;
|
||||
@ -262,11 +262,11 @@ static int initiate_cifs_search(const int xid, struct file *file)
|
||||
ffirst_retry:
|
||||
/* test for Unix extensions */
|
||||
/* but now check for them on the share/mount not on the SMB session */
|
||||
/* if (pTcon->ses->capabilities & CAP_UNIX) { */
|
||||
if (pTcon->unix_ext)
|
||||
/* if (cap_unix(tcon->ses) { */
|
||||
if (tcon->unix_ext)
|
||||
cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX;
|
||||
else if ((pTcon->ses->capabilities &
|
||||
(CAP_NT_SMBS | CAP_NT_FIND)) == 0) {
|
||||
else if ((tcon->ses->capabilities &
|
||||
tcon->ses->server->vals->cap_nt_find) == 0) {
|
||||
cifsFile->srch_inf.info_level = SMB_FIND_FILE_INFO_STANDARD;
|
||||
} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
|
||||
cifsFile->srch_inf.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
|
||||
@ -278,7 +278,7 @@ ffirst_retry:
|
||||
if (backup_cred(cifs_sb))
|
||||
search_flags |= CIFS_SEARCH_BACKUP_SEARCH;
|
||||
|
||||
rc = CIFSFindFirst(xid, pTcon, full_path, cifs_sb->local_nls,
|
||||
rc = CIFSFindFirst(xid, tcon, full_path, cifs_sb->local_nls,
|
||||
&cifsFile->netfid, search_flags, &cifsFile->srch_inf,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb));
|
||||
@ -507,7 +507,7 @@ static int cifs_save_resume_key(const char *current_entry,
|
||||
assume that they are located in the findfirst return buffer.*/
|
||||
/* We start counting in the buffer with entry 2 and increment for every
|
||||
entry (do not increment for . or .. entry) */
|
||||
static int find_cifs_entry(const int xid, struct cifs_tcon *pTcon,
|
||||
static int find_cifs_entry(const unsigned int xid, struct cifs_tcon *pTcon,
|
||||
struct file *file, char **ppCurrentEntry, int *num_to_ret)
|
||||
{
|
||||
__u16 search_flags;
|
||||
@ -721,7 +721,8 @@ static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir,
|
||||
int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
|
||||
{
|
||||
int rc = 0;
|
||||
int xid, i;
|
||||
unsigned int xid;
|
||||
int i;
|
||||
struct cifs_tcon *pTcon;
|
||||
struct cifsFileInfo *cifsFile = NULL;
|
||||
char *current_entry;
|
||||
@ -730,7 +731,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
|
||||
char *end_of_smb;
|
||||
unsigned int max_len;
|
||||
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
|
||||
/*
|
||||
* Ensure FindFirst doesn't fail before doing filldir() for '.' and
|
||||
@ -768,7 +769,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
|
||||
|
||||
if (file->private_data == NULL) {
|
||||
rc = -EINVAL;
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
cifsFile = file->private_data;
|
||||
@ -840,6 +841,6 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
|
||||
} /* end switch */
|
||||
|
||||
rddir2_exit:
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
|
@ -364,7 +364,7 @@ static int decode_ascii_ssetup(char **pbcc_area, __u16 bleft,
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
|
||||
int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
|
||||
struct cifs_ses *ses)
|
||||
{
|
||||
unsigned int tioffset; /* challenge message target info area */
|
||||
@ -415,7 +415,7 @@ static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
|
||||
|
||||
/* We do not malloc the blob, it is passed in pbuffer, because
|
||||
it is fixed size, and small, making this approach cleaner */
|
||||
static void build_ntlmssp_negotiate_blob(unsigned char *pbuffer,
|
||||
void build_ntlmssp_negotiate_blob(unsigned char *pbuffer,
|
||||
struct cifs_ses *ses)
|
||||
{
|
||||
NEGOTIATE_MESSAGE *sec_blob = (NEGOTIATE_MESSAGE *)pbuffer;
|
||||
@ -451,7 +451,7 @@ static void build_ntlmssp_negotiate_blob(unsigned char *pbuffer,
|
||||
/* We do not malloc the blob, it is passed in pbuffer, because its
|
||||
maximum possible size is fixed and small, making this approach cleaner.
|
||||
This function returns the length of the data in the blob */
|
||||
static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
|
||||
int build_ntlmssp_auth_blob(unsigned char *pbuffer,
|
||||
u16 *buflen,
|
||||
struct cifs_ses *ses,
|
||||
const struct nls_table *nls_cp)
|
||||
@ -556,7 +556,7 @@ setup_ntlmv2_ret:
|
||||
}
|
||||
|
||||
int
|
||||
CIFS_SessSetup(unsigned int xid, struct cifs_ses *ses,
|
||||
CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses,
|
||||
const struct nls_table *nls_cp)
|
||||
{
|
||||
int rc = 0;
|
||||
@ -898,7 +898,7 @@ ssetup_ntlmssp_authenticate:
|
||||
if (action & GUEST_LOGIN)
|
||||
cFYI(1, "Guest login"); /* BB mark SesInfo struct? */
|
||||
ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */
|
||||
cFYI(1, "UID = %d ", ses->Suid);
|
||||
cFYI(1, "UID = %llu ", ses->Suid);
|
||||
/* response can have either 3 or 4 word count - Samba sends 3 */
|
||||
/* and lanman response is 3 */
|
||||
bytes_remaining = get_bcc(smb_buf);
|
||||
@ -938,7 +938,7 @@ ssetup_ntlmssp_authenticate:
|
||||
|
||||
ssetup_exit:
|
||||
if (spnego_key) {
|
||||
key_revoke(spnego_key);
|
||||
key_invalidate(spnego_key);
|
||||
key_put(spnego_key);
|
||||
}
|
||||
kfree(str_area);
|
||||
|
@ -101,7 +101,8 @@ cifs_find_mid(struct TCP_Server_Info *server, char *buffer)
|
||||
}
|
||||
|
||||
static void
|
||||
cifs_add_credits(struct TCP_Server_Info *server, const unsigned int add)
|
||||
cifs_add_credits(struct TCP_Server_Info *server, const unsigned int add,
|
||||
const int optype)
|
||||
{
|
||||
spin_lock(&server->req_lock);
|
||||
server->credits += add;
|
||||
@ -120,11 +121,17 @@ cifs_set_credits(struct TCP_Server_Info *server, const int val)
|
||||
}
|
||||
|
||||
static int *
|
||||
cifs_get_credits_field(struct TCP_Server_Info *server)
|
||||
cifs_get_credits_field(struct TCP_Server_Info *server, const int optype)
|
||||
{
|
||||
return &server->credits;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
cifs_get_credits(struct mid_q_entry *mid)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find a free multiplex id (SMB mid). Otherwise there could be
|
||||
* mid collisions which might cause problems, demultiplexing the
|
||||
@ -213,14 +220,382 @@ cifs_get_next_mid(struct TCP_Server_Info *server)
|
||||
return mid;
|
||||
}
|
||||
|
||||
/*
|
||||
return codes:
|
||||
0 not a transact2, or all data present
|
||||
>0 transact2 with that much data missing
|
||||
-EINVAL invalid transact2
|
||||
*/
|
||||
static int
|
||||
check2ndT2(char *buf)
|
||||
{
|
||||
struct smb_hdr *pSMB = (struct smb_hdr *)buf;
|
||||
struct smb_t2_rsp *pSMBt;
|
||||
int remaining;
|
||||
__u16 total_data_size, data_in_this_rsp;
|
||||
|
||||
if (pSMB->Command != SMB_COM_TRANSACTION2)
|
||||
return 0;
|
||||
|
||||
/* check for plausible wct, bcc and t2 data and parm sizes */
|
||||
/* check for parm and data offset going beyond end of smb */
|
||||
if (pSMB->WordCount != 10) { /* coalesce_t2 depends on this */
|
||||
cFYI(1, "invalid transact2 word count");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pSMBt = (struct smb_t2_rsp *)pSMB;
|
||||
|
||||
total_data_size = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount);
|
||||
data_in_this_rsp = get_unaligned_le16(&pSMBt->t2_rsp.DataCount);
|
||||
|
||||
if (total_data_size == data_in_this_rsp)
|
||||
return 0;
|
||||
else if (total_data_size < data_in_this_rsp) {
|
||||
cFYI(1, "total data %d smaller than data in frame %d",
|
||||
total_data_size, data_in_this_rsp);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
remaining = total_data_size - data_in_this_rsp;
|
||||
|
||||
cFYI(1, "missing %d bytes from transact2, check next response",
|
||||
remaining);
|
||||
if (total_data_size > CIFSMaxBufSize) {
|
||||
cERROR(1, "TotalDataSize %d is over maximum buffer %d",
|
||||
total_data_size, CIFSMaxBufSize);
|
||||
return -EINVAL;
|
||||
}
|
||||
return remaining;
|
||||
}
|
||||
|
||||
static int
|
||||
coalesce_t2(char *second_buf, struct smb_hdr *target_hdr)
|
||||
{
|
||||
struct smb_t2_rsp *pSMBs = (struct smb_t2_rsp *)second_buf;
|
||||
struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)target_hdr;
|
||||
char *data_area_of_tgt;
|
||||
char *data_area_of_src;
|
||||
int remaining;
|
||||
unsigned int byte_count, total_in_tgt;
|
||||
__u16 tgt_total_cnt, src_total_cnt, total_in_src;
|
||||
|
||||
src_total_cnt = get_unaligned_le16(&pSMBs->t2_rsp.TotalDataCount);
|
||||
tgt_total_cnt = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount);
|
||||
|
||||
if (tgt_total_cnt != src_total_cnt)
|
||||
cFYI(1, "total data count of primary and secondary t2 differ "
|
||||
"source=%hu target=%hu", src_total_cnt, tgt_total_cnt);
|
||||
|
||||
total_in_tgt = get_unaligned_le16(&pSMBt->t2_rsp.DataCount);
|
||||
|
||||
remaining = tgt_total_cnt - total_in_tgt;
|
||||
|
||||
if (remaining < 0) {
|
||||
cFYI(1, "Server sent too much data. tgt_total_cnt=%hu "
|
||||
"total_in_tgt=%hu", tgt_total_cnt, total_in_tgt);
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
if (remaining == 0) {
|
||||
/* nothing to do, ignore */
|
||||
cFYI(1, "no more data remains");
|
||||
return 0;
|
||||
}
|
||||
|
||||
total_in_src = get_unaligned_le16(&pSMBs->t2_rsp.DataCount);
|
||||
if (remaining < total_in_src)
|
||||
cFYI(1, "transact2 2nd response contains too much data");
|
||||
|
||||
/* find end of first SMB data area */
|
||||
data_area_of_tgt = (char *)&pSMBt->hdr.Protocol +
|
||||
get_unaligned_le16(&pSMBt->t2_rsp.DataOffset);
|
||||
|
||||
/* validate target area */
|
||||
data_area_of_src = (char *)&pSMBs->hdr.Protocol +
|
||||
get_unaligned_le16(&pSMBs->t2_rsp.DataOffset);
|
||||
|
||||
data_area_of_tgt += total_in_tgt;
|
||||
|
||||
total_in_tgt += total_in_src;
|
||||
/* is the result too big for the field? */
|
||||
if (total_in_tgt > USHRT_MAX) {
|
||||
cFYI(1, "coalesced DataCount too large (%u)", total_in_tgt);
|
||||
return -EPROTO;
|
||||
}
|
||||
put_unaligned_le16(total_in_tgt, &pSMBt->t2_rsp.DataCount);
|
||||
|
||||
/* fix up the BCC */
|
||||
byte_count = get_bcc(target_hdr);
|
||||
byte_count += total_in_src;
|
||||
/* is the result too big for the field? */
|
||||
if (byte_count > USHRT_MAX) {
|
||||
cFYI(1, "coalesced BCC too large (%u)", byte_count);
|
||||
return -EPROTO;
|
||||
}
|
||||
put_bcc(byte_count, target_hdr);
|
||||
|
||||
byte_count = be32_to_cpu(target_hdr->smb_buf_length);
|
||||
byte_count += total_in_src;
|
||||
/* don't allow buffer to overflow */
|
||||
if (byte_count > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
|
||||
cFYI(1, "coalesced BCC exceeds buffer size (%u)", byte_count);
|
||||
return -ENOBUFS;
|
||||
}
|
||||
target_hdr->smb_buf_length = cpu_to_be32(byte_count);
|
||||
|
||||
/* copy second buffer into end of first buffer */
|
||||
memcpy(data_area_of_tgt, data_area_of_src, total_in_src);
|
||||
|
||||
if (remaining != total_in_src) {
|
||||
/* more responses to go */
|
||||
cFYI(1, "waiting for more secondary responses");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* we are done */
|
||||
cFYI(1, "found the last secondary response");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
cifs_check_trans2(struct mid_q_entry *mid, struct TCP_Server_Info *server,
|
||||
char *buf, int malformed)
|
||||
{
|
||||
if (malformed)
|
||||
return false;
|
||||
if (check2ndT2(buf) <= 0)
|
||||
return false;
|
||||
mid->multiRsp = true;
|
||||
if (mid->resp_buf) {
|
||||
/* merge response - fix up 1st*/
|
||||
malformed = coalesce_t2(buf, mid->resp_buf);
|
||||
if (malformed > 0)
|
||||
return true;
|
||||
/* All parts received or packet is malformed. */
|
||||
mid->multiEnd = true;
|
||||
dequeue_mid(mid, malformed);
|
||||
return true;
|
||||
}
|
||||
if (!server->large_buf) {
|
||||
/*FIXME: switch to already allocated largebuf?*/
|
||||
cERROR(1, "1st trans2 resp needs bigbuf");
|
||||
} else {
|
||||
/* Have first buffer */
|
||||
mid->resp_buf = buf;
|
||||
mid->large_buf = true;
|
||||
server->bigbuf = NULL;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
cifs_need_neg(struct TCP_Server_Info *server)
|
||||
{
|
||||
return server->maxBuf == 0;
|
||||
}
|
||||
|
||||
static int
|
||||
cifs_negotiate(const unsigned int xid, struct cifs_ses *ses)
|
||||
{
|
||||
int rc;
|
||||
rc = CIFSSMBNegotiate(xid, ses);
|
||||
if (rc == -EAGAIN) {
|
||||
/* retry only once on 1st time connection */
|
||||
set_credits(ses->server, 1);
|
||||
rc = CIFSSMBNegotiate(xid, ses);
|
||||
if (rc == -EAGAIN)
|
||||
rc = -EHOSTDOWN;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void
|
||||
cifs_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon)
|
||||
{
|
||||
CIFSSMBQFSDeviceInfo(xid, tcon);
|
||||
CIFSSMBQFSAttributeInfo(xid, tcon);
|
||||
}
|
||||
|
||||
static int
|
||||
cifs_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
struct cifs_sb_info *cifs_sb, const char *full_path)
|
||||
{
|
||||
int rc;
|
||||
FILE_ALL_INFO *file_info;
|
||||
|
||||
file_info = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
|
||||
if (file_info == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
rc = CIFSSMBQPathInfo(xid, tcon, full_path, file_info,
|
||||
0 /* not legacy */, cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
|
||||
if (rc == -EOPNOTSUPP || rc == -EINVAL)
|
||||
rc = SMBQueryInformation(xid, tcon, full_path, file_info,
|
||||
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
kfree(file_info);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
cifs_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
struct cifs_sb_info *cifs_sb, const char *full_path,
|
||||
FILE_ALL_INFO *data, bool *adjustTZ)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* could do find first instead but this returns more info */
|
||||
rc = CIFSSMBQPathInfo(xid, tcon, full_path, data, 0 /* not legacy */,
|
||||
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
/*
|
||||
* BB optimize code so we do not make the above call when server claims
|
||||
* no NT SMB support and the above call failed at least once - set flag
|
||||
* in tcon or mount.
|
||||
*/
|
||||
if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) {
|
||||
rc = SMBQueryInformation(xid, tcon, full_path, data,
|
||||
cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
*adjustTZ = true;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
cifs_get_srv_inum(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
struct cifs_sb_info *cifs_sb, const char *full_path,
|
||||
u64 *uniqueid, FILE_ALL_INFO *data)
|
||||
{
|
||||
/*
|
||||
* We can not use the IndexNumber field by default from Windows or
|
||||
* Samba (in ALL_INFO buf) but we can request it explicitly. The SNIA
|
||||
* CIFS spec claims that this value is unique within the scope of a
|
||||
* share, and the windows docs hint that it's actually unique
|
||||
* per-machine.
|
||||
*
|
||||
* There may be higher info levels that work but are there Windows
|
||||
* server or network appliances for which IndexNumber field is not
|
||||
* guaranteed unique?
|
||||
*/
|
||||
return CIFSGetSrvInodeNumber(xid, tcon, full_path, uniqueid,
|
||||
cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
}
|
||||
|
||||
static char *
|
||||
cifs_build_path_to_root(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
|
||||
struct cifs_tcon *tcon)
|
||||
{
|
||||
int pplen = vol->prepath ? strlen(vol->prepath) : 0;
|
||||
int dfsplen;
|
||||
char *full_path = NULL;
|
||||
|
||||
/* if no prefix path, simply set path to the root of share to "" */
|
||||
if (pplen == 0) {
|
||||
full_path = kzalloc(1, GFP_KERNEL);
|
||||
return full_path;
|
||||
}
|
||||
|
||||
if (tcon->Flags & SMB_SHARE_IS_IN_DFS)
|
||||
dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1);
|
||||
else
|
||||
dfsplen = 0;
|
||||
|
||||
full_path = kmalloc(dfsplen + pplen + 1, GFP_KERNEL);
|
||||
if (full_path == NULL)
|
||||
return full_path;
|
||||
|
||||
if (dfsplen)
|
||||
strncpy(full_path, tcon->treeName, dfsplen);
|
||||
strncpy(full_path + dfsplen, vol->prepath, pplen);
|
||||
convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
|
||||
full_path[dfsplen + pplen] = 0; /* add trailing null */
|
||||
return full_path;
|
||||
}
|
||||
|
||||
static void
|
||||
cifs_clear_stats(struct cifs_tcon *tcon)
|
||||
{
|
||||
#ifdef CONFIG_CIFS_STATS
|
||||
atomic_set(&tcon->stats.cifs_stats.num_writes, 0);
|
||||
atomic_set(&tcon->stats.cifs_stats.num_reads, 0);
|
||||
atomic_set(&tcon->stats.cifs_stats.num_flushes, 0);
|
||||
atomic_set(&tcon->stats.cifs_stats.num_oplock_brks, 0);
|
||||
atomic_set(&tcon->stats.cifs_stats.num_opens, 0);
|
||||
atomic_set(&tcon->stats.cifs_stats.num_posixopens, 0);
|
||||
atomic_set(&tcon->stats.cifs_stats.num_posixmkdirs, 0);
|
||||
atomic_set(&tcon->stats.cifs_stats.num_closes, 0);
|
||||
atomic_set(&tcon->stats.cifs_stats.num_deletes, 0);
|
||||
atomic_set(&tcon->stats.cifs_stats.num_mkdirs, 0);
|
||||
atomic_set(&tcon->stats.cifs_stats.num_rmdirs, 0);
|
||||
atomic_set(&tcon->stats.cifs_stats.num_renames, 0);
|
||||
atomic_set(&tcon->stats.cifs_stats.num_t2renames, 0);
|
||||
atomic_set(&tcon->stats.cifs_stats.num_ffirst, 0);
|
||||
atomic_set(&tcon->stats.cifs_stats.num_fnext, 0);
|
||||
atomic_set(&tcon->stats.cifs_stats.num_fclose, 0);
|
||||
atomic_set(&tcon->stats.cifs_stats.num_hardlinks, 0);
|
||||
atomic_set(&tcon->stats.cifs_stats.num_symlinks, 0);
|
||||
atomic_set(&tcon->stats.cifs_stats.num_locks, 0);
|
||||
atomic_set(&tcon->stats.cifs_stats.num_acl_get, 0);
|
||||
atomic_set(&tcon->stats.cifs_stats.num_acl_set, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
cifs_print_stats(struct seq_file *m, struct cifs_tcon *tcon)
|
||||
{
|
||||
#ifdef CONFIG_CIFS_STATS
|
||||
seq_printf(m, " Oplocks breaks: %d",
|
||||
atomic_read(&tcon->stats.cifs_stats.num_oplock_brks));
|
||||
seq_printf(m, "\nReads: %d Bytes: %llu",
|
||||
atomic_read(&tcon->stats.cifs_stats.num_reads),
|
||||
(long long)(tcon->bytes_read));
|
||||
seq_printf(m, "\nWrites: %d Bytes: %llu",
|
||||
atomic_read(&tcon->stats.cifs_stats.num_writes),
|
||||
(long long)(tcon->bytes_written));
|
||||
seq_printf(m, "\nFlushes: %d",
|
||||
atomic_read(&tcon->stats.cifs_stats.num_flushes));
|
||||
seq_printf(m, "\nLocks: %d HardLinks: %d Symlinks: %d",
|
||||
atomic_read(&tcon->stats.cifs_stats.num_locks),
|
||||
atomic_read(&tcon->stats.cifs_stats.num_hardlinks),
|
||||
atomic_read(&tcon->stats.cifs_stats.num_symlinks));
|
||||
seq_printf(m, "\nOpens: %d Closes: %d Deletes: %d",
|
||||
atomic_read(&tcon->stats.cifs_stats.num_opens),
|
||||
atomic_read(&tcon->stats.cifs_stats.num_closes),
|
||||
atomic_read(&tcon->stats.cifs_stats.num_deletes));
|
||||
seq_printf(m, "\nPosix Opens: %d Posix Mkdirs: %d",
|
||||
atomic_read(&tcon->stats.cifs_stats.num_posixopens),
|
||||
atomic_read(&tcon->stats.cifs_stats.num_posixmkdirs));
|
||||
seq_printf(m, "\nMkdirs: %d Rmdirs: %d",
|
||||
atomic_read(&tcon->stats.cifs_stats.num_mkdirs),
|
||||
atomic_read(&tcon->stats.cifs_stats.num_rmdirs));
|
||||
seq_printf(m, "\nRenames: %d T2 Renames %d",
|
||||
atomic_read(&tcon->stats.cifs_stats.num_renames),
|
||||
atomic_read(&tcon->stats.cifs_stats.num_t2renames));
|
||||
seq_printf(m, "\nFindFirst: %d FNext %d FClose %d",
|
||||
atomic_read(&tcon->stats.cifs_stats.num_ffirst),
|
||||
atomic_read(&tcon->stats.cifs_stats.num_fnext),
|
||||
atomic_read(&tcon->stats.cifs_stats.num_fclose));
|
||||
#endif
|
||||
}
|
||||
|
||||
struct smb_version_operations smb1_operations = {
|
||||
.send_cancel = send_nt_cancel,
|
||||
.compare_fids = cifs_compare_fids,
|
||||
.setup_request = cifs_setup_request,
|
||||
.setup_async_request = cifs_setup_async_request,
|
||||
.check_receive = cifs_check_receive,
|
||||
.add_credits = cifs_add_credits,
|
||||
.set_credits = cifs_set_credits,
|
||||
.get_credits_field = cifs_get_credits_field,
|
||||
.get_credits = cifs_get_credits,
|
||||
.get_next_mid = cifs_get_next_mid,
|
||||
.read_data_offset = cifs_read_data_offset,
|
||||
.read_data_length = cifs_read_data_length,
|
||||
@ -228,7 +603,23 @@ struct smb_version_operations smb1_operations = {
|
||||
.find_mid = cifs_find_mid,
|
||||
.check_message = checkSMB,
|
||||
.dump_detail = cifs_dump_detail,
|
||||
.clear_stats = cifs_clear_stats,
|
||||
.print_stats = cifs_print_stats,
|
||||
.is_oplock_break = is_valid_oplock_break,
|
||||
.check_trans2 = cifs_check_trans2,
|
||||
.need_neg = cifs_need_neg,
|
||||
.negotiate = cifs_negotiate,
|
||||
.sess_setup = CIFS_SessSetup,
|
||||
.logoff = CIFSSMBLogoff,
|
||||
.tree_connect = CIFSTCon,
|
||||
.tree_disconnect = CIFSSMBTDis,
|
||||
.get_dfs_refer = CIFSGetDFSRefer,
|
||||
.qfs_tcon = cifs_qfs_tcon,
|
||||
.is_path_accessible = cifs_is_path_accessible,
|
||||
.query_path_info = cifs_query_path_info,
|
||||
.get_srv_inum = cifs_get_srv_inum,
|
||||
.build_path_to_root = cifs_build_path_to_root,
|
||||
.echo = CIFSSMBEcho,
|
||||
};
|
||||
|
||||
struct smb_version_values smb1_values = {
|
||||
@ -240,4 +631,8 @@ struct smb_version_values smb1_values = {
|
||||
.header_size = sizeof(struct smb_hdr),
|
||||
.max_header_size = MAX_CIFS_HDR_SIZE,
|
||||
.read_rsp_size = sizeof(READ_RSP),
|
||||
.lock_cmd = cpu_to_le16(SMB_COM_LOCKING_ANDX),
|
||||
.cap_unix = CAP_UNIX,
|
||||
.cap_nt_find = CAP_NT_SMBS | CAP_NT_FIND,
|
||||
.cap_large_files = CAP_LARGE_FILES,
|
||||
};
|
||||
|
44
fs/cifs/smb2glob.h
Normal file
44
fs/cifs/smb2glob.h
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* fs/cifs/smb2glob.h
|
||||
*
|
||||
* Definitions for various global variables and structures
|
||||
*
|
||||
* Copyright (C) International Business Machines Corp., 2002, 2011
|
||||
* Etersoft, 2012
|
||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||
* Jeremy Allison (jra@samba.org)
|
||||
* Pavel Shilovsky (pshilovsky@samba.org) 2012
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
|
||||
* the GNU Lesser General Public License for more details.
|
||||
*
|
||||
*/
|
||||
#ifndef _SMB2_GLOB_H
|
||||
#define _SMB2_GLOB_H
|
||||
|
||||
/*
|
||||
*****************************************************************
|
||||
* Constants go here
|
||||
*****************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
* Identifiers for functions that use the open, operation, close pattern
|
||||
* in smb2inode.c:smb2_open_op_close()
|
||||
*/
|
||||
#define SMB2_OP_SET_DELETE 1
|
||||
#define SMB2_OP_SET_INFO 2
|
||||
#define SMB2_OP_QUERY_INFO 3
|
||||
#define SMB2_OP_QUERY_DIR 4
|
||||
#define SMB2_OP_MKDIR 5
|
||||
#define SMB2_OP_RENAME 6
|
||||
#define SMB2_OP_DELETE 7
|
||||
|
||||
#endif /* _SMB2_GLOB_H */
|
124
fs/cifs/smb2inode.c
Normal file
124
fs/cifs/smb2inode.c
Normal file
@ -0,0 +1,124 @@
|
||||
/*
|
||||
* fs/cifs/smb2inode.c
|
||||
*
|
||||
* Copyright (C) International Business Machines Corp., 2002, 2011
|
||||
* Etersoft, 2012
|
||||
* Author(s): Pavel Shilovsky (pshilovsky@samba.org),
|
||||
* Steve French (sfrench@us.ibm.com)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
|
||||
* the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include <linux/fs.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <asm/div64.h>
|
||||
#include "cifsfs.h"
|
||||
#include "cifspdu.h"
|
||||
#include "cifsglob.h"
|
||||
#include "cifsproto.h"
|
||||
#include "cifs_debug.h"
|
||||
#include "cifs_fs_sb.h"
|
||||
#include "cifs_unicode.h"
|
||||
#include "fscache.h"
|
||||
#include "smb2glob.h"
|
||||
#include "smb2pdu.h"
|
||||
#include "smb2proto.h"
|
||||
|
||||
static int
|
||||
smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
struct cifs_sb_info *cifs_sb, const char *full_path,
|
||||
__u32 desired_access, __u32 create_disposition,
|
||||
__u32 file_attributes, __u32 create_options,
|
||||
void *data, int command)
|
||||
{
|
||||
int rc, tmprc = 0;
|
||||
u64 persistent_fid, volatile_fid;
|
||||
__le16 *utf16_path;
|
||||
|
||||
utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
|
||||
if (!utf16_path)
|
||||
return -ENOMEM;
|
||||
|
||||
rc = SMB2_open(xid, tcon, utf16_path, &persistent_fid, &volatile_fid,
|
||||
desired_access, create_disposition, file_attributes,
|
||||
create_options);
|
||||
if (rc) {
|
||||
kfree(utf16_path);
|
||||
return rc;
|
||||
}
|
||||
|
||||
switch (command) {
|
||||
case SMB2_OP_DELETE:
|
||||
break;
|
||||
case SMB2_OP_QUERY_INFO:
|
||||
tmprc = SMB2_query_info(xid, tcon, persistent_fid,
|
||||
volatile_fid,
|
||||
(struct smb2_file_all_info *)data);
|
||||
break;
|
||||
case SMB2_OP_MKDIR:
|
||||
/*
|
||||
* Directories are created through parameters in the
|
||||
* SMB2_open() call.
|
||||
*/
|
||||
break;
|
||||
default:
|
||||
cERROR(1, "Invalid command");
|
||||
break;
|
||||
}
|
||||
|
||||
rc = SMB2_close(xid, tcon, persistent_fid, volatile_fid);
|
||||
if (tmprc)
|
||||
rc = tmprc;
|
||||
kfree(utf16_path);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void
|
||||
move_smb2_info_to_cifs(FILE_ALL_INFO *dst, struct smb2_file_all_info *src)
|
||||
{
|
||||
memcpy(dst, src, (size_t)(&src->CurrentByteOffset) - (size_t)src);
|
||||
dst->CurrentByteOffset = src->CurrentByteOffset;
|
||||
dst->Mode = src->Mode;
|
||||
dst->AlignmentRequirement = src->AlignmentRequirement;
|
||||
dst->IndexNumber1 = 0; /* we don't use it */
|
||||
}
|
||||
|
||||
int
|
||||
smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
struct cifs_sb_info *cifs_sb, const char *full_path,
|
||||
FILE_ALL_INFO *data, bool *adjust_tz)
|
||||
{
|
||||
int rc;
|
||||
struct smb2_file_all_info *smb2_data;
|
||||
|
||||
*adjust_tz = false;
|
||||
|
||||
smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + MAX_NAME * 2,
|
||||
GFP_KERNEL);
|
||||
if (smb2_data == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
rc = smb2_open_op_close(xid, tcon, cifs_sb, full_path,
|
||||
FILE_READ_ATTRIBUTES, FILE_OPEN, 0, 0,
|
||||
smb2_data, SMB2_OP_QUERY_INFO);
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
move_smb2_info_to_cifs(data, smb2_data);
|
||||
out:
|
||||
kfree(smb2_data);
|
||||
return rc;
|
||||
}
|
2477
fs/cifs/smb2maperror.c
Normal file
2477
fs/cifs/smb2maperror.c
Normal file
File diff suppressed because it is too large
Load Diff
347
fs/cifs/smb2misc.c
Normal file
347
fs/cifs/smb2misc.c
Normal file
@ -0,0 +1,347 @@
|
||||
/*
|
||||
* fs/cifs/smb2misc.c
|
||||
*
|
||||
* Copyright (C) International Business Machines Corp., 2002,2011
|
||||
* Etersoft, 2012
|
||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||
* Pavel Shilovsky (pshilovsky@samba.org) 2012
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
|
||||
* the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include <linux/ctype.h>
|
||||
#include "smb2pdu.h"
|
||||
#include "cifsglob.h"
|
||||
#include "cifsproto.h"
|
||||
#include "smb2proto.h"
|
||||
#include "cifs_debug.h"
|
||||
#include "cifs_unicode.h"
|
||||
#include "smb2status.h"
|
||||
|
||||
static int
|
||||
check_smb2_hdr(struct smb2_hdr *hdr, __u64 mid)
|
||||
{
|
||||
/*
|
||||
* Make sure that this really is an SMB, that it is a response,
|
||||
* and that the message ids match.
|
||||
*/
|
||||
if ((*(__le32 *)hdr->ProtocolId == SMB2_PROTO_NUMBER) &&
|
||||
(mid == hdr->MessageId)) {
|
||||
if (hdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR)
|
||||
return 0;
|
||||
else {
|
||||
/* only one valid case where server sends us request */
|
||||
if (hdr->Command == SMB2_OPLOCK_BREAK)
|
||||
return 0;
|
||||
else
|
||||
cERROR(1, "Received Request not response");
|
||||
}
|
||||
} else { /* bad signature or mid */
|
||||
if (*(__le32 *)hdr->ProtocolId != SMB2_PROTO_NUMBER)
|
||||
cERROR(1, "Bad protocol string signature header %x",
|
||||
*(unsigned int *) hdr->ProtocolId);
|
||||
if (mid != hdr->MessageId)
|
||||
cERROR(1, "Mids do not match");
|
||||
}
|
||||
cERROR(1, "Bad SMB detected. The Mid=%llu", hdr->MessageId);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following table defines the expected "StructureSize" of SMB2 responses
|
||||
* in order by SMB2 command. This is similar to "wct" in SMB/CIFS responses.
|
||||
*
|
||||
* Note that commands are defined in smb2pdu.h in le16 but the array below is
|
||||
* indexed by command in host byte order
|
||||
*/
|
||||
static const __le16 smb2_rsp_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = {
|
||||
/* SMB2_NEGOTIATE */ __constant_cpu_to_le16(65),
|
||||
/* SMB2_SESSION_SETUP */ __constant_cpu_to_le16(9),
|
||||
/* SMB2_LOGOFF */ __constant_cpu_to_le16(4),
|
||||
/* SMB2_TREE_CONNECT */ __constant_cpu_to_le16(16),
|
||||
/* SMB2_TREE_DISCONNECT */ __constant_cpu_to_le16(4),
|
||||
/* SMB2_CREATE */ __constant_cpu_to_le16(89),
|
||||
/* SMB2_CLOSE */ __constant_cpu_to_le16(60),
|
||||
/* SMB2_FLUSH */ __constant_cpu_to_le16(4),
|
||||
/* SMB2_READ */ __constant_cpu_to_le16(17),
|
||||
/* SMB2_WRITE */ __constant_cpu_to_le16(17),
|
||||
/* SMB2_LOCK */ __constant_cpu_to_le16(4),
|
||||
/* SMB2_IOCTL */ __constant_cpu_to_le16(49),
|
||||
/* BB CHECK this ... not listed in documentation */
|
||||
/* SMB2_CANCEL */ __constant_cpu_to_le16(0),
|
||||
/* SMB2_ECHO */ __constant_cpu_to_le16(4),
|
||||
/* SMB2_QUERY_DIRECTORY */ __constant_cpu_to_le16(9),
|
||||
/* SMB2_CHANGE_NOTIFY */ __constant_cpu_to_le16(9),
|
||||
/* SMB2_QUERY_INFO */ __constant_cpu_to_le16(9),
|
||||
/* SMB2_SET_INFO */ __constant_cpu_to_le16(2),
|
||||
/* BB FIXME can also be 44 for lease break */
|
||||
/* SMB2_OPLOCK_BREAK */ __constant_cpu_to_le16(24)
|
||||
};
|
||||
|
||||
int
|
||||
smb2_check_message(char *buf, unsigned int length)
|
||||
{
|
||||
struct smb2_hdr *hdr = (struct smb2_hdr *)buf;
|
||||
struct smb2_pdu *pdu = (struct smb2_pdu *)hdr;
|
||||
__u64 mid = hdr->MessageId;
|
||||
__u32 len = get_rfc1002_length(buf);
|
||||
__u32 clc_len; /* calculated length */
|
||||
int command;
|
||||
|
||||
/* BB disable following printk later */
|
||||
cFYI(1, "%s length: 0x%x, smb_buf_length: 0x%x", __func__, length, len);
|
||||
|
||||
/*
|
||||
* Add function to do table lookup of StructureSize by command
|
||||
* ie Validate the wct via smb2_struct_sizes table above
|
||||
*/
|
||||
|
||||
if (length < 2 + sizeof(struct smb2_hdr)) {
|
||||
if ((length >= sizeof(struct smb2_hdr)) && (hdr->Status != 0)) {
|
||||
pdu->StructureSize2 = 0;
|
||||
/*
|
||||
* As with SMB/CIFS, on some error cases servers may
|
||||
* not return wct properly
|
||||
*/
|
||||
return 0;
|
||||
} else {
|
||||
cERROR(1, "Length less than SMB header size");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
if (len > CIFSMaxBufSize + MAX_SMB2_HDR_SIZE - 4) {
|
||||
cERROR(1, "SMB length greater than maximum, mid=%lld", mid);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (check_smb2_hdr(hdr, mid))
|
||||
return 1;
|
||||
|
||||
if (hdr->StructureSize != SMB2_HEADER_SIZE) {
|
||||
cERROR(1, "Illegal structure size %d",
|
||||
le16_to_cpu(hdr->StructureSize));
|
||||
return 1;
|
||||
}
|
||||
|
||||
command = le16_to_cpu(hdr->Command);
|
||||
if (command >= NUMBER_OF_SMB2_COMMANDS) {
|
||||
cERROR(1, "Illegal SMB2 command %d", command);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (smb2_rsp_struct_sizes[command] != pdu->StructureSize2) {
|
||||
if (hdr->Status == 0 ||
|
||||
pdu->StructureSize2 != SMB2_ERROR_STRUCTURE_SIZE2) {
|
||||
/* error packets have 9 byte structure size */
|
||||
cERROR(1, "Illegal response size %u for command %d",
|
||||
le16_to_cpu(pdu->StructureSize2), command);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (4 + len != length) {
|
||||
cERROR(1, "Total length %u RFC1002 length %u mismatch mid %llu",
|
||||
length, 4 + len, mid);
|
||||
return 1;
|
||||
}
|
||||
|
||||
clc_len = smb2_calc_size(hdr);
|
||||
|
||||
if (4 + len != clc_len) {
|
||||
cFYI(1, "Calculated size %u length %u mismatch mid %llu",
|
||||
clc_len, 4 + len, mid);
|
||||
if (clc_len == 4 + len + 1) /* BB FIXME (fix samba) */
|
||||
return 0; /* BB workaround Samba 3 bug SessSetup rsp */
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The size of the variable area depends on the offset and length fields
|
||||
* located in different fields for various SMB2 responses. SMB2 responses
|
||||
* with no variable length info, show an offset of zero for the offset field.
|
||||
*/
|
||||
static const bool has_smb2_data_area[NUMBER_OF_SMB2_COMMANDS] = {
|
||||
/* SMB2_NEGOTIATE */ true,
|
||||
/* SMB2_SESSION_SETUP */ true,
|
||||
/* SMB2_LOGOFF */ false,
|
||||
/* SMB2_TREE_CONNECT */ false,
|
||||
/* SMB2_TREE_DISCONNECT */ false,
|
||||
/* SMB2_CREATE */ true,
|
||||
/* SMB2_CLOSE */ false,
|
||||
/* SMB2_FLUSH */ false,
|
||||
/* SMB2_READ */ true,
|
||||
/* SMB2_WRITE */ false,
|
||||
/* SMB2_LOCK */ false,
|
||||
/* SMB2_IOCTL */ true,
|
||||
/* SMB2_CANCEL */ false, /* BB CHECK this not listed in documentation */
|
||||
/* SMB2_ECHO */ false,
|
||||
/* SMB2_QUERY_DIRECTORY */ true,
|
||||
/* SMB2_CHANGE_NOTIFY */ true,
|
||||
/* SMB2_QUERY_INFO */ true,
|
||||
/* SMB2_SET_INFO */ false,
|
||||
/* SMB2_OPLOCK_BREAK */ false
|
||||
};
|
||||
|
||||
/*
|
||||
* Returns the pointer to the beginning of the data area. Length of the data
|
||||
* area and the offset to it (from the beginning of the smb are also returned.
|
||||
*/
|
||||
char *
|
||||
smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr)
|
||||
{
|
||||
*off = 0;
|
||||
*len = 0;
|
||||
|
||||
/* error responses do not have data area */
|
||||
if (hdr->Status && hdr->Status != STATUS_MORE_PROCESSING_REQUIRED &&
|
||||
(((struct smb2_err_rsp *)hdr)->StructureSize) ==
|
||||
SMB2_ERROR_STRUCTURE_SIZE2)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* Following commands have data areas so we have to get the location
|
||||
* of the data buffer offset and data buffer length for the particular
|
||||
* command.
|
||||
*/
|
||||
switch (hdr->Command) {
|
||||
case SMB2_NEGOTIATE:
|
||||
*off = le16_to_cpu(
|
||||
((struct smb2_negotiate_rsp *)hdr)->SecurityBufferOffset);
|
||||
*len = le16_to_cpu(
|
||||
((struct smb2_negotiate_rsp *)hdr)->SecurityBufferLength);
|
||||
break;
|
||||
case SMB2_SESSION_SETUP:
|
||||
*off = le16_to_cpu(
|
||||
((struct smb2_sess_setup_rsp *)hdr)->SecurityBufferOffset);
|
||||
*len = le16_to_cpu(
|
||||
((struct smb2_sess_setup_rsp *)hdr)->SecurityBufferLength);
|
||||
break;
|
||||
case SMB2_CREATE:
|
||||
*off = le32_to_cpu(
|
||||
((struct smb2_create_rsp *)hdr)->CreateContextsOffset);
|
||||
*len = le32_to_cpu(
|
||||
((struct smb2_create_rsp *)hdr)->CreateContextsLength);
|
||||
break;
|
||||
case SMB2_QUERY_INFO:
|
||||
*off = le16_to_cpu(
|
||||
((struct smb2_query_info_rsp *)hdr)->OutputBufferOffset);
|
||||
*len = le32_to_cpu(
|
||||
((struct smb2_query_info_rsp *)hdr)->OutputBufferLength);
|
||||
break;
|
||||
case SMB2_READ:
|
||||
case SMB2_QUERY_DIRECTORY:
|
||||
case SMB2_IOCTL:
|
||||
case SMB2_CHANGE_NOTIFY:
|
||||
default:
|
||||
/* BB FIXME for unimplemented cases above */
|
||||
cERROR(1, "no length check for command");
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Invalid length or offset probably means data area is invalid, but
|
||||
* we have little choice but to ignore the data area in this case.
|
||||
*/
|
||||
if (*off > 4096) {
|
||||
cERROR(1, "offset %d too large, data area ignored", *off);
|
||||
*len = 0;
|
||||
*off = 0;
|
||||
} else if (*off < 0) {
|
||||
cERROR(1, "negative offset %d to data invalid ignore data area",
|
||||
*off);
|
||||
*off = 0;
|
||||
*len = 0;
|
||||
} else if (*len < 0) {
|
||||
cERROR(1, "negative data length %d invalid, data area ignored",
|
||||
*len);
|
||||
*len = 0;
|
||||
} else if (*len > 128 * 1024) {
|
||||
cERROR(1, "data area larger than 128K: %d", *len);
|
||||
*len = 0;
|
||||
}
|
||||
|
||||
/* return pointer to beginning of data area, ie offset from SMB start */
|
||||
if ((*off != 0) && (*len != 0))
|
||||
return hdr->ProtocolId + *off;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the size of the SMB message based on the fixed header
|
||||
* portion, the number of word parameters and the data portion of the message.
|
||||
*/
|
||||
unsigned int
|
||||
smb2_calc_size(struct smb2_hdr *hdr)
|
||||
{
|
||||
struct smb2_pdu *pdu = (struct smb2_pdu *)hdr;
|
||||
int offset; /* the offset from the beginning of SMB to data area */
|
||||
int data_length; /* the length of the variable length data area */
|
||||
/* Structure Size has already been checked to make sure it is 64 */
|
||||
int len = 4 + le16_to_cpu(pdu->hdr.StructureSize);
|
||||
|
||||
/*
|
||||
* StructureSize2, ie length of fixed parameter area has already
|
||||
* been checked to make sure it is the correct length.
|
||||
*/
|
||||
len += le16_to_cpu(pdu->StructureSize2);
|
||||
|
||||
if (has_smb2_data_area[le16_to_cpu(hdr->Command)] == false)
|
||||
goto calc_size_exit;
|
||||
|
||||
smb2_get_data_area_len(&offset, &data_length, hdr);
|
||||
cFYI(1, "SMB2 data length %d offset %d", data_length, offset);
|
||||
|
||||
if (data_length > 0) {
|
||||
/*
|
||||
* Check to make sure that data area begins after fixed area,
|
||||
* Note that last byte of the fixed area is part of data area
|
||||
* for some commands, typically those with odd StructureSize,
|
||||
* so we must add one to the calculation (and 4 to account for
|
||||
* the size of the RFC1001 hdr.
|
||||
*/
|
||||
if (offset + 4 + 1 < len) {
|
||||
cERROR(1, "data area offset %d overlaps SMB2 header %d",
|
||||
offset + 4 + 1, len);
|
||||
data_length = 0;
|
||||
} else {
|
||||
len = 4 + offset + data_length;
|
||||
}
|
||||
}
|
||||
calc_size_exit:
|
||||
cFYI(1, "SMB2 len %d", len);
|
||||
return len;
|
||||
}
|
||||
|
||||
/* Note: caller must free return buffer */
|
||||
__le16 *
|
||||
cifs_convert_path_to_utf16(const char *from, struct cifs_sb_info *cifs_sb)
|
||||
{
|
||||
int len;
|
||||
const char *start_of_path;
|
||||
__le16 *to;
|
||||
|
||||
/* Windows doesn't allow paths beginning with \ */
|
||||
if (from[0] == '\\')
|
||||
start_of_path = from + 1;
|
||||
else
|
||||
start_of_path = from;
|
||||
to = cifs_strndup_to_utf16(start_of_path, PATH_MAX, &len,
|
||||
cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
return to;
|
||||
}
|
@ -18,10 +18,314 @@
|
||||
*/
|
||||
|
||||
#include "cifsglob.h"
|
||||
#include "smb2pdu.h"
|
||||
#include "smb2proto.h"
|
||||
#include "cifsproto.h"
|
||||
#include "cifs_debug.h"
|
||||
|
||||
static int
|
||||
change_conf(struct TCP_Server_Info *server)
|
||||
{
|
||||
server->credits += server->echo_credits + server->oplock_credits;
|
||||
server->oplock_credits = server->echo_credits = 0;
|
||||
switch (server->credits) {
|
||||
case 0:
|
||||
return -1;
|
||||
case 1:
|
||||
server->echoes = false;
|
||||
server->oplocks = false;
|
||||
cERROR(1, "disabling echoes and oplocks");
|
||||
break;
|
||||
case 2:
|
||||
server->echoes = true;
|
||||
server->oplocks = false;
|
||||
server->echo_credits = 1;
|
||||
cFYI(1, "disabling oplocks");
|
||||
break;
|
||||
default:
|
||||
server->echoes = true;
|
||||
server->oplocks = true;
|
||||
server->echo_credits = 1;
|
||||
server->oplock_credits = 1;
|
||||
}
|
||||
server->credits -= server->echo_credits + server->oplock_credits;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
smb2_add_credits(struct TCP_Server_Info *server, const unsigned int add,
|
||||
const int optype)
|
||||
{
|
||||
int *val, rc = 0;
|
||||
spin_lock(&server->req_lock);
|
||||
val = server->ops->get_credits_field(server, optype);
|
||||
*val += add;
|
||||
server->in_flight--;
|
||||
if (server->in_flight == 0 && (optype & CIFS_OP_MASK) != CIFS_NEG_OP)
|
||||
rc = change_conf(server);
|
||||
spin_unlock(&server->req_lock);
|
||||
wake_up(&server->request_q);
|
||||
if (rc)
|
||||
cifs_reconnect(server);
|
||||
}
|
||||
|
||||
static void
|
||||
smb2_set_credits(struct TCP_Server_Info *server, const int val)
|
||||
{
|
||||
spin_lock(&server->req_lock);
|
||||
server->credits = val;
|
||||
spin_unlock(&server->req_lock);
|
||||
}
|
||||
|
||||
static int *
|
||||
smb2_get_credits_field(struct TCP_Server_Info *server, const int optype)
|
||||
{
|
||||
switch (optype) {
|
||||
case CIFS_ECHO_OP:
|
||||
return &server->echo_credits;
|
||||
case CIFS_OBREAK_OP:
|
||||
return &server->oplock_credits;
|
||||
default:
|
||||
return &server->credits;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
smb2_get_credits(struct mid_q_entry *mid)
|
||||
{
|
||||
return le16_to_cpu(((struct smb2_hdr *)mid->resp_buf)->CreditRequest);
|
||||
}
|
||||
|
||||
static __u64
|
||||
smb2_get_next_mid(struct TCP_Server_Info *server)
|
||||
{
|
||||
__u64 mid;
|
||||
/* for SMB2 we need the current value */
|
||||
spin_lock(&GlobalMid_Lock);
|
||||
mid = server->CurrentMid++;
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
return mid;
|
||||
}
|
||||
|
||||
static struct mid_q_entry *
|
||||
smb2_find_mid(struct TCP_Server_Info *server, char *buf)
|
||||
{
|
||||
struct mid_q_entry *mid;
|
||||
struct smb2_hdr *hdr = (struct smb2_hdr *)buf;
|
||||
|
||||
spin_lock(&GlobalMid_Lock);
|
||||
list_for_each_entry(mid, &server->pending_mid_q, qhead) {
|
||||
if ((mid->mid == hdr->MessageId) &&
|
||||
(mid->mid_state == MID_REQUEST_SUBMITTED) &&
|
||||
(mid->command == hdr->Command)) {
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
return mid;
|
||||
}
|
||||
}
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
smb2_dump_detail(void *buf)
|
||||
{
|
||||
#ifdef CONFIG_CIFS_DEBUG2
|
||||
struct smb2_hdr *smb = (struct smb2_hdr *)buf;
|
||||
|
||||
cERROR(1, "Cmd: %d Err: 0x%x Flags: 0x%x Mid: %llu Pid: %d",
|
||||
smb->Command, smb->Status, smb->Flags, smb->MessageId,
|
||||
smb->ProcessId);
|
||||
cERROR(1, "smb buf %p len %u", smb, smb2_calc_size(smb));
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool
|
||||
smb2_need_neg(struct TCP_Server_Info *server)
|
||||
{
|
||||
return server->max_read == 0;
|
||||
}
|
||||
|
||||
static int
|
||||
smb2_negotiate(const unsigned int xid, struct cifs_ses *ses)
|
||||
{
|
||||
int rc;
|
||||
ses->server->CurrentMid = 0;
|
||||
rc = SMB2_negotiate(xid, ses);
|
||||
/* BB we probably don't need to retry with modern servers */
|
||||
if (rc == -EAGAIN)
|
||||
rc = -EHOSTDOWN;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
struct cifs_sb_info *cifs_sb, const char *full_path)
|
||||
{
|
||||
int rc;
|
||||
__u64 persistent_fid, volatile_fid;
|
||||
__le16 *utf16_path;
|
||||
|
||||
utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
|
||||
if (!utf16_path)
|
||||
return -ENOMEM;
|
||||
|
||||
rc = SMB2_open(xid, tcon, utf16_path, &persistent_fid, &volatile_fid,
|
||||
FILE_READ_ATTRIBUTES, FILE_OPEN, 0, 0);
|
||||
if (rc) {
|
||||
kfree(utf16_path);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = SMB2_close(xid, tcon, persistent_fid, volatile_fid);
|
||||
kfree(utf16_path);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
smb2_get_srv_inum(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
struct cifs_sb_info *cifs_sb, const char *full_path,
|
||||
u64 *uniqueid, FILE_ALL_INFO *data)
|
||||
{
|
||||
*uniqueid = le64_to_cpu(data->IndexNumber);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *
|
||||
smb2_build_path_to_root(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
|
||||
struct cifs_tcon *tcon)
|
||||
{
|
||||
int pplen = vol->prepath ? strlen(vol->prepath) : 0;
|
||||
char *full_path = NULL;
|
||||
|
||||
/* if no prefix path, simply set path to the root of share to "" */
|
||||
if (pplen == 0) {
|
||||
full_path = kzalloc(2, GFP_KERNEL);
|
||||
return full_path;
|
||||
}
|
||||
|
||||
cERROR(1, "prefixpath is not supported for SMB2 now");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool
|
||||
smb2_can_echo(struct TCP_Server_Info *server)
|
||||
{
|
||||
return server->echoes;
|
||||
}
|
||||
|
||||
static void
|
||||
smb2_clear_stats(struct cifs_tcon *tcon)
|
||||
{
|
||||
#ifdef CONFIG_CIFS_STATS
|
||||
int i;
|
||||
for (i = 0; i < NUMBER_OF_SMB2_COMMANDS; i++) {
|
||||
atomic_set(&tcon->stats.smb2_stats.smb2_com_sent[i], 0);
|
||||
atomic_set(&tcon->stats.smb2_stats.smb2_com_failed[i], 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
smb2_print_stats(struct seq_file *m, struct cifs_tcon *tcon)
|
||||
{
|
||||
#ifdef CONFIG_CIFS_STATS
|
||||
atomic_t *sent = tcon->stats.smb2_stats.smb2_com_sent;
|
||||
atomic_t *failed = tcon->stats.smb2_stats.smb2_com_failed;
|
||||
seq_printf(m, "\nNegotiates: %d sent %d failed",
|
||||
atomic_read(&sent[SMB2_NEGOTIATE_HE]),
|
||||
atomic_read(&failed[SMB2_NEGOTIATE_HE]));
|
||||
seq_printf(m, "\nSessionSetups: %d sent %d failed",
|
||||
atomic_read(&sent[SMB2_SESSION_SETUP_HE]),
|
||||
atomic_read(&failed[SMB2_SESSION_SETUP_HE]));
|
||||
#define SMB2LOGOFF 0x0002 /* trivial request/resp */
|
||||
seq_printf(m, "\nLogoffs: %d sent %d failed",
|
||||
atomic_read(&sent[SMB2_LOGOFF_HE]),
|
||||
atomic_read(&failed[SMB2_LOGOFF_HE]));
|
||||
seq_printf(m, "\nTreeConnects: %d sent %d failed",
|
||||
atomic_read(&sent[SMB2_TREE_CONNECT_HE]),
|
||||
atomic_read(&failed[SMB2_TREE_CONNECT_HE]));
|
||||
seq_printf(m, "\nTreeDisconnects: %d sent %d failed",
|
||||
atomic_read(&sent[SMB2_TREE_DISCONNECT_HE]),
|
||||
atomic_read(&failed[SMB2_TREE_DISCONNECT_HE]));
|
||||
seq_printf(m, "\nCreates: %d sent %d failed",
|
||||
atomic_read(&sent[SMB2_CREATE_HE]),
|
||||
atomic_read(&failed[SMB2_CREATE_HE]));
|
||||
seq_printf(m, "\nCloses: %d sent %d failed",
|
||||
atomic_read(&sent[SMB2_CLOSE_HE]),
|
||||
atomic_read(&failed[SMB2_CLOSE_HE]));
|
||||
seq_printf(m, "\nFlushes: %d sent %d failed",
|
||||
atomic_read(&sent[SMB2_FLUSH_HE]),
|
||||
atomic_read(&failed[SMB2_FLUSH_HE]));
|
||||
seq_printf(m, "\nReads: %d sent %d failed",
|
||||
atomic_read(&sent[SMB2_READ_HE]),
|
||||
atomic_read(&failed[SMB2_READ_HE]));
|
||||
seq_printf(m, "\nWrites: %d sent %d failed",
|
||||
atomic_read(&sent[SMB2_WRITE_HE]),
|
||||
atomic_read(&failed[SMB2_WRITE_HE]));
|
||||
seq_printf(m, "\nLocks: %d sent %d failed",
|
||||
atomic_read(&sent[SMB2_LOCK_HE]),
|
||||
atomic_read(&failed[SMB2_LOCK_HE]));
|
||||
seq_printf(m, "\nIOCTLs: %d sent %d failed",
|
||||
atomic_read(&sent[SMB2_IOCTL_HE]),
|
||||
atomic_read(&failed[SMB2_IOCTL_HE]));
|
||||
seq_printf(m, "\nCancels: %d sent %d failed",
|
||||
atomic_read(&sent[SMB2_CANCEL_HE]),
|
||||
atomic_read(&failed[SMB2_CANCEL_HE]));
|
||||
seq_printf(m, "\nEchos: %d sent %d failed",
|
||||
atomic_read(&sent[SMB2_ECHO_HE]),
|
||||
atomic_read(&failed[SMB2_ECHO_HE]));
|
||||
seq_printf(m, "\nQueryDirectories: %d sent %d failed",
|
||||
atomic_read(&sent[SMB2_QUERY_DIRECTORY_HE]),
|
||||
atomic_read(&failed[SMB2_QUERY_DIRECTORY_HE]));
|
||||
seq_printf(m, "\nChangeNotifies: %d sent %d failed",
|
||||
atomic_read(&sent[SMB2_CHANGE_NOTIFY_HE]),
|
||||
atomic_read(&failed[SMB2_CHANGE_NOTIFY_HE]));
|
||||
seq_printf(m, "\nQueryInfos: %d sent %d failed",
|
||||
atomic_read(&sent[SMB2_QUERY_INFO_HE]),
|
||||
atomic_read(&failed[SMB2_QUERY_INFO_HE]));
|
||||
seq_printf(m, "\nSetInfos: %d sent %d failed",
|
||||
atomic_read(&sent[SMB2_SET_INFO_HE]),
|
||||
atomic_read(&failed[SMB2_SET_INFO_HE]));
|
||||
seq_printf(m, "\nOplockBreaks: %d sent %d failed",
|
||||
atomic_read(&sent[SMB2_OPLOCK_BREAK_HE]),
|
||||
atomic_read(&failed[SMB2_OPLOCK_BREAK_HE]));
|
||||
#endif
|
||||
}
|
||||
|
||||
struct smb_version_operations smb21_operations = {
|
||||
.setup_request = smb2_setup_request,
|
||||
.setup_async_request = smb2_setup_async_request,
|
||||
.check_receive = smb2_check_receive,
|
||||
.add_credits = smb2_add_credits,
|
||||
.set_credits = smb2_set_credits,
|
||||
.get_credits_field = smb2_get_credits_field,
|
||||
.get_credits = smb2_get_credits,
|
||||
.get_next_mid = smb2_get_next_mid,
|
||||
.find_mid = smb2_find_mid,
|
||||
.check_message = smb2_check_message,
|
||||
.dump_detail = smb2_dump_detail,
|
||||
.clear_stats = smb2_clear_stats,
|
||||
.print_stats = smb2_print_stats,
|
||||
.need_neg = smb2_need_neg,
|
||||
.negotiate = smb2_negotiate,
|
||||
.sess_setup = SMB2_sess_setup,
|
||||
.logoff = SMB2_logoff,
|
||||
.tree_connect = SMB2_tcon,
|
||||
.tree_disconnect = SMB2_tdis,
|
||||
.is_path_accessible = smb2_is_path_accessible,
|
||||
.can_echo = smb2_can_echo,
|
||||
.echo = SMB2_echo,
|
||||
.query_path_info = smb2_query_path_info,
|
||||
.get_srv_inum = smb2_get_srv_inum,
|
||||
.build_path_to_root = smb2_build_path_to_root,
|
||||
};
|
||||
|
||||
struct smb_version_values smb21_values = {
|
||||
.version_string = SMB21_VERSION_STRING,
|
||||
.header_size = sizeof(struct smb2_hdr),
|
||||
.max_header_size = MAX_SMB2_HDR_SIZE,
|
||||
.lock_cmd = SMB2_LOCK,
|
||||
.cap_unix = 0,
|
||||
.cap_nt_find = SMB2_NT_FIND,
|
||||
.cap_large_files = SMB2_LARGE_FILES,
|
||||
};
|
||||
|
1125
fs/cifs/smb2pdu.c
Normal file
1125
fs/cifs/smb2pdu.c
Normal file
File diff suppressed because it is too large
Load Diff
577
fs/cifs/smb2pdu.h
Normal file
577
fs/cifs/smb2pdu.h
Normal file
@ -0,0 +1,577 @@
|
||||
/*
|
||||
* fs/cifs/smb2pdu.h
|
||||
*
|
||||
* Copyright (c) International Business Machines Corp., 2009, 2010
|
||||
* Etersoft, 2012
|
||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||
* Pavel Shilovsky (pshilovsky@samba.org) 2012
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
|
||||
* the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _SMB2PDU_H
|
||||
#define _SMB2PDU_H
|
||||
|
||||
#include <net/sock.h>
|
||||
|
||||
/*
|
||||
* Note that, due to trying to use names similar to the protocol specifications,
|
||||
* there are many mixed case field names in the structures below. Although
|
||||
* this does not match typical Linux kernel style, it is necessary to be
|
||||
* be able to match against the protocol specfication.
|
||||
*
|
||||
* SMB2 commands
|
||||
* Some commands have minimal (wct=0,bcc=0), or uninteresting, responses
|
||||
* (ie no useful data other than the SMB error code itself) and are marked such.
|
||||
* Knowing this helps avoid response buffer allocations and copy in some cases.
|
||||
*/
|
||||
|
||||
/* List of commands in host endian */
|
||||
#define SMB2_NEGOTIATE_HE 0x0000
|
||||
#define SMB2_SESSION_SETUP_HE 0x0001
|
||||
#define SMB2_LOGOFF_HE 0x0002 /* trivial request/resp */
|
||||
#define SMB2_TREE_CONNECT_HE 0x0003
|
||||
#define SMB2_TREE_DISCONNECT_HE 0x0004 /* trivial req/resp */
|
||||
#define SMB2_CREATE_HE 0x0005
|
||||
#define SMB2_CLOSE_HE 0x0006
|
||||
#define SMB2_FLUSH_HE 0x0007 /* trivial resp */
|
||||
#define SMB2_READ_HE 0x0008
|
||||
#define SMB2_WRITE_HE 0x0009
|
||||
#define SMB2_LOCK_HE 0x000A
|
||||
#define SMB2_IOCTL_HE 0x000B
|
||||
#define SMB2_CANCEL_HE 0x000C
|
||||
#define SMB2_ECHO_HE 0x000D
|
||||
#define SMB2_QUERY_DIRECTORY_HE 0x000E
|
||||
#define SMB2_CHANGE_NOTIFY_HE 0x000F
|
||||
#define SMB2_QUERY_INFO_HE 0x0010
|
||||
#define SMB2_SET_INFO_HE 0x0011
|
||||
#define SMB2_OPLOCK_BREAK_HE 0x0012
|
||||
|
||||
/* The same list in little endian */
|
||||
#define SMB2_NEGOTIATE cpu_to_le16(SMB2_NEGOTIATE_HE)
|
||||
#define SMB2_SESSION_SETUP cpu_to_le16(SMB2_SESSION_SETUP_HE)
|
||||
#define SMB2_LOGOFF cpu_to_le16(SMB2_LOGOFF_HE)
|
||||
#define SMB2_TREE_CONNECT cpu_to_le16(SMB2_TREE_CONNECT_HE)
|
||||
#define SMB2_TREE_DISCONNECT cpu_to_le16(SMB2_TREE_DISCONNECT_HE)
|
||||
#define SMB2_CREATE cpu_to_le16(SMB2_CREATE_HE)
|
||||
#define SMB2_CLOSE cpu_to_le16(SMB2_CLOSE_HE)
|
||||
#define SMB2_FLUSH cpu_to_le16(SMB2_FLUSH_HE)
|
||||
#define SMB2_READ cpu_to_le16(SMB2_READ_HE)
|
||||
#define SMB2_WRITE cpu_to_le16(SMB2_WRITE_HE)
|
||||
#define SMB2_LOCK cpu_to_le16(SMB2_LOCK_HE)
|
||||
#define SMB2_IOCTL cpu_to_le16(SMB2_IOCTL_HE)
|
||||
#define SMB2_CANCEL cpu_to_le16(SMB2_CANCEL_HE)
|
||||
#define SMB2_ECHO cpu_to_le16(SMB2_ECHO_HE)
|
||||
#define SMB2_QUERY_DIRECTORY cpu_to_le16(SMB2_QUERY_DIRECTORY_HE)
|
||||
#define SMB2_CHANGE_NOTIFY cpu_to_le16(SMB2_CHANGE_NOTIFY_HE)
|
||||
#define SMB2_QUERY_INFO cpu_to_le16(SMB2_QUERY_INFO_HE)
|
||||
#define SMB2_SET_INFO cpu_to_le16(SMB2_SET_INFO_HE)
|
||||
#define SMB2_OPLOCK_BREAK cpu_to_le16(SMB2_OPLOCK_BREAK_HE)
|
||||
|
||||
#define NUMBER_OF_SMB2_COMMANDS 0x0013
|
||||
|
||||
/* BB FIXME - analyze following length BB */
|
||||
#define MAX_SMB2_HDR_SIZE 0x78 /* 4 len + 64 hdr + (2*24 wct) + 2 bct + 2 pad */
|
||||
|
||||
#define SMB2_PROTO_NUMBER __constant_cpu_to_le32(0x424d53fe)
|
||||
|
||||
#define SMB2_HEADER_SIZE __constant_le16_to_cpu(64)
|
||||
|
||||
#define SMB2_ERROR_STRUCTURE_SIZE2 __constant_le16_to_cpu(9)
|
||||
|
||||
/*
|
||||
* SMB2 Header Definition
|
||||
*
|
||||
* "MBZ" : Must be Zero
|
||||
* "BB" : BugBug, Something to check/review/analyze later
|
||||
* "PDU" : "Protocol Data Unit" (ie a network "frame")
|
||||
*
|
||||
*/
|
||||
struct smb2_hdr {
|
||||
__be32 smb2_buf_length; /* big endian on wire */
|
||||
/* length is only two or three bytes - with
|
||||
one or two byte type preceding it that MBZ */
|
||||
__u8 ProtocolId[4]; /* 0xFE 'S' 'M' 'B' */
|
||||
__le16 StructureSize; /* 64 */
|
||||
__le16 CreditCharge; /* MBZ */
|
||||
__le32 Status; /* Error from server */
|
||||
__le16 Command;
|
||||
__le16 CreditRequest; /* CreditResponse */
|
||||
__le32 Flags;
|
||||
__le32 NextCommand;
|
||||
__u64 MessageId; /* opaque - so can stay little endian */
|
||||
__le32 ProcessId;
|
||||
__u32 TreeId; /* opaque - so do not make little endian */
|
||||
__u64 SessionId; /* opaque - so do not make little endian */
|
||||
__u8 Signature[16];
|
||||
} __packed;
|
||||
|
||||
struct smb2_pdu {
|
||||
struct smb2_hdr hdr;
|
||||
__le16 StructureSize2; /* size of wct area (varies, request specific) */
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* SMB2 flag definitions
|
||||
*/
|
||||
#define SMB2_FLAGS_SERVER_TO_REDIR __constant_cpu_to_le32(0x00000001)
|
||||
#define SMB2_FLAGS_ASYNC_COMMAND __constant_cpu_to_le32(0x00000002)
|
||||
#define SMB2_FLAGS_RELATED_OPERATIONS __constant_cpu_to_le32(0x00000004)
|
||||
#define SMB2_FLAGS_SIGNED __constant_cpu_to_le32(0x00000008)
|
||||
#define SMB2_FLAGS_DFS_OPERATIONS __constant_cpu_to_le32(0x10000000)
|
||||
|
||||
/*
|
||||
* Definitions for SMB2 Protocol Data Units (network frames)
|
||||
*
|
||||
* See MS-SMB2.PDF specification for protocol details.
|
||||
* The Naming convention is the lower case version of the SMB2
|
||||
* command code name for the struct. Note that structures must be packed.
|
||||
*
|
||||
*/
|
||||
struct smb2_err_rsp {
|
||||
struct smb2_hdr hdr;
|
||||
__le16 StructureSize;
|
||||
__le16 Reserved; /* MBZ */
|
||||
__le32 ByteCount; /* even if zero, at least one byte follows */
|
||||
__u8 ErrorData[1]; /* variable length */
|
||||
} __packed;
|
||||
|
||||
struct smb2_negotiate_req {
|
||||
struct smb2_hdr hdr;
|
||||
__le16 StructureSize; /* Must be 36 */
|
||||
__le16 DialectCount;
|
||||
__le16 SecurityMode;
|
||||
__le16 Reserved; /* MBZ */
|
||||
__le32 Capabilities;
|
||||
__u8 ClientGUID[16]; /* MBZ */
|
||||
__le64 ClientStartTime; /* MBZ */
|
||||
__le16 Dialects[2]; /* variable length */
|
||||
} __packed;
|
||||
|
||||
/* SecurityMode flags */
|
||||
#define SMB2_NEGOTIATE_SIGNING_ENABLED 0x0001
|
||||
#define SMB2_NEGOTIATE_SIGNING_REQUIRED 0x0002
|
||||
/* Capabilities flags */
|
||||
#define SMB2_GLOBAL_CAP_DFS 0x00000001
|
||||
#define SMB2_GLOBAL_CAP_LEASING 0x00000002 /* Resp only New to SMB2.1 */
|
||||
#define SMB2_GLOBAL_CAP_LARGE_MTU 0X00000004 /* Resp only New to SMB2.1 */
|
||||
/* Internal types */
|
||||
#define SMB2_NT_FIND 0x00100000
|
||||
#define SMB2_LARGE_FILES 0x00200000
|
||||
|
||||
struct smb2_negotiate_rsp {
|
||||
struct smb2_hdr hdr;
|
||||
__le16 StructureSize; /* Must be 65 */
|
||||
__le16 SecurityMode;
|
||||
__le16 DialectRevision;
|
||||
__le16 Reserved; /* MBZ */
|
||||
__u8 ServerGUID[16];
|
||||
__le32 Capabilities;
|
||||
__le32 MaxTransactSize;
|
||||
__le32 MaxReadSize;
|
||||
__le32 MaxWriteSize;
|
||||
__le64 SystemTime; /* MBZ */
|
||||
__le64 ServerStartTime;
|
||||
__le16 SecurityBufferOffset;
|
||||
__le16 SecurityBufferLength;
|
||||
__le32 Reserved2; /* may be any value, ignore */
|
||||
__u8 Buffer[1]; /* variable length GSS security buffer */
|
||||
} __packed;
|
||||
|
||||
struct smb2_sess_setup_req {
|
||||
struct smb2_hdr hdr;
|
||||
__le16 StructureSize; /* Must be 25 */
|
||||
__u8 VcNumber;
|
||||
__u8 SecurityMode;
|
||||
__le32 Capabilities;
|
||||
__le32 Channel;
|
||||
__le16 SecurityBufferOffset;
|
||||
__le16 SecurityBufferLength;
|
||||
__le64 PreviousSessionId;
|
||||
__u8 Buffer[1]; /* variable length GSS security buffer */
|
||||
} __packed;
|
||||
|
||||
/* Currently defined SessionFlags */
|
||||
#define SMB2_SESSION_FLAG_IS_GUEST 0x0001
|
||||
#define SMB2_SESSION_FLAG_IS_NULL 0x0002
|
||||
struct smb2_sess_setup_rsp {
|
||||
struct smb2_hdr hdr;
|
||||
__le16 StructureSize; /* Must be 9 */
|
||||
__le16 SessionFlags;
|
||||
__le16 SecurityBufferOffset;
|
||||
__le16 SecurityBufferLength;
|
||||
__u8 Buffer[1]; /* variable length GSS security buffer */
|
||||
} __packed;
|
||||
|
||||
struct smb2_logoff_req {
|
||||
struct smb2_hdr hdr;
|
||||
__le16 StructureSize; /* Must be 4 */
|
||||
__le16 Reserved;
|
||||
} __packed;
|
||||
|
||||
struct smb2_logoff_rsp {
|
||||
struct smb2_hdr hdr;
|
||||
__le16 StructureSize; /* Must be 4 */
|
||||
__le16 Reserved;
|
||||
} __packed;
|
||||
|
||||
struct smb2_tree_connect_req {
|
||||
struct smb2_hdr hdr;
|
||||
__le16 StructureSize; /* Must be 9 */
|
||||
__le16 Reserved;
|
||||
__le16 PathOffset;
|
||||
__le16 PathLength;
|
||||
__u8 Buffer[1]; /* variable length */
|
||||
} __packed;
|
||||
|
||||
struct smb2_tree_connect_rsp {
|
||||
struct smb2_hdr hdr;
|
||||
__le16 StructureSize; /* Must be 16 */
|
||||
__u8 ShareType; /* see below */
|
||||
__u8 Reserved;
|
||||
__le32 ShareFlags; /* see below */
|
||||
__le32 Capabilities; /* see below */
|
||||
__le32 MaximalAccess;
|
||||
} __packed;
|
||||
|
||||
/* Possible ShareType values */
|
||||
#define SMB2_SHARE_TYPE_DISK 0x01
|
||||
#define SMB2_SHARE_TYPE_PIPE 0x02
|
||||
#define SMB2_SHARE_TYPE_PRINT 0x03
|
||||
|
||||
/*
|
||||
* Possible ShareFlags - exactly one and only one of the first 4 caching flags
|
||||
* must be set (any of the remaining, SHI1005, flags may be set individually
|
||||
* or in combination.
|
||||
*/
|
||||
#define SMB2_SHAREFLAG_MANUAL_CACHING 0x00000000
|
||||
#define SMB2_SHAREFLAG_AUTO_CACHING 0x00000010
|
||||
#define SMB2_SHAREFLAG_VDO_CACHING 0x00000020
|
||||
#define SMB2_SHAREFLAG_NO_CACHING 0x00000030
|
||||
#define SHI1005_FLAGS_DFS 0x00000001
|
||||
#define SHI1005_FLAGS_DFS_ROOT 0x00000002
|
||||
#define SHI1005_FLAGS_RESTRICT_EXCLUSIVE_OPENS 0x00000100
|
||||
#define SHI1005_FLAGS_FORCE_SHARED_DELETE 0x00000200
|
||||
#define SHI1005_FLAGS_ALLOW_NAMESPACE_CACHING 0x00000400
|
||||
#define SHI1005_FLAGS_ACCESS_BASED_DIRECTORY_ENUM 0x00000800
|
||||
#define SHI1005_FLAGS_FORCE_LEVELII_OPLOCK 0x00001000
|
||||
#define SHI1005_FLAGS_ENABLE_HASH 0x00002000
|
||||
|
||||
/* Possible share capabilities */
|
||||
#define SMB2_SHARE_CAP_DFS cpu_to_le32(0x00000008)
|
||||
|
||||
struct smb2_tree_disconnect_req {
|
||||
struct smb2_hdr hdr;
|
||||
__le16 StructureSize; /* Must be 4 */
|
||||
__le16 Reserved;
|
||||
} __packed;
|
||||
|
||||
struct smb2_tree_disconnect_rsp {
|
||||
struct smb2_hdr hdr;
|
||||
__le16 StructureSize; /* Must be 4 */
|
||||
__le16 Reserved;
|
||||
} __packed;
|
||||
|
||||
/* File Attrubutes */
|
||||
#define FILE_ATTRIBUTE_READONLY 0x00000001
|
||||
#define FILE_ATTRIBUTE_HIDDEN 0x00000002
|
||||
#define FILE_ATTRIBUTE_SYSTEM 0x00000004
|
||||
#define FILE_ATTRIBUTE_DIRECTORY 0x00000010
|
||||
#define FILE_ATTRIBUTE_ARCHIVE 0x00000020
|
||||
#define FILE_ATTRIBUTE_NORMAL 0x00000080
|
||||
#define FILE_ATTRIBUTE_TEMPORARY 0x00000100
|
||||
#define FILE_ATTRIBUTE_SPARSE_FILE 0x00000200
|
||||
#define FILE_ATTRIBUTE_REPARSE_POINT 0x00000400
|
||||
#define FILE_ATTRIBUTE_COMPRESSED 0x00000800
|
||||
#define FILE_ATTRIBUTE_OFFLINE 0x00001000
|
||||
#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x00002000
|
||||
#define FILE_ATTRIBUTE_ENCRYPTED 0x00004000
|
||||
|
||||
/* Oplock levels */
|
||||
#define SMB2_OPLOCK_LEVEL_NONE 0x00
|
||||
#define SMB2_OPLOCK_LEVEL_II 0x01
|
||||
#define SMB2_OPLOCK_LEVEL_EXCLUSIVE 0x08
|
||||
#define SMB2_OPLOCK_LEVEL_BATCH 0x09
|
||||
#define SMB2_OPLOCK_LEVEL_LEASE 0xFF
|
||||
|
||||
/* Desired Access Flags */
|
||||
#define FILE_READ_DATA_LE cpu_to_le32(0x00000001)
|
||||
#define FILE_WRITE_DATA_LE cpu_to_le32(0x00000002)
|
||||
#define FILE_APPEND_DATA_LE cpu_to_le32(0x00000004)
|
||||
#define FILE_READ_EA_LE cpu_to_le32(0x00000008)
|
||||
#define FILE_WRITE_EA_LE cpu_to_le32(0x00000010)
|
||||
#define FILE_EXECUTE_LE cpu_to_le32(0x00000020)
|
||||
#define FILE_READ_ATTRIBUTES_LE cpu_to_le32(0x00000080)
|
||||
#define FILE_WRITE_ATTRIBUTES_LE cpu_to_le32(0x00000100)
|
||||
#define FILE_DELETE_LE cpu_to_le32(0x00010000)
|
||||
#define FILE_READ_CONTROL_LE cpu_to_le32(0x00020000)
|
||||
#define FILE_WRITE_DAC_LE cpu_to_le32(0x00040000)
|
||||
#define FILE_WRITE_OWNER_LE cpu_to_le32(0x00080000)
|
||||
#define FILE_SYNCHRONIZE_LE cpu_to_le32(0x00100000)
|
||||
#define FILE_ACCESS_SYSTEM_SECURITY_LE cpu_to_le32(0x01000000)
|
||||
#define FILE_MAXIMAL_ACCESS_LE cpu_to_le32(0x02000000)
|
||||
#define FILE_GENERIC_ALL_LE cpu_to_le32(0x10000000)
|
||||
#define FILE_GENERIC_EXECUTE_LE cpu_to_le32(0x20000000)
|
||||
#define FILE_GENERIC_WRITE_LE cpu_to_le32(0x40000000)
|
||||
#define FILE_GENERIC_READ_LE cpu_to_le32(0x80000000)
|
||||
|
||||
/* ShareAccess Flags */
|
||||
#define FILE_SHARE_READ_LE cpu_to_le32(0x00000001)
|
||||
#define FILE_SHARE_WRITE_LE cpu_to_le32(0x00000002)
|
||||
#define FILE_SHARE_DELETE_LE cpu_to_le32(0x00000004)
|
||||
#define FILE_SHARE_ALL_LE cpu_to_le32(0x00000007)
|
||||
|
||||
/* CreateDisposition Flags */
|
||||
#define FILE_SUPERSEDE_LE cpu_to_le32(0x00000000)
|
||||
#define FILE_OPEN_LE cpu_to_le32(0x00000001)
|
||||
#define FILE_CREATE_LE cpu_to_le32(0x00000002)
|
||||
#define FILE_OPEN_IF_LE cpu_to_le32(0x00000003)
|
||||
#define FILE_OVERWRITE_LE cpu_to_le32(0x00000004)
|
||||
#define FILE_OVERWRITE_IF_LE cpu_to_le32(0x00000005)
|
||||
|
||||
/* CreateOptions Flags */
|
||||
#define FILE_DIRECTORY_FILE_LE cpu_to_le32(0x00000001)
|
||||
/* same as #define CREATE_NOT_FILE_LE cpu_to_le32(0x00000001) */
|
||||
#define FILE_WRITE_THROUGH_LE cpu_to_le32(0x00000002)
|
||||
#define FILE_SEQUENTIAL_ONLY_LE cpu_to_le32(0x00000004)
|
||||
#define FILE_NO_INTERMEDIATE_BUFFERRING_LE cpu_to_le32(0x00000008)
|
||||
#define FILE_SYNCHRONOUS_IO_ALERT_LE cpu_to_le32(0x00000010)
|
||||
#define FILE_SYNCHRONOUS_IO_NON_ALERT_LE cpu_to_le32(0x00000020)
|
||||
#define FILE_NON_DIRECTORY_FILE_LE cpu_to_le32(0x00000040)
|
||||
#define FILE_COMPLETE_IF_OPLOCKED_LE cpu_to_le32(0x00000100)
|
||||
#define FILE_NO_EA_KNOWLEDGE_LE cpu_to_le32(0x00000200)
|
||||
#define FILE_RANDOM_ACCESS_LE cpu_to_le32(0x00000800)
|
||||
#define FILE_DELETE_ON_CLOSE_LE cpu_to_le32(0x00001000)
|
||||
#define FILE_OPEN_BY_FILE_ID_LE cpu_to_le32(0x00002000)
|
||||
#define FILE_OPEN_FOR_BACKUP_INTENT_LE cpu_to_le32(0x00004000)
|
||||
#define FILE_NO_COMPRESSION_LE cpu_to_le32(0x00008000)
|
||||
#define FILE_RESERVE_OPFILTER_LE cpu_to_le32(0x00100000)
|
||||
#define FILE_OPEN_REPARSE_POINT_LE cpu_to_le32(0x00200000)
|
||||
#define FILE_OPEN_NO_RECALL_LE cpu_to_le32(0x00400000)
|
||||
#define FILE_OPEN_FOR_FREE_SPACE_QUERY_LE cpu_to_le32(0x00800000)
|
||||
|
||||
#define FILE_READ_RIGHTS_LE (FILE_READ_DATA_LE | FILE_READ_EA_LE \
|
||||
| FILE_READ_ATTRIBUTES_LE)
|
||||
#define FILE_WRITE_RIGHTS_LE (FILE_WRITE_DATA_LE | FILE_APPEND_DATA_LE \
|
||||
| FILE_WRITE_EA_LE | FILE_WRITE_ATTRIBUTES_LE)
|
||||
#define FILE_EXEC_RIGHTS_LE (FILE_EXECUTE_LE)
|
||||
|
||||
/* Impersonation Levels */
|
||||
#define IL_ANONYMOUS cpu_to_le32(0x00000000)
|
||||
#define IL_IDENTIFICATION cpu_to_le32(0x00000001)
|
||||
#define IL_IMPERSONATION cpu_to_le32(0x00000002)
|
||||
#define IL_DELEGATE cpu_to_le32(0x00000003)
|
||||
|
||||
/* Create Context Values */
|
||||
#define SMB2_CREATE_EA_BUFFER "ExtA" /* extended attributes */
|
||||
#define SMB2_CREATE_SD_BUFFER "SecD" /* security descriptor */
|
||||
#define SMB2_CREATE_DURABLE_HANDLE_REQUEST "DHnQ"
|
||||
#define SMB2_CREATE_DURABLE_HANDLE_RECONNECT "DHnC"
|
||||
#define SMB2_CREATE_ALLOCATION_SIZE "AlSi"
|
||||
#define SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST "MxAc"
|
||||
#define SMB2_CREATE_TIMEWARP_REQUEST "TWrp"
|
||||
#define SMB2_CREATE_QUERY_ON_DISK_ID "QFid"
|
||||
#define SMB2_CREATE_REQUEST_LEASE "RqLs"
|
||||
|
||||
struct smb2_create_req {
|
||||
struct smb2_hdr hdr;
|
||||
__le16 StructureSize; /* Must be 57 */
|
||||
__u8 SecurityFlags;
|
||||
__u8 RequestedOplockLevel;
|
||||
__le32 ImpersonationLevel;
|
||||
__le64 SmbCreateFlags;
|
||||
__le64 Reserved;
|
||||
__le32 DesiredAccess;
|
||||
__le32 FileAttributes;
|
||||
__le32 ShareAccess;
|
||||
__le32 CreateDisposition;
|
||||
__le32 CreateOptions;
|
||||
__le16 NameOffset;
|
||||
__le16 NameLength;
|
||||
__le32 CreateContextsOffset;
|
||||
__le32 CreateContextsLength;
|
||||
__u8 Buffer[1];
|
||||
} __packed;
|
||||
|
||||
struct smb2_create_rsp {
|
||||
struct smb2_hdr hdr;
|
||||
__le16 StructureSize; /* Must be 89 */
|
||||
__u8 OplockLevel;
|
||||
__u8 Reserved;
|
||||
__le32 CreateAction;
|
||||
__le64 CreationTime;
|
||||
__le64 LastAccessTime;
|
||||
__le64 LastWriteTime;
|
||||
__le64 ChangeTime;
|
||||
__le64 AllocationSize;
|
||||
__le64 EndofFile;
|
||||
__le32 FileAttributes;
|
||||
__le32 Reserved2;
|
||||
__u64 PersistentFileId; /* opaque endianness */
|
||||
__u64 VolatileFileId; /* opaque endianness */
|
||||
__le32 CreateContextsOffset;
|
||||
__le32 CreateContextsLength;
|
||||
__u8 Buffer[1];
|
||||
} __packed;
|
||||
|
||||
/* Currently defined values for close flags */
|
||||
#define SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB cpu_to_le16(0x0001)
|
||||
struct smb2_close_req {
|
||||
struct smb2_hdr hdr;
|
||||
__le16 StructureSize; /* Must be 24 */
|
||||
__le16 Flags;
|
||||
__le32 Reserved;
|
||||
__u64 PersistentFileId; /* opaque endianness */
|
||||
__u64 VolatileFileId; /* opaque endianness */
|
||||
} __packed;
|
||||
|
||||
struct smb2_close_rsp {
|
||||
struct smb2_hdr hdr;
|
||||
__le16 StructureSize; /* 60 */
|
||||
__le16 Flags;
|
||||
__le32 Reserved;
|
||||
__le64 CreationTime;
|
||||
__le64 LastAccessTime;
|
||||
__le64 LastWriteTime;
|
||||
__le64 ChangeTime;
|
||||
__le64 AllocationSize; /* Beginning of FILE_STANDARD_INFO equivalent */
|
||||
__le64 EndOfFile;
|
||||
__le32 Attributes;
|
||||
} __packed;
|
||||
|
||||
struct smb2_echo_req {
|
||||
struct smb2_hdr hdr;
|
||||
__le16 StructureSize; /* Must be 4 */
|
||||
__u16 Reserved;
|
||||
} __packed;
|
||||
|
||||
struct smb2_echo_rsp {
|
||||
struct smb2_hdr hdr;
|
||||
__le16 StructureSize; /* Must be 4 */
|
||||
__u16 Reserved;
|
||||
} __packed;
|
||||
|
||||
/* Possible InfoType values */
|
||||
#define SMB2_O_INFO_FILE 0x01
|
||||
#define SMB2_O_INFO_FILESYSTEM 0x02
|
||||
#define SMB2_O_INFO_SECURITY 0x03
|
||||
#define SMB2_O_INFO_QUOTA 0x04
|
||||
|
||||
struct smb2_query_info_req {
|
||||
struct smb2_hdr hdr;
|
||||
__le16 StructureSize; /* Must be 41 */
|
||||
__u8 InfoType;
|
||||
__u8 FileInfoClass;
|
||||
__le32 OutputBufferLength;
|
||||
__le16 InputBufferOffset;
|
||||
__u16 Reserved;
|
||||
__le32 InputBufferLength;
|
||||
__le32 AdditionalInformation;
|
||||
__le32 Flags;
|
||||
__u64 PersistentFileId; /* opaque endianness */
|
||||
__u64 VolatileFileId; /* opaque endianness */
|
||||
__u8 Buffer[1];
|
||||
} __packed;
|
||||
|
||||
struct smb2_query_info_rsp {
|
||||
struct smb2_hdr hdr;
|
||||
__le16 StructureSize; /* Must be 9 */
|
||||
__le16 OutputBufferOffset;
|
||||
__le32 OutputBufferLength;
|
||||
__u8 Buffer[1];
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* PDU infolevel structure definitions
|
||||
* BB consider moving to a different header
|
||||
*/
|
||||
|
||||
/* partial list of QUERY INFO levels */
|
||||
#define FILE_DIRECTORY_INFORMATION 1
|
||||
#define FILE_FULL_DIRECTORY_INFORMATION 2
|
||||
#define FILE_BOTH_DIRECTORY_INFORMATION 3
|
||||
#define FILE_BASIC_INFORMATION 4
|
||||
#define FILE_STANDARD_INFORMATION 5
|
||||
#define FILE_INTERNAL_INFORMATION 6
|
||||
#define FILE_EA_INFORMATION 7
|
||||
#define FILE_ACCESS_INFORMATION 8
|
||||
#define FILE_NAME_INFORMATION 9
|
||||
#define FILE_RENAME_INFORMATION 10
|
||||
#define FILE_LINK_INFORMATION 11
|
||||
#define FILE_NAMES_INFORMATION 12
|
||||
#define FILE_DISPOSITION_INFORMATION 13
|
||||
#define FILE_POSITION_INFORMATION 14
|
||||
#define FILE_FULL_EA_INFORMATION 15
|
||||
#define FILE_MODE_INFORMATION 16
|
||||
#define FILE_ALIGNMENT_INFORMATION 17
|
||||
#define FILE_ALL_INFORMATION 18
|
||||
#define FILE_ALLOCATION_INFORMATION 19
|
||||
#define FILE_END_OF_FILE_INFORMATION 20
|
||||
#define FILE_ALTERNATE_NAME_INFORMATION 21
|
||||
#define FILE_STREAM_INFORMATION 22
|
||||
#define FILE_PIPE_INFORMATION 23
|
||||
#define FILE_PIPE_LOCAL_INFORMATION 24
|
||||
#define FILE_PIPE_REMOTE_INFORMATION 25
|
||||
#define FILE_MAILSLOT_QUERY_INFORMATION 26
|
||||
#define FILE_MAILSLOT_SET_INFORMATION 27
|
||||
#define FILE_COMPRESSION_INFORMATION 28
|
||||
#define FILE_OBJECT_ID_INFORMATION 29
|
||||
/* Number 30 not defined in documents */
|
||||
#define FILE_MOVE_CLUSTER_INFORMATION 31
|
||||
#define FILE_QUOTA_INFORMATION 32
|
||||
#define FILE_REPARSE_POINT_INFORMATION 33
|
||||
#define FILE_NETWORK_OPEN_INFORMATION 34
|
||||
#define FILE_ATTRIBUTE_TAG_INFORMATION 35
|
||||
#define FILE_TRACKING_INFORMATION 36
|
||||
#define FILEID_BOTH_DIRECTORY_INFORMATION 37
|
||||
#define FILEID_FULL_DIRECTORY_INFORMATION 38
|
||||
#define FILE_VALID_DATA_LENGTH_INFORMATION 39
|
||||
#define FILE_SHORT_NAME_INFORMATION 40
|
||||
#define FILE_SFIO_RESERVE_INFORMATION 44
|
||||
#define FILE_SFIO_VOLUME_INFORMATION 45
|
||||
#define FILE_HARD_LINK_INFORMATION 46
|
||||
#define FILE_NORMALIZED_NAME_INFORMATION 48
|
||||
#define FILEID_GLOBAL_TX_DIRECTORY_INFORMATION 50
|
||||
#define FILE_STANDARD_LINK_INFORMATION 54
|
||||
|
||||
/*
|
||||
* This level 18, although with struct with same name is different from cifs
|
||||
* level 0x107. Level 0x107 has an extra u64 between AccessFlags and
|
||||
* CurrentByteOffset.
|
||||
*/
|
||||
struct smb2_file_all_info { /* data block encoding of response to level 18 */
|
||||
__le64 CreationTime; /* Beginning of FILE_BASIC_INFO equivalent */
|
||||
__le64 LastAccessTime;
|
||||
__le64 LastWriteTime;
|
||||
__le64 ChangeTime;
|
||||
__le32 Attributes;
|
||||
__u32 Pad1; /* End of FILE_BASIC_INFO_INFO equivalent */
|
||||
__le64 AllocationSize; /* Beginning of FILE_STANDARD_INFO equivalent */
|
||||
__le64 EndOfFile; /* size ie offset to first free byte in file */
|
||||
__le32 NumberOfLinks; /* hard links */
|
||||
__u8 DeletePending;
|
||||
__u8 Directory;
|
||||
__u16 Pad2; /* End of FILE_STANDARD_INFO equivalent */
|
||||
__le64 IndexNumber;
|
||||
__le32 EASize;
|
||||
__le32 AccessFlags;
|
||||
__le64 CurrentByteOffset;
|
||||
__le32 Mode;
|
||||
__le32 AlignmentRequirement;
|
||||
__le32 FileNameLength;
|
||||
char FileName[1];
|
||||
} __packed; /* level 18 Query */
|
||||
|
||||
#endif /* _SMB2PDU_H */
|
78
fs/cifs/smb2proto.h
Normal file
78
fs/cifs/smb2proto.h
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* fs/cifs/smb2proto.h
|
||||
*
|
||||
* Copyright (c) International Business Machines Corp., 2002, 2011
|
||||
* Etersoft, 2012
|
||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||
* Pavel Shilovsky (pshilovsky@samba.org) 2012
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
|
||||
* the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef _SMB2PROTO_H
|
||||
#define _SMB2PROTO_H
|
||||
#include <linux/nls.h>
|
||||
#include <linux/key-type.h>
|
||||
|
||||
struct statfs;
|
||||
|
||||
/*
|
||||
*****************************************************************
|
||||
* All Prototypes
|
||||
*****************************************************************
|
||||
*/
|
||||
extern int map_smb2_to_linux_error(char *buf, bool log_err);
|
||||
extern int smb2_check_message(char *buf, unsigned int length);
|
||||
extern unsigned int smb2_calc_size(struct smb2_hdr *hdr);
|
||||
extern char *smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr);
|
||||
extern __le16 *cifs_convert_path_to_utf16(const char *from,
|
||||
struct cifs_sb_info *cifs_sb);
|
||||
|
||||
extern int smb2_check_receive(struct mid_q_entry *mid,
|
||||
struct TCP_Server_Info *server, bool log_error);
|
||||
extern int smb2_setup_request(struct cifs_ses *ses, struct kvec *iov,
|
||||
unsigned int nvec, struct mid_q_entry **ret_mid);
|
||||
extern int smb2_setup_async_request(struct TCP_Server_Info *server,
|
||||
struct kvec *iov, unsigned int nvec,
|
||||
struct mid_q_entry **ret_mid);
|
||||
extern void smb2_echo_request(struct work_struct *work);
|
||||
|
||||
extern int smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
struct cifs_sb_info *cifs_sb,
|
||||
const char *full_path, FILE_ALL_INFO *data,
|
||||
bool *adjust_tz);
|
||||
/*
|
||||
* SMB2 Worker functions - most of protocol specific implementation details
|
||||
* are contained within these calls.
|
||||
*/
|
||||
extern int SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses);
|
||||
extern int SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses,
|
||||
const struct nls_table *nls_cp);
|
||||
extern int SMB2_logoff(const unsigned int xid, struct cifs_ses *ses);
|
||||
extern int SMB2_tcon(const unsigned int xid, struct cifs_ses *ses,
|
||||
const char *tree, struct cifs_tcon *tcon,
|
||||
const struct nls_table *);
|
||||
extern int SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon);
|
||||
extern int SMB2_open(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
__le16 *path, u64 *persistent_fid, u64 *volatile_fid,
|
||||
__u32 desired_access, __u32 create_disposition,
|
||||
__u32 file_attributes, __u32 create_options);
|
||||
extern int SMB2_close(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
u64 persistent_file_id, u64 volatile_file_id);
|
||||
extern int SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
u64 persistent_file_id, u64 volatile_file_id,
|
||||
struct smb2_file_all_info *data);
|
||||
extern int SMB2_echo(struct TCP_Server_Info *server);
|
||||
|
||||
#endif /* _SMB2PROTO_H */
|
1782
fs/cifs/smb2status.h
Normal file
1782
fs/cifs/smb2status.h
Normal file
File diff suppressed because it is too large
Load Diff
172
fs/cifs/smb2transport.c
Normal file
172
fs/cifs/smb2transport.c
Normal file
@ -0,0 +1,172 @@
|
||||
/*
|
||||
* fs/cifs/smb2transport.c
|
||||
*
|
||||
* Copyright (C) International Business Machines Corp., 2002, 2011
|
||||
* Etersoft, 2012
|
||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||
* Jeremy Allison (jra@samba.org) 2006
|
||||
* Pavel Shilovsky (pshilovsky@samba.org) 2012
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
|
||||
* the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/net.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/processor.h>
|
||||
#include <linux/mempool.h>
|
||||
#include "smb2pdu.h"
|
||||
#include "cifsglob.h"
|
||||
#include "cifsproto.h"
|
||||
#include "smb2proto.h"
|
||||
#include "cifs_debug.h"
|
||||
#include "smb2status.h"
|
||||
|
||||
/*
|
||||
* Set message id for the request. Should be called after wait_for_free_request
|
||||
* and when srv_mutex is held.
|
||||
*/
|
||||
static inline void
|
||||
smb2_seq_num_into_buf(struct TCP_Server_Info *server, struct smb2_hdr *hdr)
|
||||
{
|
||||
hdr->MessageId = get_next_mid(server);
|
||||
}
|
||||
|
||||
static struct mid_q_entry *
|
||||
smb2_mid_entry_alloc(const struct smb2_hdr *smb_buffer,
|
||||
struct TCP_Server_Info *server)
|
||||
{
|
||||
struct mid_q_entry *temp;
|
||||
|
||||
if (server == NULL) {
|
||||
cERROR(1, "Null TCP session in smb2_mid_entry_alloc");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);
|
||||
if (temp == NULL)
|
||||
return temp;
|
||||
else {
|
||||
memset(temp, 0, sizeof(struct mid_q_entry));
|
||||
temp->mid = smb_buffer->MessageId; /* always LE */
|
||||
temp->pid = current->pid;
|
||||
temp->command = smb_buffer->Command; /* Always LE */
|
||||
temp->when_alloc = jiffies;
|
||||
temp->server = server;
|
||||
|
||||
/*
|
||||
* The default is for the mid to be synchronous, so the
|
||||
* default callback just wakes up the current task.
|
||||
*/
|
||||
temp->callback = cifs_wake_up_task;
|
||||
temp->callback_data = current;
|
||||
}
|
||||
|
||||
atomic_inc(&midCount);
|
||||
temp->mid_state = MID_REQUEST_ALLOCATED;
|
||||
return temp;
|
||||
}
|
||||
|
||||
static int
|
||||
smb2_get_mid_entry(struct cifs_ses *ses, struct smb2_hdr *buf,
|
||||
struct mid_q_entry **mid)
|
||||
{
|
||||
if (ses->server->tcpStatus == CifsExiting)
|
||||
return -ENOENT;
|
||||
|
||||
if (ses->server->tcpStatus == CifsNeedReconnect) {
|
||||
cFYI(1, "tcp session dead - return to caller to retry");
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
if (ses->status != CifsGood) {
|
||||
/* check if SMB2 session is bad because we are setting it up */
|
||||
if ((buf->Command != SMB2_SESSION_SETUP) &&
|
||||
(buf->Command != SMB2_NEGOTIATE))
|
||||
return -EAGAIN;
|
||||
/* else ok - we are setting up session */
|
||||
}
|
||||
*mid = smb2_mid_entry_alloc(buf, ses->server);
|
||||
if (*mid == NULL)
|
||||
return -ENOMEM;
|
||||
spin_lock(&GlobalMid_Lock);
|
||||
list_add_tail(&(*mid)->qhead, &ses->server->pending_mid_q);
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
smb2_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
|
||||
bool log_error)
|
||||
{
|
||||
unsigned int len = get_rfc1002_length(mid->resp_buf);
|
||||
|
||||
dump_smb(mid->resp_buf, min_t(u32, 80, len));
|
||||
/* convert the length into a more usable form */
|
||||
/* BB - uncomment with SMB2 signing implementation */
|
||||
/* if ((len > 24) &&
|
||||
(server->sec_mode & (SECMODE_SIGN_REQUIRED|SECMODE_SIGN_ENABLED))) {
|
||||
if (smb2_verify_signature(mid->resp_buf, server))
|
||||
cERROR(1, "Unexpected SMB signature");
|
||||
} */
|
||||
|
||||
return map_smb2_to_linux_error(mid->resp_buf, log_error);
|
||||
}
|
||||
|
||||
int
|
||||
smb2_setup_request(struct cifs_ses *ses, struct kvec *iov,
|
||||
unsigned int nvec, struct mid_q_entry **ret_mid)
|
||||
{
|
||||
int rc;
|
||||
struct smb2_hdr *hdr = (struct smb2_hdr *)iov[0].iov_base;
|
||||
struct mid_q_entry *mid;
|
||||
|
||||
smb2_seq_num_into_buf(ses->server, hdr);
|
||||
|
||||
rc = smb2_get_mid_entry(ses, hdr, &mid);
|
||||
if (rc)
|
||||
return rc;
|
||||
/* rc = smb2_sign_smb2(iov, nvec, ses->server);
|
||||
if (rc)
|
||||
delete_mid(mid); */
|
||||
*ret_mid = mid;
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
smb2_setup_async_request(struct TCP_Server_Info *server, struct kvec *iov,
|
||||
unsigned int nvec, struct mid_q_entry **ret_mid)
|
||||
{
|
||||
int rc = 0;
|
||||
struct smb2_hdr *hdr = (struct smb2_hdr *)iov[0].iov_base;
|
||||
struct mid_q_entry *mid;
|
||||
|
||||
smb2_seq_num_into_buf(server, hdr);
|
||||
|
||||
mid = smb2_mid_entry_alloc(hdr, server);
|
||||
if (mid == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
/* rc = smb2_sign_smb2(iov, nvec, server);
|
||||
if (rc) {
|
||||
DeleteMidQEntry(mid);
|
||||
return rc;
|
||||
}*/
|
||||
*ret_mid = mid;
|
||||
return rc;
|
||||
}
|
@ -78,7 +78,7 @@ smbhash(unsigned char *out, const unsigned char *in, unsigned char *key)
|
||||
tfm_des = crypto_alloc_blkcipher("ecb(des)", 0, CRYPTO_ALG_ASYNC);
|
||||
if (IS_ERR(tfm_des)) {
|
||||
rc = PTR_ERR(tfm_des);
|
||||
cERROR(1, "could not allocate des crypto API\n");
|
||||
cERROR(1, "could not allocate des crypto API");
|
||||
goto smbhash_err;
|
||||
}
|
||||
|
||||
@ -91,7 +91,7 @@ smbhash(unsigned char *out, const unsigned char *in, unsigned char *key)
|
||||
|
||||
rc = crypto_blkcipher_encrypt(&desc, &sgout, &sgin, 8);
|
||||
if (rc)
|
||||
cERROR(1, "could not encrypt crypt key rc: %d\n", rc);
|
||||
cERROR(1, "could not encrypt crypt key rc: %d", rc);
|
||||
|
||||
crypto_free_blkcipher(tfm_des);
|
||||
smbhash_err:
|
||||
@ -139,14 +139,14 @@ mdfour(unsigned char *md4_hash, unsigned char *link_str, int link_len)
|
||||
md4 = crypto_alloc_shash("md4", 0, 0);
|
||||
if (IS_ERR(md4)) {
|
||||
rc = PTR_ERR(md4);
|
||||
cERROR(1, "%s: Crypto md4 allocation error %d\n", __func__, rc);
|
||||
cERROR(1, "%s: Crypto md4 allocation error %d", __func__, rc);
|
||||
return rc;
|
||||
}
|
||||
size = sizeof(struct shash_desc) + crypto_shash_descsize(md4);
|
||||
sdescmd4 = kmalloc(size, GFP_KERNEL);
|
||||
if (!sdescmd4) {
|
||||
rc = -ENOMEM;
|
||||
cERROR(1, "%s: Memory allocation failure\n", __func__);
|
||||
cERROR(1, "%s: Memory allocation failure", __func__);
|
||||
goto mdfour_err;
|
||||
}
|
||||
sdescmd4->shash.tfm = md4;
|
||||
@ -154,17 +154,17 @@ mdfour(unsigned char *md4_hash, unsigned char *link_str, int link_len)
|
||||
|
||||
rc = crypto_shash_init(&sdescmd4->shash);
|
||||
if (rc) {
|
||||
cERROR(1, "%s: Could not init md4 shash\n", __func__);
|
||||
cERROR(1, "%s: Could not init md4 shash", __func__);
|
||||
goto mdfour_err;
|
||||
}
|
||||
rc = crypto_shash_update(&sdescmd4->shash, link_str, link_len);
|
||||
if (rc) {
|
||||
cERROR(1, "%s: Could not update with link_str\n", __func__);
|
||||
cERROR(1, "%s: Could not update with link_str", __func__);
|
||||
goto mdfour_err;
|
||||
}
|
||||
rc = crypto_shash_final(&sdescmd4->shash, md4_hash);
|
||||
if (rc)
|
||||
cERROR(1, "%s: Could not genereate md4 hash\n", __func__);
|
||||
cERROR(1, "%s: Could not genereate md4 hash", __func__);
|
||||
|
||||
mdfour_err:
|
||||
crypto_free_shash(md4);
|
||||
|
@ -35,10 +35,8 @@
|
||||
#include "cifsproto.h"
|
||||
#include "cifs_debug.h"
|
||||
|
||||
extern mempool_t *cifs_mid_poolp;
|
||||
|
||||
static void
|
||||
wake_up_task(struct mid_q_entry *mid)
|
||||
void
|
||||
cifs_wake_up_task(struct mid_q_entry *mid)
|
||||
{
|
||||
wake_up_process(mid->callback_data);
|
||||
}
|
||||
@ -65,12 +63,13 @@ AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
|
||||
/* do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */
|
||||
/* when mid allocated can be before when sent */
|
||||
temp->when_alloc = jiffies;
|
||||
temp->server = server;
|
||||
|
||||
/*
|
||||
* The default is for the mid to be synchronous, so the
|
||||
* default callback just wakes up the current task.
|
||||
*/
|
||||
temp->callback = wake_up_task;
|
||||
temp->callback = cifs_wake_up_task;
|
||||
temp->callback_data = current;
|
||||
}
|
||||
|
||||
@ -83,6 +82,7 @@ void
|
||||
DeleteMidQEntry(struct mid_q_entry *midEntry)
|
||||
{
|
||||
#ifdef CONFIG_CIFS_STATS2
|
||||
__le16 command = midEntry->server->vals->lock_cmd;
|
||||
unsigned long now;
|
||||
#endif
|
||||
midEntry->mid_state = MID_FREE;
|
||||
@ -96,8 +96,7 @@ DeleteMidQEntry(struct mid_q_entry *midEntry)
|
||||
/* commands taking longer than one second are indications that
|
||||
something is wrong, unless it is quite a slow link or server */
|
||||
if ((now - midEntry->when_alloc) > HZ) {
|
||||
if ((cifsFYI & CIFS_TIMER) &&
|
||||
(midEntry->command != cpu_to_le16(SMB_COM_LOCKING_ANDX))) {
|
||||
if ((cifsFYI & CIFS_TIMER) && (midEntry->command != command)) {
|
||||
printk(KERN_DEBUG " CIFS slow rsp: cmd %d mid %llu",
|
||||
midEntry->command, midEntry->mid);
|
||||
printk(" A: 0x%lx S: 0x%lx R: 0x%lx\n",
|
||||
@ -126,7 +125,6 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
|
||||
int rc = 0;
|
||||
int i = 0;
|
||||
struct msghdr smb_msg;
|
||||
__be32 *buf_len = (__be32 *)(iov[0].iov_base);
|
||||
unsigned int len = iov[0].iov_len;
|
||||
unsigned int total_len;
|
||||
int first_vec = 0;
|
||||
@ -235,9 +233,6 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
|
||||
else
|
||||
rc = 0;
|
||||
|
||||
/* Don't want to modify the buffer as a side effect of this call. */
|
||||
*buf_len = cpu_to_be32(smb_buf_length);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -254,13 +249,13 @@ smb_send(struct TCP_Server_Info *server, struct smb_hdr *smb_buffer,
|
||||
}
|
||||
|
||||
static int
|
||||
wait_for_free_credits(struct TCP_Server_Info *server, const int optype,
|
||||
wait_for_free_credits(struct TCP_Server_Info *server, const int timeout,
|
||||
int *credits)
|
||||
{
|
||||
int rc;
|
||||
|
||||
spin_lock(&server->req_lock);
|
||||
if (optype == CIFS_ASYNC_OP) {
|
||||
if (timeout == CIFS_ASYNC_OP) {
|
||||
/* oplock breaks must not be held up */
|
||||
server->in_flight++;
|
||||
*credits -= 1;
|
||||
@ -290,7 +285,7 @@ wait_for_free_credits(struct TCP_Server_Info *server, const int optype,
|
||||
*/
|
||||
|
||||
/* update # of requests on the wire to server */
|
||||
if (optype != CIFS_BLOCKING_OP) {
|
||||
if (timeout != CIFS_BLOCKING_OP) {
|
||||
*credits -= 1;
|
||||
server->in_flight++;
|
||||
}
|
||||
@ -302,10 +297,11 @@ wait_for_free_credits(struct TCP_Server_Info *server, const int optype,
|
||||
}
|
||||
|
||||
static int
|
||||
wait_for_free_request(struct TCP_Server_Info *server, const int optype)
|
||||
wait_for_free_request(struct TCP_Server_Info *server, const int timeout,
|
||||
const int optype)
|
||||
{
|
||||
return wait_for_free_credits(server, optype,
|
||||
server->ops->get_credits_field(server));
|
||||
return wait_for_free_credits(server, timeout,
|
||||
server->ops->get_credits_field(server, optype));
|
||||
}
|
||||
|
||||
static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf,
|
||||
@ -349,7 +345,7 @@ wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
int
|
||||
cifs_setup_async_request(struct TCP_Server_Info *server, struct kvec *iov,
|
||||
unsigned int nvec, struct mid_q_entry **ret_mid)
|
||||
{
|
||||
@ -365,7 +361,7 @@ cifs_setup_async_request(struct TCP_Server_Info *server, struct kvec *iov,
|
||||
if (mid == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
rc = cifs_sign_smb2(iov, nvec, server, &mid->sequence_number);
|
||||
rc = cifs_sign_smbv(iov, nvec, server, &mid->sequence_number);
|
||||
if (rc) {
|
||||
DeleteMidQEntry(mid);
|
||||
return rc;
|
||||
@ -382,20 +378,23 @@ cifs_setup_async_request(struct TCP_Server_Info *server, struct kvec *iov,
|
||||
int
|
||||
cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov,
|
||||
unsigned int nvec, mid_receive_t *receive,
|
||||
mid_callback_t *callback, void *cbdata, bool ignore_pend)
|
||||
mid_callback_t *callback, void *cbdata, const int flags)
|
||||
{
|
||||
int rc;
|
||||
int rc, timeout, optype;
|
||||
struct mid_q_entry *mid;
|
||||
|
||||
rc = wait_for_free_request(server, ignore_pend ? CIFS_ASYNC_OP : 0);
|
||||
timeout = flags & CIFS_TIMEOUT_MASK;
|
||||
optype = flags & CIFS_OP_MASK;
|
||||
|
||||
rc = wait_for_free_request(server, timeout, optype);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
mutex_lock(&server->srv_mutex);
|
||||
rc = cifs_setup_async_request(server, iov, nvec, &mid);
|
||||
rc = server->ops->setup_async_request(server, iov, nvec, &mid);
|
||||
if (rc) {
|
||||
mutex_unlock(&server->srv_mutex);
|
||||
add_credits(server, 1);
|
||||
add_credits(server, 1, optype);
|
||||
wake_up(&server->request_q);
|
||||
return rc;
|
||||
}
|
||||
@ -421,7 +420,7 @@ cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov,
|
||||
return 0;
|
||||
|
||||
delete_mid(mid);
|
||||
add_credits(server, 1);
|
||||
add_credits(server, 1, optype);
|
||||
wake_up(&server->request_q);
|
||||
return rc;
|
||||
}
|
||||
@ -528,7 +527,7 @@ cifs_setup_request(struct cifs_ses *ses, struct kvec *iov,
|
||||
rc = allocate_mid(ses, hdr, &mid);
|
||||
if (rc)
|
||||
return rc;
|
||||
rc = cifs_sign_smb2(iov, nvec, ses->server, &mid->sequence_number);
|
||||
rc = cifs_sign_smbv(iov, nvec, ses->server, &mid->sequence_number);
|
||||
if (rc)
|
||||
delete_mid(mid);
|
||||
*ret_mid = mid;
|
||||
@ -537,17 +536,19 @@ cifs_setup_request(struct cifs_ses *ses, struct kvec *iov,
|
||||
|
||||
int
|
||||
SendReceive2(const unsigned int xid, struct cifs_ses *ses,
|
||||
struct kvec *iov, int n_vec, int *pRespBufType /* ret */,
|
||||
struct kvec *iov, int n_vec, int *resp_buf_type /* ret */,
|
||||
const int flags)
|
||||
{
|
||||
int rc = 0;
|
||||
int long_op;
|
||||
int timeout, optype;
|
||||
struct mid_q_entry *midQ;
|
||||
char *buf = iov[0].iov_base;
|
||||
unsigned int credits = 1;
|
||||
|
||||
long_op = flags & CIFS_TIMEOUT_MASK;
|
||||
timeout = flags & CIFS_TIMEOUT_MASK;
|
||||
optype = flags & CIFS_OP_MASK;
|
||||
|
||||
*pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */
|
||||
*resp_buf_type = CIFS_NO_BUFFER; /* no response buf yet */
|
||||
|
||||
if ((ses == NULL) || (ses->server == NULL)) {
|
||||
cifs_small_buf_release(buf);
|
||||
@ -566,7 +567,7 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
|
||||
* use ses->maxReq.
|
||||
*/
|
||||
|
||||
rc = wait_for_free_request(ses->server, long_op);
|
||||
rc = wait_for_free_request(ses->server, timeout, optype);
|
||||
if (rc) {
|
||||
cifs_small_buf_release(buf);
|
||||
return rc;
|
||||
@ -585,7 +586,7 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
|
||||
mutex_unlock(&ses->server->srv_mutex);
|
||||
cifs_small_buf_release(buf);
|
||||
/* Update # of requests on wire to server */
|
||||
add_credits(ses->server, 1);
|
||||
add_credits(ses->server, 1, optype);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -602,7 +603,7 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (long_op == CIFS_ASYNC_OP) {
|
||||
if (timeout == CIFS_ASYNC_OP) {
|
||||
cifs_small_buf_release(buf);
|
||||
goto out;
|
||||
}
|
||||
@ -615,7 +616,7 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
|
||||
midQ->callback = DeleteMidQEntry;
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
cifs_small_buf_release(buf);
|
||||
add_credits(ses->server, 1);
|
||||
add_credits(ses->server, 1, optype);
|
||||
return rc;
|
||||
}
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
@ -625,7 +626,7 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
|
||||
|
||||
rc = cifs_sync_mid_result(midQ, ses->server);
|
||||
if (rc != 0) {
|
||||
add_credits(ses->server, 1);
|
||||
add_credits(ses->server, 1, optype);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -639,9 +640,11 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
|
||||
iov[0].iov_base = buf;
|
||||
iov[0].iov_len = get_rfc1002_length(buf) + 4;
|
||||
if (midQ->large_buf)
|
||||
*pRespBufType = CIFS_LARGE_BUFFER;
|
||||
*resp_buf_type = CIFS_LARGE_BUFFER;
|
||||
else
|
||||
*pRespBufType = CIFS_SMALL_BUFFER;
|
||||
*resp_buf_type = CIFS_SMALL_BUFFER;
|
||||
|
||||
credits = ses->server->ops->get_credits(midQ);
|
||||
|
||||
rc = ses->server->ops->check_receive(midQ, ses->server,
|
||||
flags & CIFS_LOG_ERROR);
|
||||
@ -651,7 +654,7 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
|
||||
midQ->resp_buf = NULL;
|
||||
out:
|
||||
delete_mid(midQ);
|
||||
add_credits(ses->server, 1);
|
||||
add_credits(ses->server, credits, optype);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@ -659,7 +662,7 @@ out:
|
||||
int
|
||||
SendReceive(const unsigned int xid, struct cifs_ses *ses,
|
||||
struct smb_hdr *in_buf, struct smb_hdr *out_buf,
|
||||
int *pbytes_returned, const int long_op)
|
||||
int *pbytes_returned, const int timeout)
|
||||
{
|
||||
int rc = 0;
|
||||
struct mid_q_entry *midQ;
|
||||
@ -687,7 +690,7 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
rc = wait_for_free_request(ses->server, long_op);
|
||||
rc = wait_for_free_request(ses->server, timeout, 0);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
@ -701,7 +704,7 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
|
||||
if (rc) {
|
||||
mutex_unlock(&ses->server->srv_mutex);
|
||||
/* Update # of requests on wire to server */
|
||||
add_credits(ses->server, 1);
|
||||
add_credits(ses->server, 1, 0);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -722,7 +725,7 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
|
||||
if (long_op == CIFS_ASYNC_OP)
|
||||
if (timeout == CIFS_ASYNC_OP)
|
||||
goto out;
|
||||
|
||||
rc = wait_for_response(ses->server, midQ);
|
||||
@ -733,7 +736,7 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
|
||||
/* no longer considered to be "in-flight" */
|
||||
midQ->callback = DeleteMidQEntry;
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
add_credits(ses->server, 1);
|
||||
add_credits(ses->server, 1, 0);
|
||||
return rc;
|
||||
}
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
@ -741,7 +744,7 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
|
||||
|
||||
rc = cifs_sync_mid_result(midQ, ses->server);
|
||||
if (rc != 0) {
|
||||
add_credits(ses->server, 1);
|
||||
add_credits(ses->server, 1, 0);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -757,7 +760,7 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
|
||||
rc = cifs_check_receive(midQ, ses->server, 0);
|
||||
out:
|
||||
delete_mid(midQ);
|
||||
add_credits(ses->server, 1);
|
||||
add_credits(ses->server, 1, 0);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@ -822,7 +825,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
rc = wait_for_free_request(ses->server, CIFS_BLOCKING_OP);
|
||||
rc = wait_for_free_request(ses->server, CIFS_BLOCKING_OP, 0);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
@ -39,7 +39,7 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name)
|
||||
{
|
||||
int rc = -EOPNOTSUPP;
|
||||
#ifdef CONFIG_CIFS_XATTR
|
||||
int xid;
|
||||
unsigned int xid;
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
struct tcon_link *tlink;
|
||||
struct cifs_tcon *pTcon;
|
||||
@ -60,7 +60,7 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name)
|
||||
return PTR_ERR(tlink);
|
||||
pTcon = tlink_tcon(tlink);
|
||||
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
|
||||
full_path = build_path_from_dentry(direntry);
|
||||
if (full_path == NULL) {
|
||||
@ -88,7 +88,7 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name)
|
||||
}
|
||||
remove_ea_exit:
|
||||
kfree(full_path);
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
cifs_put_tlink(tlink);
|
||||
#endif
|
||||
return rc;
|
||||
@ -99,7 +99,7 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name,
|
||||
{
|
||||
int rc = -EOPNOTSUPP;
|
||||
#ifdef CONFIG_CIFS_XATTR
|
||||
int xid;
|
||||
unsigned int xid;
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
struct tcon_link *tlink;
|
||||
struct cifs_tcon *pTcon;
|
||||
@ -120,7 +120,7 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name,
|
||||
return PTR_ERR(tlink);
|
||||
pTcon = tlink_tcon(tlink);
|
||||
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
|
||||
full_path = build_path_from_dentry(direntry);
|
||||
if (full_path == NULL) {
|
||||
@ -221,7 +221,7 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name,
|
||||
|
||||
set_ea_exit:
|
||||
kfree(full_path);
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
cifs_put_tlink(tlink);
|
||||
#endif
|
||||
return rc;
|
||||
@ -232,7 +232,7 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
|
||||
{
|
||||
ssize_t rc = -EOPNOTSUPP;
|
||||
#ifdef CONFIG_CIFS_XATTR
|
||||
int xid;
|
||||
unsigned int xid;
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
struct tcon_link *tlink;
|
||||
struct cifs_tcon *pTcon;
|
||||
@ -253,7 +253,7 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
|
||||
return PTR_ERR(tlink);
|
||||
pTcon = tlink_tcon(tlink);
|
||||
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
|
||||
full_path = build_path_from_dentry(direntry);
|
||||
if (full_path == NULL) {
|
||||
@ -355,7 +355,7 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
|
||||
|
||||
get_ea_exit:
|
||||
kfree(full_path);
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
cifs_put_tlink(tlink);
|
||||
#endif
|
||||
return rc;
|
||||
@ -365,7 +365,7 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
|
||||
{
|
||||
ssize_t rc = -EOPNOTSUPP;
|
||||
#ifdef CONFIG_CIFS_XATTR
|
||||
int xid;
|
||||
unsigned int xid;
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
struct tcon_link *tlink;
|
||||
struct cifs_tcon *pTcon;
|
||||
@ -389,7 +389,7 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
|
||||
return PTR_ERR(tlink);
|
||||
pTcon = tlink_tcon(tlink);
|
||||
|
||||
xid = GetXid();
|
||||
xid = get_xid();
|
||||
|
||||
full_path = build_path_from_dentry(direntry);
|
||||
if (full_path == NULL) {
|
||||
@ -409,7 +409,7 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
|
||||
|
||||
list_ea_exit:
|
||||
kfree(full_path);
|
||||
FreeXid(xid);
|
||||
free_xid(xid);
|
||||
cifs_put_tlink(tlink);
|
||||
#endif
|
||||
return rc;
|
||||
|
Loading…
Reference in New Issue
Block a user