Commit c0bebb33 authored by Steve French's avatar Steve French

Merge bk://linux.bkbits.net/linux-2.5

into hostme.bitkeeper.com:/repos/c/cifs/linux-2.5cifs
parents 85283764 b7df0fd6
......@@ -21,11 +21,13 @@ Zwane Mwaikambo
Andi Kleen
Amrut Joshi
Shobhit Dayal
Sergey Vlasov
Test case and Bug Report contributors
-------------------------------------
Thanks to those in the community who have submitted detailed bug reports
and debug of problems they have found: Jochen Dolze, David Blaine,
Rene Scharfe, Martin Josefsson, Alexander Wild, Anthony Liguori,
Urban Widmark, Massimiliano Ferrero, Howard Owen and others.
Lars Muller, Urban Widmark, Massimiliano Ferrero, Howard Owen,
Kieron Briggs and others.
Version 1.11
------------
Better port 139 support to Windows servers (RFC1001/RFC1002 Session_Initialize) also
now allowing support for specifying client netbiosname. NT4 support added.
Version 1.10
------------
Fix reconnection (and certain failed mounts) to properly wake up the
......
......@@ -148,8 +148,8 @@ If no password is provided, mount.cifs will prompt for password entry
Restrictions
============
Servers must support the NTLM SMB dialect (which is the most recent, supported
by Samba and Windows NT, 2000 and XP and many other SMB/CIFS servers) and
servers must support either "pure-TCP" (port 445 TCP/IP CIFS connections) or RFC
by Samba and Windows NT version 4, 2000 and XP and many other SMB/CIFS servers)
Servers must support either "pure-TCP" (port 445 TCP/IP CIFS connections) or RFC
1001/1002 support for "Netbios-Over-TCP/IP." Neither of these is likely to be a
problem as most servers support this. IPv6 support is planned for the future.
......@@ -275,6 +275,15 @@ tracing to the kernel message log type:
and for more extensive tracing including the start of smb requests and responses
echo 1 > /proc/fs/cifs/traceSMB
Three other experimental features are under development and to test
require enabling an ifdef (e.g. by adding "#define CIFS_FCNTL" in cifsglob.h)
CIFS_QUOTA
CIFS_XATTR
CIFS_FCNTL (fcntl needed for support of directory change notification)
Also note that "cat /proc/fs/cifs/DebugData" will display some information about
the active sessions and the shares that are mounted. Note: NTLMv2 enablement
......
......@@ -65,14 +65,27 @@ but recognizes them
3) create of new files to FAT partitions on Windows servers can
succeed but still return access denied (appears to be Windows
not client problem). NTFS partitions do not have this problem.
4) debug connectathon special test case nfs_idem (which does
some invalid symlink naming, or at least what Samba thinks
is an invalid symlink target).
5) debug connectation lock test case 10 which fails against
Samba (may be unmappable due to POSIX to Windows lock model
differences but worth investigating). Also debug Samba to
see why lock test case 7 takes longer to complete to Samba
than to Windows.
Misc testing to do
=================
1) check out max path names and max path name components against various server
types.
2) Run dbench. Modify file portion of ltp so it can run against a mounted network
2) Modify file portion of ltp so it can run against a mounted network
share and run it against cifs vfs.
3) Additional performance testing and optimization using iozone and similar tools.
3) Additional performance testing and optimization using iozone and similar -
there are some easy changes that can be done to parallelize sequential writes,
and when signing is disabled to request larger read sizes (larger than
negotiated size) and send larger write sizes to modern servers.
4) More exhaustively test the recently added NT4 support
......@@ -672,8 +672,10 @@ static int cifs_oplock_thread(void * dummyarg)
/* down(&inode->i_sem);*/
if (S_ISREG(inode->i_mode)) {
rc = filemap_fdatawrite(inode->i_mapping);
if(CIFS_I(inode)->clientCanCacheRead == 0)
if(CIFS_I(inode)->clientCanCacheRead == 0) {
filemap_fdatawait(inode->i_mapping);
invalidate_remote_inode(inode);
}
} else
rc = 0;
/* up(&inode->i_sem);*/
......@@ -772,6 +774,6 @@ exit_cifs(void)
MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>");
MODULE_LICENSE("GPL"); /* combination of LGPL + GPL source behaves as GPL */
MODULE_DESCRIPTION
("VFS to access servers complying with the SNIA CIFS Specification e.g. Samba and Windows");
("VFS to access servers complying with the SNIA CIFS Specification e.g. Samba and Windows Revision: 1.11");
module_init(init_cifs)
module_exit(exit_cifs)
......@@ -139,6 +139,7 @@ struct TCP_Server_Info {
int capabilities; /* allow selective disabling of caps by smb sess */
__u16 timeZone;
char cryptKey[CIFS_CRYPTO_KEY_SIZE];
char workstation_RFC1001_name[16]; /* 16th byte is always zero */
};
/*
......
......@@ -26,6 +26,7 @@
#include <linux/version.h>
#include <linux/ipv6.h>
#include <linux/pagemap.h>
#include <linux/ctype.h>
#include <asm/uaccess.h>
#include <asm/processor.h>
#include "cifspdu.h"
......@@ -54,7 +55,7 @@ struct smb_vol {
char *UNC;
char *UNCip;
char *iocharset; /* local code page for mapping to and from Unicode */
char *source_rfc1001_name; /* netbios name of client */
char source_rfc1001_name[16]; /* netbios name of client */
uid_t linux_uid;
gid_t linux_gid;
mode_t file_mode;
......@@ -67,8 +68,11 @@ struct smb_vol {
unsigned short int port;
};
int ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket);
int ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket);
static int ipv4_connect(struct sockaddr_in *psin_server,
struct socket **csocket,
char * netb_name);
static int ipv6_connect(struct sockaddr_in6 *psin_server,
struct socket **csocket);
/*
......@@ -149,7 +153,9 @@ cifs_reconnect(struct TCP_Server_Info *server)
if(server->protocolType == IPV6) {
rc = ipv6_connect(&server->addr.sockAddr6,&server->ssocket);
} else {
rc = ipv4_connect(&server->addr.sockAddr, &server->ssocket);
rc = ipv4_connect(&server->addr.sockAddr,
&server->ssocket,
server->workstation_RFC1001_name);
}
if(rc) {
set_current_state(TASK_INTERRUPTIBLE);
......@@ -160,7 +166,6 @@ cifs_reconnect(struct TCP_Server_Info *server)
wake_up(&server->response_q);
}
}
return rc;
}
......@@ -456,12 +461,21 @@ cifs_parse_mount_options(char *options, const char *devname, struct smb_vol *vol
{
char *value;
char *data;
int temp_len, i, j;
unsigned int temp_len, i, j;
char separator[2];
separator[0] = ',';
separator[1] = 0;
memset(vol->source_rfc1001_name,0x20,15);
for(i=0;i < strnlen(system_utsname.nodename,15);i++) {
/* does not have to be a perfect mapping since the field is
informational, only used for servers that do not support
port 445 and it can be overridden at mount time */
vol->source_rfc1001_name[i] = toupper(system_utsname.nodename[i]);
}
vol->source_rfc1001_name[15] = 0;
vol->linux_uid = current->uid; /* current->euid instead? */
vol->linux_gid = current->gid;
vol->dir_mode = S_IRWXUGO;
......@@ -590,6 +604,8 @@ cifs_parse_mount_options(char *options, const char *devname, struct smb_vol *vol
printk(KERN_WARNING "CIFS: invalid domain name\n");
return 1; /* needs_arg; */
}
/* BB are there cases in which a comma can be valid in
a domain name and need special handling? */
if (strnlen(value, 65) < 65) {
vol->domainname = value;
cFYI(1, ("Domain name set"));
......@@ -652,12 +668,25 @@ cifs_parse_mount_options(char *options, const char *devname, struct smb_vol *vol
simple_strtoul(value, &value, 0);
}
} else if (strnicmp(data, "netbiosname", 4) == 0) {
if (!value || !*value) {
vol->source_rfc1001_name = NULL;
} else if (strnlen(value, 17) < 17) {
vol->source_rfc1001_name = value;
if (!value || !*value || (*value == ' ')) {
cFYI(1,("invalid (empty) netbiosname specified"));
} else {
printk(KERN_WARNING "CIFS: netbiosname too long (more than 15)\n");
memset(vol->source_rfc1001_name,0x20,15);
for(i=0;i<15;i++) {
/* BB are there cases in which a comma can be
valid in this workstation netbios name (and need
special handling)? */
/* We do not uppercase netbiosname for user */
if (value[i]==0)
break;
else
vol->source_rfc1001_name[i] = value[i];
}
/* The string has 16th byte zero still from
set at top of the function */
if((i==15) && (value[i] != 0))
printk(KERN_WARNING "CIFS: netbiosname longer than 15 and was truncated.\n");
}
} else if (strnicmp(data, "version", 3) == 0) {
/* ignore */
......@@ -845,8 +874,24 @@ get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
return rc;
}
int
ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket)
/* See RFC1001 section 14 on representation of Netbios names */
static void rfc1002mangle(char * target,char * source, unsigned int length)
{
unsigned int i,j;
for(i=0,j=0;i<(length);i++) {
/* mask a nibble at a time and encode */
target[j] = 'A' + (0x0F & (source[i] >> 4));
target[j+1] = 'A' + (0x0F & source[i]);
j+=2;
}
}
static int
ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
char * netbios_name)
{
int rc = 0;
int connected = 0;
......@@ -865,7 +910,6 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket)
}
psin_server->sin_family = AF_INET;
if(psin_server->sin_port) { /* user overrode default port */
rc = (*csocket)->ops->connect(*csocket,
(struct sockaddr *) psin_server,
......@@ -912,11 +956,47 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket)
the default. sock_setsockopt not used because it expects
user space buffer */
(*csocket)->sk->sk_rcvtimeo = 7 * HZ;
/* send RFC1001 sessinit */
if(psin_server->sin_port == htons(139)) {
/* some servers require RFC1001 sessinit before sending
negprot - BB check reconnection in case where second
sessinit is sent but no second negprot */
struct rfc1002_session_packet * ses_init_buf;
struct smb_hdr * smb_buf;
ses_init_buf = cifs_kcalloc(sizeof(struct rfc1002_session_packet), GFP_KERNEL);
if(ses_init_buf) {
ses_init_buf->trailer.session_req.called_len = 32;
rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
DEFAULT_CIFS_CALLED_NAME,16);
ses_init_buf->trailer.session_req.calling_len = 32;
if(netbios_name && (netbios_name[0] !=0)) {
rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
netbios_name,16);
} else {
rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
"LINUX_CIFS_CLNT",16);
}
ses_init_buf->trailer.session_req.scope1 = 0;
ses_init_buf->trailer.session_req.scope2 = 0;
/* BB fixme ensure calling space padded w/null terminate*/
smb_buf = (struct smb_hdr *)ses_init_buf;
/* sizeof RFC1002_SESSION_REQUEST with no scope */
smb_buf->smb_buf_length = 0x81000044;
rc = smb_send(*csocket, smb_buf, 0x44,
(struct sockaddr *)psin_server);
kfree(ses_init_buf);
}
/* else the negprot may still work without this
even though malloc failed */
}
return rc;
}
int
static int
ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
{
int rc = 0;
......@@ -1000,7 +1080,6 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
/* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
memset(&volume_info,0,sizeof(struct smb_vol));
if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
if(volume_info.UNC)
kfree(volume_info.UNC);
......@@ -1049,6 +1128,12 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
} else if (volume_info.UNCip){
/* BB using ip addr as server name connect to the DFS root below */
cERROR(1,("Connecting to DFS root not implemented yet"));
if(volume_info.UNC)
kfree(volume_info.UNC);
if(volume_info.password)
kfree(volume_info.password);
FreeXid(xid);
return -EINVAL;
} else /* which servers DFS root would we conect to */ {
cERROR(1,
("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified "));
......@@ -1087,7 +1172,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
sin_server.sin_port = htons(volume_info.port);
else
sin_server.sin_port = 0;
rc = ipv4_connect(&sin_server, &csocket);
rc = ipv4_connect(&sin_server,&csocket,volume_info.source_rfc1001_name);
if (rc < 0) {
cERROR(1,
("Error connecting to IPv4 socket. Aborting operation"));
......@@ -1123,6 +1208,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
init_MUTEX(&srvTcp->tcpSem);
kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
CLONE_FS | CLONE_FILES | CLONE_VM);
memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
}
}
......@@ -1131,6 +1217,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
cFYI(1, ("Existing smb sess found "));
if(volume_info.password)
kfree(volume_info.password);
/* volume_info.UNC freed at end of function */
} else if (!rc) {
cFYI(1, ("Existing smb sess not found "));
pSesInfo = sesInfoAlloc();
......@@ -1142,7 +1229,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
NIPQUAD(sin_server.sin_addr.s_addr));
}
if (!rc){
if (!rc){
/* volume_info.password freed at unmount */
if (volume_info.password)
pSesInfo->password = volume_info.password;
if (volume_info.username)
......@@ -1263,6 +1351,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
if (tcon->ses->capabilities & CAP_UNIX)
CIFSSMBQFSUnixInfo(xid, tcon, cifs_sb->local_nls);
}
/* volume_info.password is freed above when existing session found
(in which case it is not needed anymore) but when new sesion is created
the password ptr is put in the new session structure (in which case the
password will be freed at unmount time) */
if(volume_info.UNC)
kfree(volume_info.UNC);
FreeXid(xid);
......
......@@ -187,6 +187,12 @@ cifs_open(struct inode *inode, struct file *file)
(file->f_dentry->d_inode->i_size == (loff_t)le64_to_cpu(buf->EndOfFile))) {
cFYI(1,("inode unchanged on server"));
} else {
if(file->f_dentry->d_inode->i_mapping) {
/* BB no need to lock inode until after invalidate*/
/* since namei code should already have it locked?*/
filemap_fdatawrite(file->f_dentry->d_inode->i_mapping);
filemap_fdatawait(file->f_dentry->d_inode->i_mapping);
}
cFYI(1,("invalidating remote inode since open detected it changed"));
invalidate_remote_inode(file->f_dentry->d_inode);
}
......@@ -1049,7 +1055,7 @@ cifs_readpages(struct file *file, struct address_space *mapping,
} else if (bytes_read > 0) {
pSMBr = (struct smb_com_read_rsp *)smb_read_data;
cifs_copy_cache_pages(mapping, page_list, bytes_read,
smb_read_data + 4 /* RFC1000 hdr */ +
smb_read_data + 4 /* RFC1001 hdr */ +
le16_to_cpu(pSMBr->DataOffset), &lru_pvec);
i += bytes_read >> PAGE_CACHE_SHIFT;
......@@ -1277,20 +1283,20 @@ unix_fill_in_inode(struct inode *tmp_inode,
(tmp_inode->i_blksize - 1 + pfindData->NumOfBytes) >> tmp_inode->i_blkbits;
if (S_ISREG(tmp_inode->i_mode)) {
cFYI(1, (" File inode "));
cFYI(1, ("File inode"));
tmp_inode->i_op = &cifs_file_inode_ops;
tmp_inode->i_fop = &cifs_file_ops;
tmp_inode->i_data.a_ops = &cifs_addr_ops;
} else if (S_ISDIR(tmp_inode->i_mode)) {
cFYI(1, (" Directory inode"));
cFYI(1, ("Directory inode"));
tmp_inode->i_op = &cifs_dir_inode_ops;
tmp_inode->i_fop = &cifs_dir_ops;
} else if (S_ISLNK(tmp_inode->i_mode)) {
cFYI(1, (" Symbolic Link inode "));
cFYI(1, ("Symbolic Link inode"));
tmp_inode->i_op = &cifs_symlink_inode_ops;
/* tmp_inode->i_fop = *//* do not need to set to anything */
} else {
cFYI(1, (" Init special inode "));
cFYI(1, ("Special inode"));
init_special_inode(tmp_inode, tmp_inode->i_mode,
tmp_inode->i_rdev);
}
......
......@@ -42,8 +42,12 @@ struct rfc1002_session_packet {
__u16 length;
union {
struct {
__u8 called_name[16];
__u8 calling_name[16];
__u8 called_len;
__u8 called_name[32];
__u8 scope1; /* null */
__u8 calling_len;
__u8 calling_name[32];
__u8 scope2; /* null */
} session_req;
struct {
__u32 retarget_ip_addr;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment