mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 19:56:18 +00:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6: prevent cifs_writepages() from skipping unwritten pages Fixed parsing of mount options when doing DFS submount [CIFS] Fix check for tcon seal setting and fix oops on failed mount from earlier patch [CIFS] Fix build break cifs: reinstate sharing of tree connections [CIFS] minor cleanup to cifs_mount cifs: reinstate sharing of SMB sessions sans races cifs: disable sharing session and tcon and add new TCP sharing code [CIFS] clean up server protocol handling [CIFS] remove unused list, add new cifs sock list to prepare for mount/umount fix [CIFS] Fix cifs reconnection flags [CIFS] Can't rely on iov length and base when kernel_recvmsg returns error
This commit is contained in:
commit
4e14e833ac
9 changed files with 767 additions and 718 deletions
|
@ -107,12 +107,13 @@ void cifs_dump_mids(struct TCP_Server_Info *server)
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
|
static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
|
||||||
{
|
{
|
||||||
struct list_head *tmp;
|
struct list_head *tmp1, *tmp2, *tmp3;
|
||||||
struct list_head *tmp1;
|
|
||||||
struct mid_q_entry *mid_entry;
|
struct mid_q_entry *mid_entry;
|
||||||
|
struct TCP_Server_Info *server;
|
||||||
struct cifsSesInfo *ses;
|
struct cifsSesInfo *ses;
|
||||||
struct cifsTconInfo *tcon;
|
struct cifsTconInfo *tcon;
|
||||||
int i;
|
int i, j;
|
||||||
|
__u32 dev_type;
|
||||||
|
|
||||||
seq_puts(m,
|
seq_puts(m,
|
||||||
"Display Internal CIFS Data Structures for Debugging\n"
|
"Display Internal CIFS Data Structures for Debugging\n"
|
||||||
|
@ -122,46 +123,78 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
|
||||||
seq_printf(m, "Servers:");
|
seq_printf(m, "Servers:");
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
read_lock(&GlobalSMBSeslock);
|
read_lock(&cifs_tcp_ses_lock);
|
||||||
list_for_each(tmp, &GlobalSMBSessionList) {
|
list_for_each(tmp1, &cifs_tcp_ses_list) {
|
||||||
|
server = list_entry(tmp1, struct TCP_Server_Info,
|
||||||
|
tcp_ses_list);
|
||||||
i++;
|
i++;
|
||||||
ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
|
list_for_each(tmp2, &server->smb_ses_list) {
|
||||||
if ((ses->serverDomain == NULL) || (ses->serverOS == NULL) ||
|
ses = list_entry(tmp2, struct cifsSesInfo,
|
||||||
(ses->serverNOS == NULL)) {
|
smb_ses_list);
|
||||||
seq_printf(m, "\nentry for %s not fully "
|
if ((ses->serverDomain == NULL) ||
|
||||||
"displayed\n\t", ses->serverName);
|
(ses->serverOS == NULL) ||
|
||||||
} else {
|
(ses->serverNOS == NULL)) {
|
||||||
seq_printf(m,
|
seq_printf(m, "\n%d) entry for %s not fully "
|
||||||
"\n%d) Name: %s Domain: %s Mounts: %d OS:"
|
"displayed\n\t", i, ses->serverName);
|
||||||
" %s \n\tNOS: %s\tCapability: 0x%x\n\tSMB"
|
} else {
|
||||||
|
seq_printf(m,
|
||||||
|
"\n%d) Name: %s Domain: %s Uses: %d OS:"
|
||||||
|
" %s\n\tNOS: %s\tCapability: 0x%x\n\tSMB"
|
||||||
" session status: %d\t",
|
" session status: %d\t",
|
||||||
i, ses->serverName, ses->serverDomain,
|
i, ses->serverName, ses->serverDomain,
|
||||||
atomic_read(&ses->inUse),
|
ses->ses_count, ses->serverOS, ses->serverNOS,
|
||||||
ses->serverOS, ses->serverNOS,
|
|
||||||
ses->capabilities, ses->status);
|
ses->capabilities, ses->status);
|
||||||
}
|
}
|
||||||
if (ses->server) {
|
|
||||||
seq_printf(m, "TCP status: %d\n\tLocal Users To "
|
seq_printf(m, "TCP status: %d\n\tLocal Users To "
|
||||||
"Server: %d SecMode: 0x%x Req On Wire: %d",
|
"Server: %d SecMode: 0x%x Req On Wire: %d",
|
||||||
ses->server->tcpStatus,
|
server->tcpStatus, server->srv_count,
|
||||||
atomic_read(&ses->server->socketUseCount),
|
server->secMode,
|
||||||
ses->server->secMode,
|
atomic_read(&server->inFlight));
|
||||||
atomic_read(&ses->server->inFlight));
|
|
||||||
|
|
||||||
#ifdef CONFIG_CIFS_STATS2
|
#ifdef CONFIG_CIFS_STATS2
|
||||||
seq_printf(m, " In Send: %d In MaxReq Wait: %d",
|
seq_printf(m, " In Send: %d In MaxReq Wait: %d",
|
||||||
atomic_read(&ses->server->inSend),
|
atomic_read(&server->inSend),
|
||||||
atomic_read(&ses->server->num_waiters));
|
atomic_read(&server->num_waiters));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
seq_puts(m, "\nMIDs:\n");
|
seq_puts(m, "\n\tShares:");
|
||||||
|
j = 0;
|
||||||
|
list_for_each(tmp3, &ses->tcon_list) {
|
||||||
|
tcon = list_entry(tmp3, struct cifsTconInfo,
|
||||||
|
tcon_list);
|
||||||
|
++j;
|
||||||
|
dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType);
|
||||||
|
seq_printf(m, "\n\t%d) %s Mounts: %d ", j,
|
||||||
|
tcon->treeName, tcon->tc_count);
|
||||||
|
if (tcon->nativeFileSystem) {
|
||||||
|
seq_printf(m, "Type: %s ",
|
||||||
|
tcon->nativeFileSystem);
|
||||||
|
}
|
||||||
|
seq_printf(m, "DevInfo: 0x%x Attributes: 0x%x"
|
||||||
|
"\nPathComponentMax: %d Status: 0x%d",
|
||||||
|
le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics),
|
||||||
|
le32_to_cpu(tcon->fsAttrInfo.Attributes),
|
||||||
|
le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength),
|
||||||
|
tcon->tidStatus);
|
||||||
|
if (dev_type == FILE_DEVICE_DISK)
|
||||||
|
seq_puts(m, " type: DISK ");
|
||||||
|
else if (dev_type == FILE_DEVICE_CD_ROM)
|
||||||
|
seq_puts(m, " type: CDROM ");
|
||||||
|
else
|
||||||
|
seq_printf(m, " type: %d ", dev_type);
|
||||||
|
|
||||||
|
if (tcon->need_reconnect)
|
||||||
|
seq_puts(m, "\tDISCONNECTED ");
|
||||||
|
seq_putc(m, '\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
seq_puts(m, "\n\tMIDs:\n");
|
||||||
|
|
||||||
spin_lock(&GlobalMid_Lock);
|
spin_lock(&GlobalMid_Lock);
|
||||||
list_for_each(tmp1, &ses->server->pending_mid_q) {
|
list_for_each(tmp3, &server->pending_mid_q) {
|
||||||
mid_entry = list_entry(tmp1, struct
|
mid_entry = list_entry(tmp3, struct mid_q_entry,
|
||||||
mid_q_entry,
|
|
||||||
qhead);
|
qhead);
|
||||||
seq_printf(m, "State: %d com: %d pid:"
|
seq_printf(m, "\tState: %d com: %d pid:"
|
||||||
" %d tsk: %p mid %d\n",
|
" %d tsk: %p mid %d\n",
|
||||||
mid_entry->midState,
|
mid_entry->midState,
|
||||||
(int)mid_entry->command,
|
(int)mid_entry->command,
|
||||||
|
@ -171,44 +204,8 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
|
||||||
}
|
}
|
||||||
spin_unlock(&GlobalMid_Lock);
|
spin_unlock(&GlobalMid_Lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
read_unlock(&GlobalSMBSeslock);
|
read_unlock(&cifs_tcp_ses_lock);
|
||||||
seq_putc(m, '\n');
|
|
||||||
|
|
||||||
seq_puts(m, "Shares:");
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
read_lock(&GlobalSMBSeslock);
|
|
||||||
list_for_each(tmp, &GlobalTreeConnectionList) {
|
|
||||||
__u32 dev_type;
|
|
||||||
i++;
|
|
||||||
tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
|
|
||||||
dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType);
|
|
||||||
seq_printf(m, "\n%d) %s Uses: %d ", i,
|
|
||||||
tcon->treeName, atomic_read(&tcon->useCount));
|
|
||||||
if (tcon->nativeFileSystem) {
|
|
||||||
seq_printf(m, "Type: %s ",
|
|
||||||
tcon->nativeFileSystem);
|
|
||||||
}
|
|
||||||
seq_printf(m, "DevInfo: 0x%x Attributes: 0x%x"
|
|
||||||
"\nPathComponentMax: %d Status: %d",
|
|
||||||
le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics),
|
|
||||||
le32_to_cpu(tcon->fsAttrInfo.Attributes),
|
|
||||||
le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength),
|
|
||||||
tcon->tidStatus);
|
|
||||||
if (dev_type == FILE_DEVICE_DISK)
|
|
||||||
seq_puts(m, " type: DISK ");
|
|
||||||
else if (dev_type == FILE_DEVICE_CD_ROM)
|
|
||||||
seq_puts(m, " type: CDROM ");
|
|
||||||
else
|
|
||||||
seq_printf(m, " type: %d ", dev_type);
|
|
||||||
|
|
||||||
if (tcon->tidStatus == CifsNeedReconnect)
|
|
||||||
seq_puts(m, "\tDISCONNECTED ");
|
|
||||||
}
|
|
||||||
read_unlock(&GlobalSMBSeslock);
|
|
||||||
|
|
||||||
seq_putc(m, '\n');
|
seq_putc(m, '\n');
|
||||||
|
|
||||||
/* BB add code to dump additional info such as TCP session info now */
|
/* BB add code to dump additional info such as TCP session info now */
|
||||||
|
@ -234,7 +231,9 @@ static ssize_t cifs_stats_proc_write(struct file *file,
|
||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
int rc;
|
int rc;
|
||||||
struct list_head *tmp;
|
struct list_head *tmp1, *tmp2, *tmp3;
|
||||||
|
struct TCP_Server_Info *server;
|
||||||
|
struct cifsSesInfo *ses;
|
||||||
struct cifsTconInfo *tcon;
|
struct cifsTconInfo *tcon;
|
||||||
|
|
||||||
rc = get_user(c, buffer);
|
rc = get_user(c, buffer);
|
||||||
|
@ -242,33 +241,42 @@ static ssize_t cifs_stats_proc_write(struct file *file,
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
if (c == '1' || c == 'y' || c == 'Y' || c == '0') {
|
if (c == '1' || c == 'y' || c == 'Y' || c == '0') {
|
||||||
read_lock(&GlobalSMBSeslock);
|
|
||||||
#ifdef CONFIG_CIFS_STATS2
|
#ifdef CONFIG_CIFS_STATS2
|
||||||
atomic_set(&totBufAllocCount, 0);
|
atomic_set(&totBufAllocCount, 0);
|
||||||
atomic_set(&totSmBufAllocCount, 0);
|
atomic_set(&totSmBufAllocCount, 0);
|
||||||
#endif /* CONFIG_CIFS_STATS2 */
|
#endif /* CONFIG_CIFS_STATS2 */
|
||||||
list_for_each(tmp, &GlobalTreeConnectionList) {
|
read_lock(&cifs_tcp_ses_lock);
|
||||||
tcon = list_entry(tmp, struct cifsTconInfo,
|
list_for_each(tmp1, &cifs_tcp_ses_list) {
|
||||||
cifsConnectionList);
|
server = list_entry(tmp1, struct TCP_Server_Info,
|
||||||
atomic_set(&tcon->num_smbs_sent, 0);
|
tcp_ses_list);
|
||||||
atomic_set(&tcon->num_writes, 0);
|
list_for_each(tmp2, &server->smb_ses_list) {
|
||||||
atomic_set(&tcon->num_reads, 0);
|
ses = list_entry(tmp2, struct cifsSesInfo,
|
||||||
atomic_set(&tcon->num_oplock_brks, 0);
|
smb_ses_list);
|
||||||
atomic_set(&tcon->num_opens, 0);
|
list_for_each(tmp3, &ses->tcon_list) {
|
||||||
atomic_set(&tcon->num_closes, 0);
|
tcon = list_entry(tmp3,
|
||||||
atomic_set(&tcon->num_deletes, 0);
|
struct cifsTconInfo,
|
||||||
atomic_set(&tcon->num_mkdirs, 0);
|
tcon_list);
|
||||||
atomic_set(&tcon->num_rmdirs, 0);
|
atomic_set(&tcon->num_smbs_sent, 0);
|
||||||
atomic_set(&tcon->num_renames, 0);
|
atomic_set(&tcon->num_writes, 0);
|
||||||
atomic_set(&tcon->num_t2renames, 0);
|
atomic_set(&tcon->num_reads, 0);
|
||||||
atomic_set(&tcon->num_ffirst, 0);
|
atomic_set(&tcon->num_oplock_brks, 0);
|
||||||
atomic_set(&tcon->num_fnext, 0);
|
atomic_set(&tcon->num_opens, 0);
|
||||||
atomic_set(&tcon->num_fclose, 0);
|
atomic_set(&tcon->num_closes, 0);
|
||||||
atomic_set(&tcon->num_hardlinks, 0);
|
atomic_set(&tcon->num_deletes, 0);
|
||||||
atomic_set(&tcon->num_symlinks, 0);
|
atomic_set(&tcon->num_mkdirs, 0);
|
||||||
atomic_set(&tcon->num_locks, 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
read_unlock(&GlobalSMBSeslock);
|
read_unlock(&cifs_tcp_ses_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
|
@ -277,7 +285,9 @@ static ssize_t cifs_stats_proc_write(struct file *file,
|
||||||
static int cifs_stats_proc_show(struct seq_file *m, void *v)
|
static int cifs_stats_proc_show(struct seq_file *m, void *v)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct list_head *tmp;
|
struct list_head *tmp1, *tmp2, *tmp3;
|
||||||
|
struct TCP_Server_Info *server;
|
||||||
|
struct cifsSesInfo *ses;
|
||||||
struct cifsTconInfo *tcon;
|
struct cifsTconInfo *tcon;
|
||||||
|
|
||||||
seq_printf(m,
|
seq_printf(m,
|
||||||
|
@ -306,44 +316,55 @@ static int cifs_stats_proc_show(struct seq_file *m, void *v)
|
||||||
GlobalCurrentXid, GlobalMaxActiveXid);
|
GlobalCurrentXid, GlobalMaxActiveXid);
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
read_lock(&GlobalSMBSeslock);
|
read_lock(&cifs_tcp_ses_lock);
|
||||||
list_for_each(tmp, &GlobalTreeConnectionList) {
|
list_for_each(tmp1, &cifs_tcp_ses_list) {
|
||||||
i++;
|
server = list_entry(tmp1, struct TCP_Server_Info,
|
||||||
tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
|
tcp_ses_list);
|
||||||
seq_printf(m, "\n%d) %s", i, tcon->treeName);
|
list_for_each(tmp2, &server->smb_ses_list) {
|
||||||
if (tcon->tidStatus == CifsNeedReconnect)
|
ses = list_entry(tmp2, struct cifsSesInfo,
|
||||||
seq_puts(m, "\tDISCONNECTED ");
|
smb_ses_list);
|
||||||
seq_printf(m, "\nSMBs: %d Oplock Breaks: %d",
|
list_for_each(tmp3, &ses->tcon_list) {
|
||||||
atomic_read(&tcon->num_smbs_sent),
|
tcon = list_entry(tmp3,
|
||||||
atomic_read(&tcon->num_oplock_brks));
|
struct cifsTconInfo,
|
||||||
seq_printf(m, "\nReads: %d Bytes: %lld",
|
tcon_list);
|
||||||
atomic_read(&tcon->num_reads),
|
i++;
|
||||||
(long long)(tcon->bytes_read));
|
seq_printf(m, "\n%d) %s", i, tcon->treeName);
|
||||||
seq_printf(m, "\nWrites: %d Bytes: %lld",
|
if (tcon->need_reconnect)
|
||||||
atomic_read(&tcon->num_writes),
|
seq_puts(m, "\tDISCONNECTED ");
|
||||||
(long long)(tcon->bytes_written));
|
seq_printf(m, "\nSMBs: %d Oplock Breaks: %d",
|
||||||
seq_printf(m,
|
atomic_read(&tcon->num_smbs_sent),
|
||||||
"\nLocks: %d HardLinks: %d Symlinks: %d",
|
atomic_read(&tcon->num_oplock_brks));
|
||||||
atomic_read(&tcon->num_locks),
|
seq_printf(m, "\nReads: %d Bytes: %lld",
|
||||||
atomic_read(&tcon->num_hardlinks),
|
atomic_read(&tcon->num_reads),
|
||||||
atomic_read(&tcon->num_symlinks));
|
(long long)(tcon->bytes_read));
|
||||||
|
seq_printf(m, "\nWrites: %d Bytes: %lld",
|
||||||
seq_printf(m, "\nOpens: %d Closes: %d Deletes: %d",
|
atomic_read(&tcon->num_writes),
|
||||||
atomic_read(&tcon->num_opens),
|
(long long)(tcon->bytes_written));
|
||||||
atomic_read(&tcon->num_closes),
|
seq_printf(m, "\nLocks: %d HardLinks: %d "
|
||||||
atomic_read(&tcon->num_deletes));
|
"Symlinks: %d",
|
||||||
seq_printf(m, "\nMkdirs: %d Rmdirs: %d",
|
atomic_read(&tcon->num_locks),
|
||||||
atomic_read(&tcon->num_mkdirs),
|
atomic_read(&tcon->num_hardlinks),
|
||||||
atomic_read(&tcon->num_rmdirs));
|
atomic_read(&tcon->num_symlinks));
|
||||||
seq_printf(m, "\nRenames: %d T2 Renames %d",
|
seq_printf(m, "\nOpens: %d Closes: %d"
|
||||||
atomic_read(&tcon->num_renames),
|
"Deletes: %d",
|
||||||
atomic_read(&tcon->num_t2renames));
|
atomic_read(&tcon->num_opens),
|
||||||
seq_printf(m, "\nFindFirst: %d FNext %d FClose %d",
|
atomic_read(&tcon->num_closes),
|
||||||
atomic_read(&tcon->num_ffirst),
|
atomic_read(&tcon->num_deletes));
|
||||||
atomic_read(&tcon->num_fnext),
|
seq_printf(m, "\nMkdirs: %d Rmdirs: %d",
|
||||||
atomic_read(&tcon->num_fclose));
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
read_unlock(&GlobalSMBSeslock);
|
read_unlock(&cifs_tcp_ses_lock);
|
||||||
|
|
||||||
seq_putc(m, '\n');
|
seq_putc(m, '\n');
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -106,7 +106,8 @@ static char *cifs_get_share_name(const char *node_name)
|
||||||
/**
|
/**
|
||||||
* compose_mount_options - creates mount options for refferral
|
* compose_mount_options - creates mount options for refferral
|
||||||
* @sb_mountdata: parent/root DFS mount options (template)
|
* @sb_mountdata: parent/root DFS mount options (template)
|
||||||
* @ref_unc: refferral server UNC
|
* @dentry: point where we are going to mount
|
||||||
|
* @ref: server's referral
|
||||||
* @devname: pointer for saving device name
|
* @devname: pointer for saving device name
|
||||||
*
|
*
|
||||||
* creates mount options for submount based on template options sb_mountdata
|
* creates mount options for submount based on template options sb_mountdata
|
||||||
|
@ -116,7 +117,8 @@ static char *cifs_get_share_name(const char *node_name)
|
||||||
* Caller is responcible for freeing retunrned value if it is not error.
|
* Caller is responcible for freeing retunrned value if it is not error.
|
||||||
*/
|
*/
|
||||||
static char *compose_mount_options(const char *sb_mountdata,
|
static char *compose_mount_options(const char *sb_mountdata,
|
||||||
const char *ref_unc,
|
struct dentry *dentry,
|
||||||
|
const struct dfs_info3_param *ref,
|
||||||
char **devname)
|
char **devname)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
@ -126,11 +128,12 @@ static char *compose_mount_options(const char *sb_mountdata,
|
||||||
char *srvIP = NULL;
|
char *srvIP = NULL;
|
||||||
char sep = ',';
|
char sep = ',';
|
||||||
int off, noff;
|
int off, noff;
|
||||||
|
char *fullpath;
|
||||||
|
|
||||||
if (sb_mountdata == NULL)
|
if (sb_mountdata == NULL)
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
*devname = cifs_get_share_name(ref_unc);
|
*devname = cifs_get_share_name(ref->node_name);
|
||||||
rc = dns_resolve_server_name_to_ip(*devname, &srvIP);
|
rc = dns_resolve_server_name_to_ip(*devname, &srvIP);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
cERROR(1, ("%s: Failed to resolve server part of %s to IP",
|
cERROR(1, ("%s: Failed to resolve server part of %s to IP",
|
||||||
|
@ -138,7 +141,12 @@ static char *compose_mount_options(const char *sb_mountdata,
|
||||||
mountdata = ERR_PTR(rc);
|
mountdata = ERR_PTR(rc);
|
||||||
goto compose_mount_options_out;
|
goto compose_mount_options_out;
|
||||||
}
|
}
|
||||||
md_len = strlen(sb_mountdata) + strlen(srvIP) + strlen(ref_unc) + 3;
|
/* md_len = strlen(...) + 12 for 'sep+prefixpath='
|
||||||
|
* assuming that we have 'unc=' and 'ip=' in
|
||||||
|
* the original sb_mountdata
|
||||||
|
*/
|
||||||
|
md_len = strlen(sb_mountdata) + strlen(srvIP) +
|
||||||
|
strlen(ref->node_name) + 12;
|
||||||
mountdata = kzalloc(md_len+1, GFP_KERNEL);
|
mountdata = kzalloc(md_len+1, GFP_KERNEL);
|
||||||
if (mountdata == NULL) {
|
if (mountdata == NULL) {
|
||||||
mountdata = ERR_PTR(-ENOMEM);
|
mountdata = ERR_PTR(-ENOMEM);
|
||||||
|
@ -152,41 +160,56 @@ static char *compose_mount_options(const char *sb_mountdata,
|
||||||
strncpy(mountdata, sb_mountdata, 5);
|
strncpy(mountdata, sb_mountdata, 5);
|
||||||
off += 5;
|
off += 5;
|
||||||
}
|
}
|
||||||
while ((tkn_e = strchr(sb_mountdata+off, sep))) {
|
|
||||||
noff = (tkn_e - (sb_mountdata+off)) + 1;
|
do {
|
||||||
if (strnicmp(sb_mountdata+off, "unc=", 4) == 0) {
|
tkn_e = strchr(sb_mountdata + off, sep);
|
||||||
|
if (tkn_e == NULL)
|
||||||
|
noff = strlen(sb_mountdata + off);
|
||||||
|
else
|
||||||
|
noff = tkn_e - (sb_mountdata + off) + 1;
|
||||||
|
|
||||||
|
if (strnicmp(sb_mountdata + off, "unc=", 4) == 0) {
|
||||||
off += noff;
|
off += noff;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (strnicmp(sb_mountdata+off, "ip=", 3) == 0) {
|
if (strnicmp(sb_mountdata + off, "ip=", 3) == 0) {
|
||||||
off += noff;
|
off += noff;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (strnicmp(sb_mountdata+off, "prefixpath=", 3) == 0) {
|
if (strnicmp(sb_mountdata + off, "prefixpath=", 11) == 0) {
|
||||||
off += noff;
|
off += noff;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
strncat(mountdata, sb_mountdata+off, noff);
|
strncat(mountdata, sb_mountdata + off, noff);
|
||||||
off += noff;
|
off += noff;
|
||||||
}
|
} while (tkn_e);
|
||||||
strcat(mountdata, sb_mountdata+off);
|
strcat(mountdata, sb_mountdata + off);
|
||||||
mountdata[md_len] = '\0';
|
mountdata[md_len] = '\0';
|
||||||
|
|
||||||
/* copy new IP and ref share name */
|
/* copy new IP and ref share name */
|
||||||
strcat(mountdata, ",ip=");
|
if (mountdata[strlen(mountdata) - 1] != sep)
|
||||||
|
strncat(mountdata, &sep, 1);
|
||||||
|
strcat(mountdata, "ip=");
|
||||||
strcat(mountdata, srvIP);
|
strcat(mountdata, srvIP);
|
||||||
strcat(mountdata, ",unc=");
|
strncat(mountdata, &sep, 1);
|
||||||
|
strcat(mountdata, "unc=");
|
||||||
strcat(mountdata, *devname);
|
strcat(mountdata, *devname);
|
||||||
|
|
||||||
/* find & copy prefixpath */
|
/* find & copy prefixpath */
|
||||||
tkn_e = strchr(ref_unc+2, '\\');
|
tkn_e = strchr(ref->node_name + 2, '\\');
|
||||||
if (tkn_e) {
|
if (tkn_e == NULL) /* invalid unc, missing share name*/
|
||||||
tkn_e = strchr(tkn_e+1, '\\');
|
goto compose_mount_options_out;
|
||||||
if (tkn_e) {
|
|
||||||
strcat(mountdata, ",prefixpath=");
|
fullpath = build_path_from_dentry(dentry);
|
||||||
strcat(mountdata, tkn_e+1);
|
tkn_e = strchr(tkn_e + 1, '\\');
|
||||||
}
|
if (tkn_e || strlen(fullpath) - (ref->path_consumed)) {
|
||||||
|
strncat(mountdata, &sep, 1);
|
||||||
|
strcat(mountdata, "prefixpath=");
|
||||||
|
if (tkn_e)
|
||||||
|
strcat(mountdata, tkn_e + 1);
|
||||||
|
strcat(mountdata, fullpath + (ref->path_consumed));
|
||||||
}
|
}
|
||||||
|
kfree(fullpath);
|
||||||
|
|
||||||
/*cFYI(1,("%s: parent mountdata: %s", __func__,sb_mountdata));*/
|
/*cFYI(1,("%s: parent mountdata: %s", __func__,sb_mountdata));*/
|
||||||
/*cFYI(1, ("%s: submount mountdata: %s", __func__, mountdata ));*/
|
/*cFYI(1, ("%s: submount mountdata: %s", __func__, mountdata ));*/
|
||||||
|
@ -198,7 +221,7 @@ compose_mount_options_out:
|
||||||
|
|
||||||
|
|
||||||
static struct vfsmount *cifs_dfs_do_refmount(const struct vfsmount *mnt_parent,
|
static struct vfsmount *cifs_dfs_do_refmount(const struct vfsmount *mnt_parent,
|
||||||
struct dentry *dentry, char *ref_unc)
|
struct dentry *dentry, const struct dfs_info3_param *ref)
|
||||||
{
|
{
|
||||||
struct cifs_sb_info *cifs_sb;
|
struct cifs_sb_info *cifs_sb;
|
||||||
struct vfsmount *mnt;
|
struct vfsmount *mnt;
|
||||||
|
@ -207,7 +230,7 @@ static struct vfsmount *cifs_dfs_do_refmount(const struct vfsmount *mnt_parent,
|
||||||
|
|
||||||
cifs_sb = CIFS_SB(dentry->d_inode->i_sb);
|
cifs_sb = CIFS_SB(dentry->d_inode->i_sb);
|
||||||
mountdata = compose_mount_options(cifs_sb->mountdata,
|
mountdata = compose_mount_options(cifs_sb->mountdata,
|
||||||
ref_unc, &devname);
|
dentry, ref, &devname);
|
||||||
|
|
||||||
if (IS_ERR(mountdata))
|
if (IS_ERR(mountdata))
|
||||||
return (struct vfsmount *)mountdata;
|
return (struct vfsmount *)mountdata;
|
||||||
|
@ -310,7 +333,7 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
|
||||||
}
|
}
|
||||||
mnt = cifs_dfs_do_refmount(nd->path.mnt,
|
mnt = cifs_dfs_do_refmount(nd->path.mnt,
|
||||||
nd->path.dentry,
|
nd->path.dentry,
|
||||||
referrals[i].node_name);
|
referrals + i);
|
||||||
cFYI(1, ("%s: cifs_dfs_do_refmount:%s , mnt:%p",
|
cFYI(1, ("%s: cifs_dfs_do_refmount:%s , mnt:%p",
|
||||||
__func__,
|
__func__,
|
||||||
referrals[i].node_name, mnt));
|
referrals[i].node_name, mnt));
|
||||||
|
|
|
@ -73,8 +73,8 @@ struct key_type cifs_spnego_key_type = {
|
||||||
* strlen(";sec=ntlmsspi") */
|
* strlen(";sec=ntlmsspi") */
|
||||||
#define MAX_MECH_STR_LEN 13
|
#define MAX_MECH_STR_LEN 13
|
||||||
|
|
||||||
/* max possible addr len eg FEDC:BA98:7654:3210:FEDC:BA98:7654:3210/60 */
|
/* max possible addr len eg FEDC:BA98:7654:3210:FEDC:BA98:7654:3210/128 */
|
||||||
#define MAX_IPV6_ADDR_LEN 42
|
#define MAX_IPV6_ADDR_LEN 43
|
||||||
|
|
||||||
/* strlen of "host=" */
|
/* strlen of "host=" */
|
||||||
#define HOST_KEY_LEN 5
|
#define HOST_KEY_LEN 5
|
||||||
|
|
|
@ -514,10 +514,11 @@ static void cifs_umount_begin(struct super_block *sb)
|
||||||
tcon = cifs_sb->tcon;
|
tcon = cifs_sb->tcon;
|
||||||
if (tcon == NULL)
|
if (tcon == NULL)
|
||||||
return;
|
return;
|
||||||
down(&tcon->tconSem);
|
|
||||||
if (atomic_read(&tcon->useCount) == 1)
|
read_lock(&cifs_tcp_ses_lock);
|
||||||
|
if (tcon->tc_count == 1)
|
||||||
tcon->tidStatus = CifsExiting;
|
tcon->tidStatus = CifsExiting;
|
||||||
up(&tcon->tconSem);
|
read_unlock(&cifs_tcp_ses_lock);
|
||||||
|
|
||||||
/* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */
|
/* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */
|
||||||
/* cancel_notify_requests(tcon); */
|
/* cancel_notify_requests(tcon); */
|
||||||
|
@ -1013,7 +1014,7 @@ static int cifs_oplock_thread(void *dummyarg)
|
||||||
not bother sending an oplock release if session
|
not bother sending an oplock release if session
|
||||||
to server still is disconnected since oplock
|
to server still is disconnected since oplock
|
||||||
already released by the server in that case */
|
already released by the server in that case */
|
||||||
if (pTcon->tidStatus != CifsNeedReconnect) {
|
if (!pTcon->need_reconnect) {
|
||||||
rc = CIFSSMBLock(0, pTcon, netfid,
|
rc = CIFSSMBLock(0, pTcon, netfid,
|
||||||
0 /* len */ , 0 /* offset */, 0,
|
0 /* len */ , 0 /* offset */, 0,
|
||||||
0, LOCKING_ANDX_OPLOCK_RELEASE,
|
0, LOCKING_ANDX_OPLOCK_RELEASE,
|
||||||
|
@ -1031,24 +1032,24 @@ static int cifs_oplock_thread(void *dummyarg)
|
||||||
static int cifs_dnotify_thread(void *dummyarg)
|
static int cifs_dnotify_thread(void *dummyarg)
|
||||||
{
|
{
|
||||||
struct list_head *tmp;
|
struct list_head *tmp;
|
||||||
struct cifsSesInfo *ses;
|
struct TCP_Server_Info *server;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (try_to_freeze())
|
if (try_to_freeze())
|
||||||
continue;
|
continue;
|
||||||
set_current_state(TASK_INTERRUPTIBLE);
|
set_current_state(TASK_INTERRUPTIBLE);
|
||||||
schedule_timeout(15*HZ);
|
schedule_timeout(15*HZ);
|
||||||
read_lock(&GlobalSMBSeslock);
|
|
||||||
/* check if any stuck requests that need
|
/* check if any stuck requests that need
|
||||||
to be woken up and wakeq so the
|
to be woken up and wakeq so the
|
||||||
thread can wake up and error out */
|
thread can wake up and error out */
|
||||||
list_for_each(tmp, &GlobalSMBSessionList) {
|
read_lock(&cifs_tcp_ses_lock);
|
||||||
ses = list_entry(tmp, struct cifsSesInfo,
|
list_for_each(tmp, &cifs_tcp_ses_list) {
|
||||||
cifsSessionList);
|
server = list_entry(tmp, struct TCP_Server_Info,
|
||||||
if (ses->server && atomic_read(&ses->server->inFlight))
|
tcp_ses_list);
|
||||||
wake_up_all(&ses->server->response_q);
|
if (atomic_read(&server->inFlight))
|
||||||
|
wake_up_all(&server->response_q);
|
||||||
}
|
}
|
||||||
read_unlock(&GlobalSMBSeslock);
|
read_unlock(&cifs_tcp_ses_lock);
|
||||||
} while (!kthread_should_stop());
|
} while (!kthread_should_stop());
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1059,9 +1060,7 @@ init_cifs(void)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
cifs_proc_init();
|
cifs_proc_init();
|
||||||
/* INIT_LIST_HEAD(&GlobalServerList);*/ /* BB not implemented yet */
|
INIT_LIST_HEAD(&cifs_tcp_ses_list);
|
||||||
INIT_LIST_HEAD(&GlobalSMBSessionList);
|
|
||||||
INIT_LIST_HEAD(&GlobalTreeConnectionList);
|
|
||||||
INIT_LIST_HEAD(&GlobalOplock_Q);
|
INIT_LIST_HEAD(&GlobalOplock_Q);
|
||||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
||||||
INIT_LIST_HEAD(&GlobalDnotifyReqList);
|
INIT_LIST_HEAD(&GlobalDnotifyReqList);
|
||||||
|
@ -1089,6 +1088,7 @@ init_cifs(void)
|
||||||
GlobalMaxActiveXid = 0;
|
GlobalMaxActiveXid = 0;
|
||||||
memset(Local_System_Name, 0, 15);
|
memset(Local_System_Name, 0, 15);
|
||||||
rwlock_init(&GlobalSMBSeslock);
|
rwlock_init(&GlobalSMBSeslock);
|
||||||
|
rwlock_init(&cifs_tcp_ses_lock);
|
||||||
spin_lock_init(&GlobalMid_Lock);
|
spin_lock_init(&GlobalMid_Lock);
|
||||||
|
|
||||||
if (cifs_max_pending < 2) {
|
if (cifs_max_pending < 2) {
|
||||||
|
|
|
@ -85,8 +85,7 @@ enum securityEnum {
|
||||||
};
|
};
|
||||||
|
|
||||||
enum protocolEnum {
|
enum protocolEnum {
|
||||||
IPV4 = 0,
|
TCP = 0,
|
||||||
IPV6,
|
|
||||||
SCTP
|
SCTP
|
||||||
/* Netbios frames protocol not supported at this time */
|
/* Netbios frames protocol not supported at this time */
|
||||||
};
|
};
|
||||||
|
@ -122,6 +121,9 @@ struct cifs_cred {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct TCP_Server_Info {
|
struct TCP_Server_Info {
|
||||||
|
struct list_head tcp_ses_list;
|
||||||
|
struct list_head smb_ses_list;
|
||||||
|
int srv_count; /* reference counter */
|
||||||
/* 15 character server name + 0x20 16th byte indicating type = srv */
|
/* 15 character server name + 0x20 16th byte indicating type = srv */
|
||||||
char server_RFC1001_name[SERVER_NAME_LEN_WITH_NULL];
|
char server_RFC1001_name[SERVER_NAME_LEN_WITH_NULL];
|
||||||
char unicode_server_Name[SERVER_NAME_LEN_WITH_NULL * 2];
|
char unicode_server_Name[SERVER_NAME_LEN_WITH_NULL * 2];
|
||||||
|
@ -143,7 +145,6 @@ struct TCP_Server_Info {
|
||||||
bool svlocal:1; /* local server or remote */
|
bool svlocal:1; /* local server or remote */
|
||||||
bool noblocksnd; /* use blocking sendmsg */
|
bool noblocksnd; /* use blocking sendmsg */
|
||||||
bool noautotune; /* do not autotune send buf sizes */
|
bool noautotune; /* do not autotune send buf sizes */
|
||||||
atomic_t socketUseCount; /* number of open cifs sessions on socket */
|
|
||||||
atomic_t inFlight; /* number of requests on the wire to server */
|
atomic_t inFlight; /* number of requests on the wire to server */
|
||||||
#ifdef CONFIG_CIFS_STATS2
|
#ifdef CONFIG_CIFS_STATS2
|
||||||
atomic_t inSend; /* requests trying to send */
|
atomic_t inSend; /* requests trying to send */
|
||||||
|
@ -194,13 +195,14 @@ struct cifsUidInfo {
|
||||||
* Session structure. One of these for each uid session with a particular host
|
* Session structure. One of these for each uid session with a particular host
|
||||||
*/
|
*/
|
||||||
struct cifsSesInfo {
|
struct cifsSesInfo {
|
||||||
struct list_head cifsSessionList;
|
struct list_head smb_ses_list;
|
||||||
|
struct list_head tcon_list;
|
||||||
struct semaphore sesSem;
|
struct semaphore sesSem;
|
||||||
#if 0
|
#if 0
|
||||||
struct cifsUidInfo *uidInfo; /* pointer to user info */
|
struct cifsUidInfo *uidInfo; /* pointer to user info */
|
||||||
#endif
|
#endif
|
||||||
struct TCP_Server_Info *server; /* pointer to server info */
|
struct TCP_Server_Info *server; /* pointer to server info */
|
||||||
atomic_t inUse; /* # of mounts (tree connections) on this ses */
|
int ses_count; /* reference counter */
|
||||||
enum statusEnum status;
|
enum statusEnum status;
|
||||||
unsigned overrideSecFlg; /* if non-zero override global sec flags */
|
unsigned overrideSecFlg; /* if non-zero override global sec flags */
|
||||||
__u16 ipc_tid; /* special tid for connection to IPC share */
|
__u16 ipc_tid; /* special tid for connection to IPC share */
|
||||||
|
@ -216,6 +218,7 @@ struct cifsSesInfo {
|
||||||
char userName[MAX_USERNAME_SIZE + 1];
|
char userName[MAX_USERNAME_SIZE + 1];
|
||||||
char *domainName;
|
char *domainName;
|
||||||
char *password;
|
char *password;
|
||||||
|
bool need_reconnect:1; /* connection reset, uid now invalid */
|
||||||
};
|
};
|
||||||
/* no more than one of the following three session flags may be set */
|
/* no more than one of the following three session flags may be set */
|
||||||
#define CIFS_SES_NT4 1
|
#define CIFS_SES_NT4 1
|
||||||
|
@ -230,16 +233,15 @@ struct cifsSesInfo {
|
||||||
* session
|
* session
|
||||||
*/
|
*/
|
||||||
struct cifsTconInfo {
|
struct cifsTconInfo {
|
||||||
struct list_head cifsConnectionList;
|
struct list_head tcon_list;
|
||||||
|
int tc_count;
|
||||||
struct list_head openFileList;
|
struct list_head openFileList;
|
||||||
struct semaphore tconSem;
|
|
||||||
struct cifsSesInfo *ses; /* pointer to session associated with */
|
struct cifsSesInfo *ses; /* pointer to session associated with */
|
||||||
char treeName[MAX_TREE_SIZE + 1]; /* UNC name of resource in ASCII */
|
char treeName[MAX_TREE_SIZE + 1]; /* UNC name of resource in ASCII */
|
||||||
char *nativeFileSystem;
|
char *nativeFileSystem;
|
||||||
__u16 tid; /* The 2 byte tree id */
|
__u16 tid; /* The 2 byte tree id */
|
||||||
__u16 Flags; /* optional support bits */
|
__u16 Flags; /* optional support bits */
|
||||||
enum statusEnum tidStatus;
|
enum statusEnum tidStatus;
|
||||||
atomic_t useCount; /* how many explicit/implicit mounts to share */
|
|
||||||
#ifdef CONFIG_CIFS_STATS
|
#ifdef CONFIG_CIFS_STATS
|
||||||
atomic_t num_smbs_sent;
|
atomic_t num_smbs_sent;
|
||||||
atomic_t num_writes;
|
atomic_t num_writes;
|
||||||
|
@ -288,6 +290,7 @@ struct cifsTconInfo {
|
||||||
bool unix_ext:1; /* if false disable Linux extensions to CIFS protocol
|
bool unix_ext:1; /* if false disable Linux extensions to CIFS protocol
|
||||||
for this mount even if server would support */
|
for this mount even if server would support */
|
||||||
bool local_lease:1; /* check leases (only) on local system not remote */
|
bool local_lease:1; /* check leases (only) on local system not remote */
|
||||||
|
bool need_reconnect:1; /* connection reset, tid now invalid */
|
||||||
/* BB add field for back pointer to sb struct(s)? */
|
/* BB add field for back pointer to sb struct(s)? */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -588,21 +591,21 @@ require use of the stronger protocol */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The list of servers that did not respond with NT LM 0.12.
|
* the list of TCP_Server_Info structures, ie each of the sockets
|
||||||
* This list helps improve performance and eliminate the messages indicating
|
* connecting our client to a distinct server (ip address), is
|
||||||
* that we had a communications error talking to the server in this list.
|
* chained together by cifs_tcp_ses_list. The list of all our SMB
|
||||||
|
* sessions (and from that the tree connections) can be found
|
||||||
|
* by iterating over cifs_tcp_ses_list
|
||||||
*/
|
*/
|
||||||
/* Feature not supported */
|
GLOBAL_EXTERN struct list_head cifs_tcp_ses_list;
|
||||||
/* GLOBAL_EXTERN struct servers_not_supported *NotSuppList; */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following is a hash table of all the users we know about.
|
* This lock protects the cifs_tcp_ses_list, the list of smb sessions per
|
||||||
|
* tcp session, and the list of tcon's per smb session. It also protects
|
||||||
|
* the reference counters for the server, smb session, and tcon. Finally,
|
||||||
|
* changes to the tcon->tidStatus should be done while holding this lock.
|
||||||
*/
|
*/
|
||||||
GLOBAL_EXTERN struct smbUidInfo *GlobalUidList[UID_HASH];
|
GLOBAL_EXTERN rwlock_t cifs_tcp_ses_lock;
|
||||||
|
|
||||||
/* GLOBAL_EXTERN struct list_head GlobalServerList; BB not implemented yet */
|
|
||||||
GLOBAL_EXTERN struct list_head GlobalSMBSessionList;
|
|
||||||
GLOBAL_EXTERN struct list_head GlobalTreeConnectionList;
|
|
||||||
GLOBAL_EXTERN rwlock_t GlobalSMBSeslock; /* protects list inserts on 3 above */
|
GLOBAL_EXTERN rwlock_t GlobalSMBSeslock; /* protects list inserts on 3 above */
|
||||||
|
|
||||||
GLOBAL_EXTERN struct list_head GlobalOplock_Q;
|
GLOBAL_EXTERN struct list_head GlobalOplock_Q;
|
||||||
|
|
|
@ -190,10 +190,10 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
|
||||||
/* need to prevent multiple threads trying to
|
/* need to prevent multiple threads trying to
|
||||||
simultaneously reconnect the same SMB session */
|
simultaneously reconnect the same SMB session */
|
||||||
down(&tcon->ses->sesSem);
|
down(&tcon->ses->sesSem);
|
||||||
if (tcon->ses->status == CifsNeedReconnect)
|
if (tcon->ses->need_reconnect)
|
||||||
rc = cifs_setup_session(0, tcon->ses,
|
rc = cifs_setup_session(0, tcon->ses,
|
||||||
nls_codepage);
|
nls_codepage);
|
||||||
if (!rc && (tcon->tidStatus == CifsNeedReconnect)) {
|
if (!rc && (tcon->need_reconnect)) {
|
||||||
mark_open_files_invalid(tcon);
|
mark_open_files_invalid(tcon);
|
||||||
rc = CIFSTCon(0, tcon->ses, tcon->treeName,
|
rc = CIFSTCon(0, tcon->ses, tcon->treeName,
|
||||||
tcon, nls_codepage);
|
tcon, nls_codepage);
|
||||||
|
@ -295,7 +295,7 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
|
||||||
check for tcp and smb session status done differently
|
check for tcp and smb session status done differently
|
||||||
for those three - in the calling routine */
|
for those three - in the calling routine */
|
||||||
if (tcon) {
|
if (tcon) {
|
||||||
if (tcon->tidStatus == CifsExiting) {
|
if (tcon->need_reconnect) {
|
||||||
/* only tree disconnect, open, and write,
|
/* only tree disconnect, open, and write,
|
||||||
(and ulogoff which does not have tcon)
|
(and ulogoff which does not have tcon)
|
||||||
are allowed as we start force umount */
|
are allowed as we start force umount */
|
||||||
|
@ -337,10 +337,10 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
|
||||||
/* need to prevent multiple threads trying to
|
/* need to prevent multiple threads trying to
|
||||||
simultaneously reconnect the same SMB session */
|
simultaneously reconnect the same SMB session */
|
||||||
down(&tcon->ses->sesSem);
|
down(&tcon->ses->sesSem);
|
||||||
if (tcon->ses->status == CifsNeedReconnect)
|
if (tcon->ses->need_reconnect)
|
||||||
rc = cifs_setup_session(0, tcon->ses,
|
rc = cifs_setup_session(0, tcon->ses,
|
||||||
nls_codepage);
|
nls_codepage);
|
||||||
if (!rc && (tcon->tidStatus == CifsNeedReconnect)) {
|
if (!rc && (tcon->need_reconnect)) {
|
||||||
mark_open_files_invalid(tcon);
|
mark_open_files_invalid(tcon);
|
||||||
rc = CIFSTCon(0, tcon->ses, tcon->treeName,
|
rc = CIFSTCon(0, tcon->ses, tcon->treeName,
|
||||||
tcon, nls_codepage);
|
tcon, nls_codepage);
|
||||||
|
@ -664,8 +664,9 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
|
||||||
rc = -EIO;
|
rc = -EIO;
|
||||||
goto neg_err_exit;
|
goto neg_err_exit;
|
||||||
}
|
}
|
||||||
|
read_lock(&cifs_tcp_ses_lock);
|
||||||
if (server->socketUseCount.counter > 1) {
|
if (server->srv_count > 1) {
|
||||||
|
read_unlock(&cifs_tcp_ses_lock);
|
||||||
if (memcmp(server->server_GUID,
|
if (memcmp(server->server_GUID,
|
||||||
pSMBr->u.extended_response.
|
pSMBr->u.extended_response.
|
||||||
GUID, 16) != 0) {
|
GUID, 16) != 0) {
|
||||||
|
@ -674,9 +675,11 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
|
||||||
pSMBr->u.extended_response.GUID,
|
pSMBr->u.extended_response.GUID,
|
||||||
16);
|
16);
|
||||||
}
|
}
|
||||||
} else
|
} else {
|
||||||
|
read_unlock(&cifs_tcp_ses_lock);
|
||||||
memcpy(server->server_GUID,
|
memcpy(server->server_GUID,
|
||||||
pSMBr->u.extended_response.GUID, 16);
|
pSMBr->u.extended_response.GUID, 16);
|
||||||
|
}
|
||||||
|
|
||||||
if (count == 16) {
|
if (count == 16) {
|
||||||
server->secType = RawNTLMSSP;
|
server->secType = RawNTLMSSP;
|
||||||
|
@ -739,50 +742,31 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
cFYI(1, ("In tree disconnect"));
|
cFYI(1, ("In tree disconnect"));
|
||||||
|
|
||||||
|
/* BB: do we need to check this? These should never be NULL. */
|
||||||
|
if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If last user of the connection and
|
* No need to return error on this operation if tid invalidated and
|
||||||
* connection alive - disconnect it
|
* closed on server already e.g. due to tcp session crashing. Also,
|
||||||
* If this is the last connection on the server session disconnect it
|
* the tcon is no longer on the list, so no need to take lock before
|
||||||
* (and inside session disconnect we should check if tcp socket needs
|
* checking this.
|
||||||
* to be freed and kernel thread woken up).
|
|
||||||
*/
|
*/
|
||||||
if (tcon)
|
if (tcon->need_reconnect)
|
||||||
down(&tcon->tconSem);
|
|
||||||
else
|
|
||||||
return -EIO;
|
|
||||||
|
|
||||||
atomic_dec(&tcon->useCount);
|
|
||||||
if (atomic_read(&tcon->useCount) > 0) {
|
|
||||||
up(&tcon->tconSem);
|
|
||||||
return -EBUSY;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* No need to return error on this operation if tid invalidated and
|
|
||||||
closed on server already e.g. due to tcp session crashing */
|
|
||||||
if (tcon->tidStatus == CifsNeedReconnect) {
|
|
||||||
up(&tcon->tconSem);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
if ((tcon->ses == NULL) || (tcon->ses->server == NULL)) {
|
|
||||||
up(&tcon->tconSem);
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
|
rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
|
||||||
(void **)&smb_buffer);
|
(void **)&smb_buffer);
|
||||||
if (rc) {
|
if (rc)
|
||||||
up(&tcon->tconSem);
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
|
||||||
|
|
||||||
rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0);
|
rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0);
|
||||||
if (rc)
|
if (rc)
|
||||||
cFYI(1, ("Tree disconnect failed %d", rc));
|
cFYI(1, ("Tree disconnect failed %d", rc));
|
||||||
|
|
||||||
up(&tcon->tconSem);
|
|
||||||
|
|
||||||
/* No need to return error on this operation if tid invalidated and
|
/* No need to return error on this operation if tid invalidated and
|
||||||
closed on server already e.g. due to tcp session crashing */
|
closed on server already e.g. due to tcp session crashing */
|
||||||
if (rc == -EAGAIN)
|
if (rc == -EAGAIN)
|
||||||
rc = 0;
|
rc = 0;
|
||||||
|
|
||||||
|
@ -796,43 +780,36 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
cFYI(1, ("In SMBLogoff for session disconnect"));
|
cFYI(1, ("In SMBLogoff for session disconnect"));
|
||||||
if (ses)
|
|
||||||
down(&ses->sesSem);
|
/*
|
||||||
else
|
* BB: do we need to check validity of ses and server? They should
|
||||||
|
* always be valid since we have an active reference. If not, that
|
||||||
|
* should probably be a BUG()
|
||||||
|
*/
|
||||||
|
if (!ses || !ses->server)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
atomic_dec(&ses->inUse);
|
down(&ses->sesSem);
|
||||||
if (atomic_read(&ses->inUse) > 0) {
|
if (ses->need_reconnect)
|
||||||
up(&ses->sesSem);
|
goto session_already_dead; /* no need to send SMBlogoff if uid
|
||||||
return -EBUSY;
|
already closed due to reconnect */
|
||||||
}
|
|
||||||
rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
|
rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
up(&ses->sesSem);
|
up(&ses->sesSem);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ses->server) {
|
pSMB->hdr.Mid = GetNextMid(ses->server);
|
||||||
pSMB->hdr.Mid = GetNextMid(ses->server);
|
|
||||||
|
|
||||||
if (ses->server->secMode &
|
if (ses->server->secMode &
|
||||||
(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
|
(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
|
||||||
pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
|
pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
|
||||||
}
|
|
||||||
|
|
||||||
pSMB->hdr.Uid = ses->Suid;
|
pSMB->hdr.Uid = ses->Suid;
|
||||||
|
|
||||||
pSMB->AndXCommand = 0xFF;
|
pSMB->AndXCommand = 0xFF;
|
||||||
rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0);
|
rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0);
|
||||||
if (ses->server) {
|
session_already_dead:
|
||||||
atomic_dec(&ses->server->socketUseCount);
|
|
||||||
if (atomic_read(&ses->server->socketUseCount) == 0) {
|
|
||||||
spin_lock(&GlobalMid_Lock);
|
|
||||||
ses->server->tcpStatus = CifsExiting;
|
|
||||||
spin_unlock(&GlobalMid_Lock);
|
|
||||||
rc = -ESHUTDOWN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
up(&ses->sesSem);
|
up(&ses->sesSem);
|
||||||
|
|
||||||
/* if session dead then we do not need to do ulogoff,
|
/* if session dead then we do not need to do ulogoff,
|
||||||
|
@ -3922,6 +3899,27 @@ GetInodeNumOut:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* computes length of UCS string converted to host codepage
|
||||||
|
* @src: UCS string
|
||||||
|
* @maxlen: length of the input string in UCS characters
|
||||||
|
* (not in bytes)
|
||||||
|
*
|
||||||
|
* return: size of input string in host codepage
|
||||||
|
*/
|
||||||
|
static int hostlen_fromUCS(const __le16 *src, const int maxlen,
|
||||||
|
const struct nls_table *nls_codepage) {
|
||||||
|
int i;
|
||||||
|
int hostlen = 0;
|
||||||
|
char to[4];
|
||||||
|
int charlen;
|
||||||
|
for (i = 0; (i < maxlen) && src[i]; ++i) {
|
||||||
|
charlen = nls_codepage->uni2char(le16_to_cpu(src[i]),
|
||||||
|
to, NLS_MAX_CHARSET_SIZE);
|
||||||
|
hostlen += charlen > 0 ? charlen : 1;
|
||||||
|
}
|
||||||
|
return hostlen;
|
||||||
|
}
|
||||||
|
|
||||||
/* parses DFS refferal V3 structure
|
/* parses DFS refferal V3 structure
|
||||||
* caller is responsible for freeing target_nodes
|
* caller is responsible for freeing target_nodes
|
||||||
* returns:
|
* returns:
|
||||||
|
@ -3932,7 +3930,8 @@ static int
|
||||||
parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
|
parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
|
||||||
unsigned int *num_of_nodes,
|
unsigned int *num_of_nodes,
|
||||||
struct dfs_info3_param **target_nodes,
|
struct dfs_info3_param **target_nodes,
|
||||||
const struct nls_table *nls_codepage)
|
const struct nls_table *nls_codepage, int remap,
|
||||||
|
const char *searchName)
|
||||||
{
|
{
|
||||||
int i, rc = 0;
|
int i, rc = 0;
|
||||||
char *data_end;
|
char *data_end;
|
||||||
|
@ -3983,7 +3982,17 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
|
||||||
struct dfs_info3_param *node = (*target_nodes)+i;
|
struct dfs_info3_param *node = (*target_nodes)+i;
|
||||||
|
|
||||||
node->flags = le16_to_cpu(pSMBr->DFSFlags);
|
node->flags = le16_to_cpu(pSMBr->DFSFlags);
|
||||||
node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
|
if (is_unicode) {
|
||||||
|
__le16 *tmp = kmalloc(strlen(searchName)*2, GFP_KERNEL);
|
||||||
|
cifsConvertToUCS((__le16 *) tmp, searchName,
|
||||||
|
PATH_MAX, nls_codepage, remap);
|
||||||
|
node->path_consumed = hostlen_fromUCS(tmp,
|
||||||
|
le16_to_cpu(pSMBr->PathConsumed)/2,
|
||||||
|
nls_codepage);
|
||||||
|
kfree(tmp);
|
||||||
|
} else
|
||||||
|
node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
|
||||||
|
|
||||||
node->server_type = le16_to_cpu(ref->ServerType);
|
node->server_type = le16_to_cpu(ref->ServerType);
|
||||||
node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
|
node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
|
||||||
|
|
||||||
|
@ -4116,7 +4125,8 @@ getDFSRetry:
|
||||||
|
|
||||||
/* parse returned result into more usable form */
|
/* parse returned result into more usable form */
|
||||||
rc = parse_DFS_referrals(pSMBr, num_of_nodes,
|
rc = parse_DFS_referrals(pSMBr, num_of_nodes,
|
||||||
target_nodes, nls_codepage);
|
target_nodes, nls_codepage, remap,
|
||||||
|
searchName);
|
||||||
|
|
||||||
GetDFSRefExit:
|
GetDFSRefExit:
|
||||||
cifs_buf_release(pSMB);
|
cifs_buf_release(pSMB);
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -493,7 +493,7 @@ int cifs_close(struct inode *inode, struct file *file)
|
||||||
if (pTcon) {
|
if (pTcon) {
|
||||||
/* no sense reconnecting to close a file that is
|
/* no sense reconnecting to close a file that is
|
||||||
already closed */
|
already closed */
|
||||||
if (pTcon->tidStatus != CifsNeedReconnect) {
|
if (!pTcon->need_reconnect) {
|
||||||
timeout = 2;
|
timeout = 2;
|
||||||
while ((atomic_read(&pSMBFile->wrtPending) != 0)
|
while ((atomic_read(&pSMBFile->wrtPending) != 0)
|
||||||
&& (timeout <= 2048)) {
|
&& (timeout <= 2048)) {
|
||||||
|
@ -1404,7 +1404,10 @@ retry:
|
||||||
if ((wbc->nr_to_write -= n_iov) <= 0)
|
if ((wbc->nr_to_write -= n_iov) <= 0)
|
||||||
done = 1;
|
done = 1;
|
||||||
index = next;
|
index = next;
|
||||||
}
|
} else
|
||||||
|
/* Need to re-find the pages we skipped */
|
||||||
|
index = pvec.pages[0]->index + 1;
|
||||||
|
|
||||||
pagevec_release(&pvec);
|
pagevec_release(&pvec);
|
||||||
}
|
}
|
||||||
if (!scanned && !done) {
|
if (!scanned && !done) {
|
||||||
|
|
|
@ -75,12 +75,12 @@ sesInfoAlloc(void)
|
||||||
|
|
||||||
ret_buf = kzalloc(sizeof(struct cifsSesInfo), GFP_KERNEL);
|
ret_buf = kzalloc(sizeof(struct cifsSesInfo), GFP_KERNEL);
|
||||||
if (ret_buf) {
|
if (ret_buf) {
|
||||||
write_lock(&GlobalSMBSeslock);
|
|
||||||
atomic_inc(&sesInfoAllocCount);
|
atomic_inc(&sesInfoAllocCount);
|
||||||
ret_buf->status = CifsNew;
|
ret_buf->status = CifsNew;
|
||||||
list_add(&ret_buf->cifsSessionList, &GlobalSMBSessionList);
|
++ret_buf->ses_count;
|
||||||
|
INIT_LIST_HEAD(&ret_buf->smb_ses_list);
|
||||||
|
INIT_LIST_HEAD(&ret_buf->tcon_list);
|
||||||
init_MUTEX(&ret_buf->sesSem);
|
init_MUTEX(&ret_buf->sesSem);
|
||||||
write_unlock(&GlobalSMBSeslock);
|
|
||||||
}
|
}
|
||||||
return ret_buf;
|
return ret_buf;
|
||||||
}
|
}
|
||||||
|
@ -93,10 +93,7 @@ sesInfoFree(struct cifsSesInfo *buf_to_free)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
write_lock(&GlobalSMBSeslock);
|
|
||||||
atomic_dec(&sesInfoAllocCount);
|
atomic_dec(&sesInfoAllocCount);
|
||||||
list_del(&buf_to_free->cifsSessionList);
|
|
||||||
write_unlock(&GlobalSMBSeslock);
|
|
||||||
kfree(buf_to_free->serverOS);
|
kfree(buf_to_free->serverOS);
|
||||||
kfree(buf_to_free->serverDomain);
|
kfree(buf_to_free->serverDomain);
|
||||||
kfree(buf_to_free->serverNOS);
|
kfree(buf_to_free->serverNOS);
|
||||||
|
@ -111,17 +108,14 @@ tconInfoAlloc(void)
|
||||||
struct cifsTconInfo *ret_buf;
|
struct cifsTconInfo *ret_buf;
|
||||||
ret_buf = kzalloc(sizeof(struct cifsTconInfo), GFP_KERNEL);
|
ret_buf = kzalloc(sizeof(struct cifsTconInfo), GFP_KERNEL);
|
||||||
if (ret_buf) {
|
if (ret_buf) {
|
||||||
write_lock(&GlobalSMBSeslock);
|
|
||||||
atomic_inc(&tconInfoAllocCount);
|
atomic_inc(&tconInfoAllocCount);
|
||||||
list_add(&ret_buf->cifsConnectionList,
|
|
||||||
&GlobalTreeConnectionList);
|
|
||||||
ret_buf->tidStatus = CifsNew;
|
ret_buf->tidStatus = CifsNew;
|
||||||
|
++ret_buf->tc_count;
|
||||||
INIT_LIST_HEAD(&ret_buf->openFileList);
|
INIT_LIST_HEAD(&ret_buf->openFileList);
|
||||||
init_MUTEX(&ret_buf->tconSem);
|
INIT_LIST_HEAD(&ret_buf->tcon_list);
|
||||||
#ifdef CONFIG_CIFS_STATS
|
#ifdef CONFIG_CIFS_STATS
|
||||||
spin_lock_init(&ret_buf->stat_lock);
|
spin_lock_init(&ret_buf->stat_lock);
|
||||||
#endif
|
#endif
|
||||||
write_unlock(&GlobalSMBSeslock);
|
|
||||||
}
|
}
|
||||||
return ret_buf;
|
return ret_buf;
|
||||||
}
|
}
|
||||||
|
@ -133,10 +127,7 @@ tconInfoFree(struct cifsTconInfo *buf_to_free)
|
||||||
cFYI(1, ("Null buffer passed to tconInfoFree"));
|
cFYI(1, ("Null buffer passed to tconInfoFree"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
write_lock(&GlobalSMBSeslock);
|
|
||||||
atomic_dec(&tconInfoAllocCount);
|
atomic_dec(&tconInfoAllocCount);
|
||||||
list_del(&buf_to_free->cifsConnectionList);
|
|
||||||
write_unlock(&GlobalSMBSeslock);
|
|
||||||
kfree(buf_to_free->nativeFileSystem);
|
kfree(buf_to_free->nativeFileSystem);
|
||||||
kfree(buf_to_free);
|
kfree(buf_to_free);
|
||||||
}
|
}
|
||||||
|
@ -350,9 +341,9 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
|
||||||
if (current->fsuid != treeCon->ses->linux_uid) {
|
if (current->fsuid != treeCon->ses->linux_uid) {
|
||||||
cFYI(1, ("Multiuser mode and UID "
|
cFYI(1, ("Multiuser mode and UID "
|
||||||
"did not match tcon uid"));
|
"did not match tcon uid"));
|
||||||
read_lock(&GlobalSMBSeslock);
|
read_lock(&cifs_tcp_ses_lock);
|
||||||
list_for_each(temp_item, &GlobalSMBSessionList) {
|
list_for_each(temp_item, &treeCon->ses->server->smb_ses_list) {
|
||||||
ses = list_entry(temp_item, struct cifsSesInfo, cifsSessionList);
|
ses = list_entry(temp_item, struct cifsSesInfo, smb_ses_list);
|
||||||
if (ses->linux_uid == current->fsuid) {
|
if (ses->linux_uid == current->fsuid) {
|
||||||
if (ses->server == treeCon->ses->server) {
|
if (ses->server == treeCon->ses->server) {
|
||||||
cFYI(1, ("found matching uid substitute right smb_uid"));
|
cFYI(1, ("found matching uid substitute right smb_uid"));
|
||||||
|
@ -364,7 +355,7 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
read_unlock(&GlobalSMBSeslock);
|
read_unlock(&cifs_tcp_ses_lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -497,9 +488,10 @@ bool
|
||||||
is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
|
is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
|
||||||
{
|
{
|
||||||
struct smb_com_lock_req *pSMB = (struct smb_com_lock_req *)buf;
|
struct smb_com_lock_req *pSMB = (struct smb_com_lock_req *)buf;
|
||||||
struct list_head *tmp;
|
struct list_head *tmp, *tmp1, *tmp2;
|
||||||
struct list_head *tmp1;
|
struct cifsSesInfo *ses;
|
||||||
struct cifsTconInfo *tcon;
|
struct cifsTconInfo *tcon;
|
||||||
|
struct cifsInodeInfo *pCifsInode;
|
||||||
struct cifsFileInfo *netfile;
|
struct cifsFileInfo *netfile;
|
||||||
|
|
||||||
cFYI(1, ("Checking for oplock break or dnotify response"));
|
cFYI(1, ("Checking for oplock break or dnotify response"));
|
||||||
|
@ -554,42 +546,42 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* look up tcon based on tid & uid */
|
/* look up tcon based on tid & uid */
|
||||||
read_lock(&GlobalSMBSeslock);
|
read_lock(&cifs_tcp_ses_lock);
|
||||||
list_for_each(tmp, &GlobalTreeConnectionList) {
|
list_for_each(tmp, &srv->smb_ses_list) {
|
||||||
tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
|
ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list);
|
||||||
if ((tcon->tid == buf->Tid) && (srv == tcon->ses->server)) {
|
list_for_each(tmp1, &ses->tcon_list) {
|
||||||
|
tcon = list_entry(tmp1, struct cifsTconInfo, tcon_list);
|
||||||
|
if (tcon->tid != buf->Tid)
|
||||||
|
continue;
|
||||||
|
|
||||||
cifs_stats_inc(&tcon->num_oplock_brks);
|
cifs_stats_inc(&tcon->num_oplock_brks);
|
||||||
list_for_each(tmp1, &tcon->openFileList) {
|
list_for_each(tmp2, &tcon->openFileList) {
|
||||||
netfile = list_entry(tmp1, struct cifsFileInfo,
|
netfile = list_entry(tmp2, struct cifsFileInfo,
|
||||||
tlist);
|
tlist);
|
||||||
if (pSMB->Fid == netfile->netfid) {
|
if (pSMB->Fid != netfile->netfid)
|
||||||
struct cifsInodeInfo *pCifsInode;
|
continue;
|
||||||
read_unlock(&GlobalSMBSeslock);
|
|
||||||
cFYI(1,
|
read_unlock(&cifs_tcp_ses_lock);
|
||||||
("file id match, oplock break"));
|
cFYI(1, ("file id match, oplock break"));
|
||||||
pCifsInode =
|
pCifsInode = CIFS_I(netfile->pInode);
|
||||||
CIFS_I(netfile->pInode);
|
pCifsInode->clientCanCacheAll = false;
|
||||||
pCifsInode->clientCanCacheAll = false;
|
if (pSMB->OplockLevel == 0)
|
||||||
if (pSMB->OplockLevel == 0)
|
pCifsInode->clientCanCacheRead = false;
|
||||||
pCifsInode->clientCanCacheRead
|
pCifsInode->oplockPending = true;
|
||||||
= false;
|
AllocOplockQEntry(netfile->pInode,
|
||||||
pCifsInode->oplockPending = true;
|
netfile->netfid, tcon);
|
||||||
AllocOplockQEntry(netfile->pInode,
|
cFYI(1, ("about to wake up oplock thread"));
|
||||||
netfile->netfid,
|
if (oplockThread)
|
||||||
tcon);
|
wake_up_process(oplockThread);
|
||||||
cFYI(1,
|
|
||||||
("about to wake up oplock thread"));
|
return true;
|
||||||
if (oplockThread)
|
|
||||||
wake_up_process(oplockThread);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
read_unlock(&GlobalSMBSeslock);
|
read_unlock(&cifs_tcp_ses_lock);
|
||||||
cFYI(1, ("No matching file for oplock break"));
|
cFYI(1, ("No matching file for oplock break"));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
read_unlock(&GlobalSMBSeslock);
|
read_unlock(&cifs_tcp_ses_lock);
|
||||||
cFYI(1, ("Can not process oplock break for non-existent connection"));
|
cFYI(1, ("Can not process oplock break for non-existent connection"));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue