From ac67055ef2378ea95c34b593ddf9d0a0737a240a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 22 Jun 2005 17:26:35 -0700 Subject: [CIFS] POSIX extensions, SetFSInfo added Signed-off-by: Steve French@sfrench@us.ibm.com Signed-off-by: Jeremy Allison (jra@samba.org) --- fs/cifs/connect.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'fs/cifs/connect.c') diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index e568cc4..bef5d6f 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -74,6 +74,7 @@ struct smb_vol { unsigned server_ino:1; /* use inode numbers from server ie UniqueId */ unsigned direct_io:1; unsigned remap:1; /* set to remap seven reserved chars in filenames */ + unsigned posix_paths:1; /* unset to not ask for posix pathnames. */ unsigned int rsize; unsigned int wsize; unsigned int sockopt; @@ -745,6 +746,9 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */ vol->rw = TRUE; + /* default is always to request posix paths. */ + vol->posix_paths = 1; + if (!options) return 1; @@ -1023,6 +1027,10 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) vol->remap = 1; } else if (strnicmp(data, "nomapchars", 10) == 0) { vol->remap = 0; + } else if (strnicmp(data, "posixpaths", 10) == 0) { + vol->posix_paths = 1; + } else if (strnicmp(data, "noposixpaths", 12) == 0) { + vol->posix_paths = 0; } else if (strnicmp(data, "setuids", 7) == 0) { vol->setuids = 1; } else if (strnicmp(data, "nosetuids", 9) == 0) { @@ -1679,6 +1687,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR; if(volume_info.no_xattr) cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR; + if(volume_info.direct_io) { cERROR(1,("mounting share using direct i/o")); cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; @@ -1781,6 +1790,17 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, cFYI(1,("server negotiated posix acl support")); sb->s_flags |= MS_POSIXACL; } + + /* Try and negotiate POSIX pathnames if we can. */ + if (volume_info.posix_paths && (CIFS_UNIX_POSIX_PATHNAMES_CAP & + le64_to_cpu(tcon->fsUnixInfo.Capability))) { + if (!CIFSSMBSETFSUnixInfo(xid, tcon, CIFS_UNIX_POSIX_PATHNAMES_CAP, 0)) { + cFYI(1,("negotiated posix pathnames support")); + cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS; + } else { + cFYI(1,("posix pathnames support requested but not supported")); + } + } } } } -- cgit v1.1 From 45abc6ee2b916a235d6824a41225177bd6e5e24f Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 23 Jun 2005 13:42:03 -0500 Subject: [CIFS] Fix typo in POSIX SetFSInfo call Signed-off-by: Steve French (sfrench@us.ibm.com) --- fs/cifs/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/cifs/connect.c') diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index bef5d6f..f6d2a79 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1794,7 +1794,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, /* Try and negotiate POSIX pathnames if we can. */ if (volume_info.posix_paths && (CIFS_UNIX_POSIX_PATHNAMES_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability))) { - if (!CIFSSMBSETFSUnixInfo(xid, tcon, CIFS_UNIX_POSIX_PATHNAMES_CAP, 0)) { + if (!CIFSSMBSetFSUnixInfo(xid, tcon, CIFS_UNIX_POSIX_PATHNAMES_CAP)) { cFYI(1,("negotiated posix pathnames support")); cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS; } else { -- cgit v1.1 From d7245c2ccf14cde2023273c1ec246732d96e2c27 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 14 Jul 2005 18:25:12 -0500 Subject: [CIFS] Add compat with SFU (part 1) This should help the case of creating fifos and other special files to servers which do not support the Unix extensions. Signed-off-by: Steve French (sfrench@us.ibm.com) Thanks to Martin Koeppe for his suggestions and good analysis --- fs/cifs/connect.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'fs/cifs/connect.c') diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index f6d2a79..36f7859 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -75,6 +75,7 @@ struct smb_vol { unsigned direct_io:1; unsigned remap:1; /* set to remap seven reserved chars in filenames */ unsigned posix_paths:1; /* unset to not ask for posix pathnames. */ + unsigned sfu_emul:1; unsigned int rsize; unsigned int wsize; unsigned int sockopt; @@ -1027,6 +1028,10 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) vol->remap = 1; } else if (strnicmp(data, "nomapchars", 10) == 0) { vol->remap = 0; + } else if (strnicmp(data, "sfu", 3) == 0) { + vol->sfu_emul = 1; + } else if (strnicmp(data, "nosfu", 5) == 0) { + vol->sfu_emul = 0; } else if (strnicmp(data, "posixpaths", 10) == 0) { vol->posix_paths = 1; } else if (strnicmp(data, "noposixpaths", 12) == 0) { @@ -1687,6 +1692,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR; if(volume_info.no_xattr) cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR; + if(volume_info.sfu_emul) + cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL; if(volume_info.direct_io) { cERROR(1,("mounting share using direct i/o")); -- cgit v1.1 From 1982c344f1bf08118f7c224958b30c64e162009e Mon Sep 17 00:00:00 2001 From: Steve French Date: Wed, 17 Aug 2005 12:38:22 -0700 Subject: [CIFS] Ensure that cifs multiplex ids do not collide. Signed-off-by: Steve French (sfrench@us.ibm.com) --- fs/cifs/connect.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'fs/cifs/connect.c') diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 36f7859..9e82560 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1857,6 +1857,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, NULL /* no tCon exists yet */ , 13 /* wct */ ); + smb_buffer->Mid = GetNextMid(ses->server); pSMB->req_no_secext.AndXCommand = 0xFF; pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq); @@ -2132,6 +2133,8 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses, /* send SMBsessionSetup here */ header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, NULL /* no tCon exists yet */ , 12 /* wct */ ); + + smb_buffer->Mid = GetNextMid(ses->server); pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; pSMB->req.AndXCommand = 0xFF; pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); @@ -2398,6 +2401,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, /* send SMBsessionSetup here */ header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, NULL /* no tCon exists yet */ , 12 /* wct */ ); + + smb_buffer->Mid = GetNextMid(ses->server); pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT); @@ -2740,6 +2745,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, /* send SMBsessionSetup here */ header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, NULL /* no tCon exists yet */ , 12 /* wct */ ); + + smb_buffer->Mid = GetNextMid(ses->server); pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT); pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; pSMB->req.AndXCommand = 0xFF; @@ -3111,6 +3118,8 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX, NULL /*no tid */ , 4 /*wct */ ); + + smb_buffer->Mid = GetNextMid(ses->server); smb_buffer->Uid = ses->Suid; pSMB = (TCONX_REQ *) smb_buffer; pSMBr = (TCONX_RSP *) smb_buffer_response; -- cgit v1.1 From f191401f5906f4d942fac87ebeb4671faf1ba7d6 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 18 Aug 2005 09:37:34 -0700 Subject: [CIFS] rmmod cifs can oops if done soon after the last cifs unmount Signed-off-by: Shaggy (shaggy@austin.ibm.com) Signed-off-by: Steve French (sfrench@us.ibm.com) --- fs/cifs/connect.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) (limited to 'fs/cifs/connect.c') diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 9e82560..ef0432c 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include "cifspdu.h" @@ -44,6 +45,8 @@ #define CIFS_PORT 445 #define RFC1001_PORT 139 +static DECLARE_COMPLETION(cifsd_complete); + extern void SMBencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24); extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, @@ -339,6 +342,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) atomic_inc(&tcpSesAllocCount); length = tcpSesAllocCount.counter; write_unlock(&GlobalSMBSeslock); + complete(&cifsd_complete); if(length > 1) { mempool_resize(cifs_req_poolp, length + cifs_min_rcv, @@ -676,7 +680,7 @@ multi_t2_fnd: msleep(125); } - if (list_empty(&server->pending_mid_q)) { + if (!list_empty(&server->pending_mid_q)) { /* mpx threads have not exited yet give them at least the smb send timeout time for long ops */ /* due to delays on oplock break requests, we need @@ -713,7 +717,7 @@ multi_t2_fnd: GFP_KERNEL); } - msleep(250); + complete_and_exit(&cifsd_complete, 0); return 0; } @@ -1617,8 +1621,9 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, kfree(volume_info.password); FreeXid(xid); return rc; - } else - rc = 0; + } + wait_for_completion(&cifsd_complete); + rc = 0; memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16); srvTcp->sequence_number = 0; } @@ -1759,8 +1764,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, spin_lock(&GlobalMid_Lock); srvTcp->tcpStatus = CifsExiting; spin_unlock(&GlobalMid_Lock); - if(srvTcp->tsk) + if(srvTcp->tsk) { send_sig(SIGKILL,srvTcp->tsk,1); + wait_for_completion(&cifsd_complete); + } } /* If find_unc succeeded then rc == 0 so we can not end */ if (tcon) /* up accidently freeing someone elses tcon struct */ @@ -1773,8 +1780,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, temp_rc = CIFSSMBLogoff(xid, pSesInfo); /* if the socketUseCount is now zero */ if((temp_rc == -ESHUTDOWN) && - (pSesInfo->server->tsk)) + (pSesInfo->server->tsk)) { send_sig(SIGKILL,pSesInfo->server->tsk,1); + wait_for_completion(&cifsd_complete); + } } else cFYI(1, ("No session or bad tcon")); sesInfoFree(pSesInfo); @@ -3241,8 +3250,10 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb) return 0; } else if (rc == -ESHUTDOWN) { cFYI(1,("Waking up socket by sending it signal")); - if(cifsd_task) + if(cifsd_task) { send_sig(SIGKILL,cifsd_task,1); + wait_for_completion(&cifsd_complete); + } rc = 0; } /* else - we have an smb session left on this socket do not kill cifsd */ -- cgit v1.1 From c46fa8acdc533e8084359ea11c79d56eb98313fb Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 18 Aug 2005 20:49:57 -0700 Subject: [CIFS] Add mount option for disabling sending byte range lock requests over the wire (to help the case when applications break with cifs mandatory lock behavior. Add part one of mount option for requesting case insensitive path name matching. Signed-off-by: Steve French (sfrench@us.ibm.com) --- fs/cifs/connect.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'fs/cifs/connect.c') diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index ef0432c..6b21f6a 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -79,6 +79,8 @@ struct smb_vol { unsigned remap:1; /* set to remap seven reserved chars in filenames */ unsigned posix_paths:1; /* unset to not ask for posix pathnames. */ unsigned sfu_emul:1; + unsigned nocase; /* request case insensitive filenames */ + unsigned nobrl; /* disable sending byte range locks to srv */ unsigned int rsize; unsigned int wsize; unsigned int sockopt; @@ -1040,6 +1042,12 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) vol->posix_paths = 1; } else if (strnicmp(data, "noposixpaths", 12) == 0) { vol->posix_paths = 0; + } else if (strnicmp(data, "nocase", 6) == 0) { + vol->nocase = 1; + } else if (strnicmp(data, "brl", 3) == 0) { + vol->nobrl = 0; + } else if (strnicmp(data, "nobrl", 5) == 0) { + vol->nobrl = 1; } else if (strnicmp(data, "setuids", 7) == 0) { vol->setuids = 1; } else if (strnicmp(data, "nosetuids", 9) == 0) { @@ -1699,9 +1707,13 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR; if(volume_info.sfu_emul) cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL; + if(volume_info.nocase) + cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CASE_INSENS; + if(volume_info.nobrl) + cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL; if(volume_info.direct_io) { - cERROR(1,("mounting share using direct i/o")); + cFYI(1,("mounting share using direct i/o")); cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; } -- cgit v1.1 From d3485d37c0b3292aec0618b6663c57542df5da99 Mon Sep 17 00:00:00 2001 From: Steve French Date: Fri, 19 Aug 2005 11:04:29 -0700 Subject: [CIFS] Finish cifs mount option which requests case insensitive path name matching. Signed-off-by: Steve French (sfrench@us.ibm.com) --- fs/cifs/connect.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'fs/cifs/connect.c') diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 6b21f6a..ac2c8bd 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1048,6 +1048,11 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) vol->nobrl = 0; } else if (strnicmp(data, "nobrl", 5) == 0) { vol->nobrl = 1; + /* turn off mandatory locking in mode + if remote locking is turned off since the + local vfs will do advisory */ + if(vol->file_mode == (S_IALLUGO & ~(S_ISUID | S_IXGRP))) + vol->file_mode = S_IALLUGO; } else if (strnicmp(data, "setuids", 7) == 0) { vol->setuids = 1; } else if (strnicmp(data, "nosetuids", 9) == 0) { @@ -1707,8 +1712,6 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR; if(volume_info.sfu_emul) cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL; - if(volume_info.nocase) - cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CASE_INSENS; if(volume_info.nobrl) cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL; @@ -1727,6 +1730,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, 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; } else { tcon = tconInfoAlloc(); if (tcon == NULL) @@ -1755,6 +1759,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, if (!rc) { atomic_inc(&pSesInfo->inUse); tcon->retry = volume_info.retry; + tcon->nocase = volume_info.nocase; } } } -- cgit v1.1 From a10faeb2a3e266385cc334fe9af76e08e5e4330f Mon Sep 17 00:00:00 2001 From: Steve French Date: Mon, 22 Aug 2005 21:38:31 -0700 Subject: [CIFS] Support for mounting to older, pre-CIFS servers added. This allows specifying an RFC1001 target "called" name (netbios name of the server, which can now be pecified as mount option "servernetbiosname" but will eventually be passed in automatically on retry of host down error messages caused when server refuses to handle default server name and can not handle port 445). This is an important step, but additional testing and fixup is needed to add remaining function needed for these. Signed-off-by: Steve French (sfrench@us.ibm.com) --- fs/cifs/connect.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 9 deletions(-) (limited to 'fs/cifs/connect.c') diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index ac2c8bd..9d61844 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -63,6 +63,7 @@ struct smb_vol { char *in6_addr; /* ipv6 address as human readable form of in6_addr */ char *iocharset; /* local code page for mapping to and from Unicode */ char source_rfc1001_name[16]; /* netbios name of client */ + char target_rfc1001_name[16]; /* netbios name of server for Win9x/ME */ uid_t linux_uid; gid_t linux_gid; mode_t file_mode; @@ -89,7 +90,8 @@ struct smb_vol { static int ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, - char * netb_name); + char * netb_name, + char * server_netb_name); static int ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket); @@ -182,7 +184,8 @@ cifs_reconnect(struct TCP_Server_Info *server) } else { rc = ipv4_connect(&server->addr.sockAddr, &server->ssocket, - server->workstation_RFC1001_name); + server->workstation_RFC1001_name, + server->server_RFC1001_name); } if(rc) { msleep(3000); @@ -743,7 +746,9 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) toupper(system_utsname.nodename[i]); } vol->source_rfc1001_name[15] = 0; - + /* null target name indicates to use *SMBSERVR default called name + if we end up sending RFC1001 session initialize */ + vol->target_rfc1001_name[0] = 0; vol->linux_uid = current->uid; /* current->euid instead? */ vol->linux_gid = current->gid; vol->dir_mode = S_IRWXUGO; @@ -996,7 +1001,31 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) /* 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"); + printk(KERN_WARNING "CIFS: netbiosname longer than 15 truncated.\n"); + } + } else if (strnicmp(data, "servern", 7) == 0) { + /* servernetbiosname specified override *SMBSERVER */ + if (!value || !*value || (*value == ' ')) { + cFYI(1,("empty server netbiosname specified")); + } else { + /* last byte, type, is 0x20 for servr type */ + memset(vol->target_rfc1001_name,0x20,16); + + 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)? */ + + /* user or mount helper must uppercase netbiosname */ + if (value[i]==0) + break; + else + vol->target_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: server netbiosname longer than 15 truncated.\n"); } } else if (strnicmp(data, "credentials", 4) == 0) { /* ignore */ @@ -1042,7 +1071,8 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) vol->posix_paths = 1; } else if (strnicmp(data, "noposixpaths", 12) == 0) { vol->posix_paths = 0; - } else if (strnicmp(data, "nocase", 6) == 0) { + } else if ((strnicmp(data, "nocase", 6) == 0) || + (strnicmp(data, "ignorecase", 10) == 0)) { vol->nocase = 1; } else if (strnicmp(data, "brl", 3) == 0) { vol->nobrl = 0; @@ -1272,7 +1302,7 @@ static void rfc1002mangle(char * target,char * source, unsigned int length) static int ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, - char * netbios_name) + char * netbios_name, char * target_name) { int rc = 0; int connected = 0; @@ -1350,8 +1380,14 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, ses_init_buf = kcalloc(1, 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); + if(target_name && (target_name[0] != 0)) { + rfc1002mangle(ses_init_buf->trailer.session_req.called_name, + target_name, 16); + } else { + rfc1002mangle(ses_init_buf->trailer.session_req.called_name, + DEFAULT_CIFS_CALLED_NAME,16); + } + ses_init_buf->trailer.session_req.calling_len = 32; /* calling name ends in null (byte 16) from old smb convention. */ @@ -1584,7 +1620,9 @@ 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,volume_info.source_rfc1001_name); + rc = ipv4_connect(&sin_server,&csocket, + volume_info.source_rfc1001_name, + volume_info.target_rfc1001_name); if (rc < 0) { cERROR(1, ("Error connecting to IPv4 socket. Aborting operation")); @@ -1638,6 +1676,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, wait_for_completion(&cifsd_complete); rc = 0; memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16); + memcpy(srvTcp->server_RFC1001_name, volume_info.target_rfc1001_name,16); srvTcp->sequence_number = 0; } } -- cgit v1.1 From 6b8edfe0f918e7585acb3bd63f62ff56e32dd3d2 Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 23 Aug 2005 20:26:03 -0700 Subject: [CIFS] Support for mounting to older servers part 2. Add support for legacy getattr (lookup). Signed-off-by: Steve French (sfrench@us.ibm.com) --- fs/cifs/connect.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'fs/cifs/connect.c') diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 9d61844..c75bae1 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1730,8 +1730,9 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, else cifs_sb->wsize = CIFSMaxBufSize; /* default */ if(cifs_sb->rsize < PAGE_CACHE_SIZE) { - cifs_sb->rsize = PAGE_CACHE_SIZE; - cERROR(1,("Attempt to set readsize for mount to less than one page (4096)")); + cifs_sb->rsize = PAGE_CACHE_SIZE; + /* Windows ME does this */ + cFYI(1,("Attempt to set readsize for mount to less than one page (4096)")); } cifs_sb->mnt_uid = volume_info.linux_uid; cifs_sb->mnt_gid = volume_info.linux_gid; -- cgit v1.1 From 16abbecdad3367c76c12537450eba0d86943fe2c Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 30 Aug 2005 13:10:14 -0700 Subject: [CIFS] Add support for suspend cifsd had been preventing software suspend from completing. Signed-off-by: pavel@suse.de Signed-off-by: Steve French lightly modified --- fs/cifs/CHANGES | 3 ++- fs/cifs/cifsfs.c | 4 ++++ fs/cifs/connect.c | 2 ++ 3 files changed, 8 insertions(+), 1 deletions(-) --- fs/cifs/connect.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'fs/cifs/connect.c') diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index c75bae1..134195c 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -355,6 +355,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) } while (server->tcpStatus != CifsExiting) { + if(try_to_freeze()) + continue; if (bigbuf == NULL) { bigbuf = cifs_buf_get(); if(bigbuf == NULL) { -- cgit v1.1 From cb8be64084e6294fcb9e558188fe104050b94f0b Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 30 Aug 2005 15:25:52 -0700 Subject: [CIFS] Add nolock synonym (ala nfs) for nobrl to disable sending byte range locks remotely. Signed-off-by: Steve French (sfrench@us.ibm.com) --- fs/cifs/connect.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs/cifs/connect.c') diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 134195c..f784b70 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1078,7 +1078,8 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) vol->nocase = 1; } else if (strnicmp(data, "brl", 3) == 0) { vol->nobrl = 0; - } else if (strnicmp(data, "nobrl", 5) == 0) { + } else if ((strnicmp(data, "nobrl", 5) == 0) || + (strnicmp(data, "nolock", 6)) { vol->nobrl = 1; /* turn off mandatory locking in mode if remote locking is turned off since the -- cgit v1.1 From 1c9551878c4629ca78dfe12ed23b9dc8d97770cc Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 30 Aug 2005 20:58:07 -0700 Subject: [CIFS] Add support for legacy servers part 4 Fix WriteX support for old servers which do not support large files. Signed-off-by: Steve French --- fs/cifs/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/cifs/connect.c') diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index f784b70..1969760 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1079,7 +1079,7 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) } else if (strnicmp(data, "brl", 3) == 0) { vol->nobrl = 0; } else if ((strnicmp(data, "nobrl", 5) == 0) || - (strnicmp(data, "nolock", 6)) { + (strnicmp(data, "nolock", 6) == 0)) { vol->nobrl = 1; /* turn off mandatory locking in mode if remote locking is turned off since the -- cgit v1.1 From 70ca734a14366b634224a1e4586d43b36b65ab67 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 22 Sep 2005 16:32:06 -0700 Subject: [CIFS] Various minor bigendian fixes and sparse level 2 warning message fixes Most important of these fixes mapchars on bigendian and a few statfs fields Signed-off-by: Shaggy (shaggy@austin.ibm.com) Signed-off-by: Steve French (sfrench@us.ibm.com) --- fs/cifs/connect.c | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) (limited to 'fs/cifs/connect.c') diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 1969760..e27e5ad 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -303,12 +303,12 @@ static int coalesce_t2(struct smb_hdr * psecond, struct smb_hdr *pTargetSMB) byte_count += total_in_buf2; BCC_LE(pTargetSMB) = cpu_to_le16(byte_count); - byte_count = be32_to_cpu(pTargetSMB->smb_buf_length); + byte_count = pTargetSMB->smb_buf_length; byte_count += total_in_buf2; /* BB also add check that we are not beyond maximum buffer size */ - pTargetSMB->smb_buf_length = cpu_to_be32(byte_count); + pTargetSMB->smb_buf_length = byte_count; if(remaining == total_in_buf2) { cFYI(1,("found the last secondary response")); @@ -333,7 +333,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) struct cifsSesInfo *ses; struct task_struct *task_to_wake = NULL; struct mid_q_entry *mid_entry; - char *temp; + char temp; int isLargeBuf = FALSE; int isMultiRsp; int reconnect; @@ -435,22 +435,32 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) continue; } - /* the right amount was read from socket - 4 bytes */ + /* The right amount was read from socket - 4 bytes */ + /* so we can now interpret the length field */ + /* the first byte big endian of the length field, + is actually not part of the length but the type + with the most common, zero, as regular data */ + temp = *((char *) smb_buffer); + + /* Note that FC 1001 length is big endian on the wire, + but we convert it here so it is always manipulated + as host byte order */ pdu_length = ntohl(smb_buffer->smb_buf_length); - cFYI(1,("rfc1002 length(big endian)0x%x)", pdu_length+4)); + smb_buffer->smb_buf_length = pdu_length; + + cFYI(1,("rfc1002 length 0x%x)", pdu_length+4)); - temp = (char *) smb_buffer; - if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) { + if (temp == (char) RFC1002_SESSION_KEEP_ALIVE) { continue; - } else if (temp[0] == (char)RFC1002_POSITIVE_SESSION_RESPONSE) { + } else if (temp == (char)RFC1002_POSITIVE_SESSION_RESPONSE) { cFYI(1,("Good RFC 1002 session rsp")); continue; - } else if (temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) { + } else if (temp == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) { /* we get this from Windows 98 instead of an error on SMB negprot response */ cFYI(1,("Negative RFC1002 Session Response Error 0x%x)", - temp[4])); + pdu_length)); if(server->tcpStatus == CifsNew) { /* if nack on negprot (rather than ret of smb negprot error) reconnecting @@ -472,9 +482,10 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) wake_up(&server->response_q); continue; } - } else if (temp[0] != (char) 0) { + } else if (temp != (char) 0) { cERROR(1,("Unknown RFC 1002 frame")); - cifs_dump_mem(" Received Data: ", temp, length); + cifs_dump_mem(" Received Data: ", (char *)smb_buffer, + length); cifs_reconnect(server); csocket = server->ssocket; continue; @@ -609,7 +620,8 @@ multi_t2_fnd: } else if ((is_valid_oplock_break(smb_buffer) == FALSE) && (isMultiRsp == FALSE)) { cERROR(1, ("No task to wake, unknown frame rcvd!")); - cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr)); + cifs_dump_mem("Received Data is: ",(char *)smb_buffer, + sizeof(struct smb_hdr)); } } /* end while !EXITING */ -- cgit v1.1 From 3e84469d0101456caceffc6b22218a49017fcd3f Mon Sep 17 00:00:00 2001 From: Steve French Date: Mon, 3 Oct 2005 13:37:24 -0700 Subject: [CIFS] Add writepages support to shrink memory usage on writes, eliminate the double copy, and improve cifs write performance and help the server by upping the typical write size from 4K to 16K (or even larger if wsize set explicitly) for servers which support this. Part 1 of 2 Signed-off-by: Dave Kleikamp Signed-off-by: Steve French --- fs/cifs/connect.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'fs/cifs/connect.c') diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index e27e5ad..f05d9e2 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1891,6 +1891,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, } } } + if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X)) + cifs_sb->wsize = min(cifs_sb->wsize, + (tcon->ses->server->maxBuf - + MAX_CIFS_HDR_SIZE)); } /* volume_info.password is freed above when existing session found -- cgit v1.1 From 4a77118cd5018fec11bf86f6f8d659352ad9a92b Mon Sep 17 00:00:00 2001 From: Steve French Date: Wed, 5 Oct 2005 15:14:33 -0700 Subject: CIFS: Allow wsize to exceed CIFSMaxBufSize This allows cifs_writepages to send data in larger chunks from the page cache, without requiring larger memory allocations in other cases. Signed-off-by: Dave Kleikamp Signed-off-by: Steve French --- fs/cifs/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/cifs/connect.c') diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index f05d9e2..31eb9a3 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1740,7 +1740,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, cifs_sb->rsize = volume_info.rsize; else cifs_sb->rsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */ - if((volume_info.wsize) && (volume_info.wsize <= CIFSMaxBufSize)) + if(volume_info.wsize) cifs_sb->wsize = volume_info.wsize; else cifs_sb->wsize = CIFSMaxBufSize; /* default */ -- cgit v1.1 From 0ae0efada36219024e4e3008f16c993d5d091280 Mon Sep 17 00:00:00 2001 From: Steve French Date: Mon, 10 Oct 2005 10:57:19 -0700 Subject: [CIFS] Fix rsize calculation so that large readx flag is checked. Signed-off-by: Steve French (sfrench@us.ibm.com) --- fs/cifs/connect.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) (limited to 'fs/cifs/connect.c') diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 31eb9a3..d1c6ace 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include "cifspdu.h" @@ -188,6 +189,7 @@ cifs_reconnect(struct TCP_Server_Info *server) server->server_RFC1001_name); } if(rc) { + cERROR(1,("reconnect error %d",rc)); msleep(3000); } else { atomic_inc(&tcpSesReconnectCount); @@ -469,6 +471,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) } else { /* give server a second to clean up before reconnect attempt */ + cERROR(1,("sleep before reconnect")); msleep(1000); /* always try 445 first on reconnect since we get NACK on some if we ever @@ -556,6 +559,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) dump_smb(smb_buffer, length); if (checkSMB (smb_buffer, smb_buffer->Mid, total_read+4)) { cERROR(1, ("Bad SMB Received ")); + cifs_dump_mem("smb: ", smb_buffer, 48); continue; } @@ -1383,7 +1387,9 @@ 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; - + cERROR(1,("sndbuf %d rcvbuf %d reset to 200K each",(*csocket)->sk->sk_sndbuf, (*csocket)->sk->sk_rcvbuf)); + (*csocket)->sk->sk_sndbuf = 300 * 1024; + (*csocket)->sk->sk_rcvbuf = 200 * 1024; /* send RFC1001 sessinit */ if(psin_server->sin_port == htons(RFC1001_PORT)) { @@ -1736,11 +1742,20 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, /* search for existing tcon to this server share */ if (!rc) { - if((volume_info.rsize) && (volume_info.rsize <= CIFSMaxBufSize)) + if(volume_info.rsize > CIFSMaxBufSize) { + cERROR(1,("rsize %d too large, using MaxBufSize", + volume_info.rsize)); + cifs_sb->rsize = CIFSMaxBufSize; + } else if((volume_info.rsize) && (volume_info.rsize <= CIFSMaxBufSize)) cifs_sb->rsize = volume_info.rsize; - else - cifs_sb->rsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */ - if(volume_info.wsize) + else /* default */ + cifs_sb->rsize = CIFSMaxBufSize; + + if(volume_info.wsize > PAGEVEC_SIZE * PAGE_CACHE_SIZE) { + cERROR(1,("wsize %d too large using 4096 instead", + volume_info.wsize)); + cifs_sb->wsize = 4096; + } else if(volume_info.wsize) cifs_sb->wsize = volume_info.wsize; else cifs_sb->wsize = CIFSMaxBufSize; /* default */ @@ -1895,6 +1910,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, cifs_sb->wsize = min(cifs_sb->wsize, (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)); + if (!(tcon->ses->capabilities & CAP_LARGE_READ_X)) + cifs_sb->rsize = min(cifs_sb->rsize, + (tcon->ses->server->maxBuf - + MAX_CIFS_HDR_SIZE)); } /* volume_info.password is freed above when existing session found -- cgit v1.1 From b387eaeb666f6a5e24990a1f4d6a0447ae14315d Mon Sep 17 00:00:00 2001 From: Steve French Date: Mon, 10 Oct 2005 14:21:15 -0700 Subject: [CIFS] Do not shrink tcp sndbuf/rcvbuf from their defaults Signed-off-by: Steve French --- fs/cifs/connect.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'fs/cifs/connect.c') diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index d1c6ace..1772897 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -189,7 +189,7 @@ cifs_reconnect(struct TCP_Server_Info *server) server->server_RFC1001_name); } if(rc) { - cERROR(1,("reconnect error %d",rc)); + cFYI(1,("reconnect error %d",rc)); msleep(3000); } else { atomic_inc(&tcpSesReconnectCount); @@ -471,7 +471,6 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) } else { /* give server a second to clean up before reconnect attempt */ - cERROR(1,("sleep before reconnect")); msleep(1000); /* always try 445 first on reconnect since we get NACK on some if we ever @@ -558,8 +557,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) dump_smb(smb_buffer, length); if (checkSMB (smb_buffer, smb_buffer->Mid, total_read+4)) { - cERROR(1, ("Bad SMB Received ")); - cifs_dump_mem("smb: ", smb_buffer, 48); + cifs_dump_mem("Bad SMB: ", smb_buffer, 48); continue; } @@ -1386,12 +1384,16 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, /* Eventually check for other socket options to change from the default. sock_setsockopt not used because it expects user space buffer */ + cFYI(1,("sndbuf %d rcvbuf %d rcvtimeo 0x%lx",(*csocket)->sk->sk_sndbuf, + (*csocket)->sk->sk_rcvbuf, (*csocket)->sk->sk_rcvtimeo)); (*csocket)->sk->sk_rcvtimeo = 7 * HZ; - cERROR(1,("sndbuf %d rcvbuf %d reset to 200K each",(*csocket)->sk->sk_sndbuf, (*csocket)->sk->sk_rcvbuf)); - (*csocket)->sk->sk_sndbuf = 300 * 1024; - (*csocket)->sk->sk_rcvbuf = 200 * 1024; - /* send RFC1001 sessinit */ + /* make the bufsizes depend on wsize/rsize and max requests */ + if((*csocket)->sk->sk_sndbuf < (200 * 1024)) + (*csocket)->sk->sk_sndbuf = 200 * 1024; + if((*csocket)->sk->sk_rcvbuf < (140 * 1024)) + (*csocket)->sk->sk_rcvbuf = 140 * 1024; + /* send RFC1001 sessinit */ if(psin_server->sin_port == htons(RFC1001_PORT)) { /* some servers require RFC1001 sessinit before sending negprot - BB check reconnection in case where second -- cgit v1.1 From 1047abc159b4eb4ba4a7342a0969e16e9d4b4c69 Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 11 Oct 2005 19:58:06 -0700 Subject: [CIFS] CIFS Stats improvements New cifs_writepages routine was not updated bytes written in cifs stats. Also added ability to clear /proc/fs/cifs/Stats by writing (0 or 1) to it. Signed-off-by: Steve French --- fs/cifs/connect.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'fs/cifs/connect.c') diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 1772897..a8f0cbad 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -605,6 +605,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) multi_t2_fnd: task_to_wake = mid_entry->tsk; mid_entry->midState = MID_RESPONSE_RECEIVED; +#ifdef CONFIG_CIFS_STATS2 + mid_entry->when_received = jiffies; +#endif break; } } -- cgit v1.1