Commit 754d4c9b authored by Linus Torvalds's avatar Linus Torvalds

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

into ppc970.osdl.org:/home/torvalds/v2.6/linux
parents b8611623 ce0025eb
...@@ -23,6 +23,7 @@ Amrut Joshi ...@@ -23,6 +23,7 @@ Amrut Joshi
Shobhit Dayal Shobhit Dayal
Sergey Vlasov Sergey Vlasov
Richard Hughes Richard Hughes
Yury Umanets
Test case and Bug Report contributors Test case and Bug Report contributors
------------------------------------- -------------------------------------
...@@ -30,5 +31,7 @@ Thanks to those in the community who have submitted detailed bug reports ...@@ -30,5 +31,7 @@ Thanks to those in the community who have submitted detailed bug reports
and debug of problems they have found: Jochen Dolze, David Blaine, and debug of problems they have found: Jochen Dolze, David Blaine,
Rene Scharfe, Martin Josefsson, Alexander Wild, Anthony Liguori, Rene Scharfe, Martin Josefsson, Alexander Wild, Anthony Liguori,
Lars Muller, Urban Widmark, Massimiliano Ferrero, Howard Owen, Lars Muller, Urban Widmark, Massimiliano Ferrero, Howard Owen,
Kieron Briggs and others. Olaf Kirch, Kieron Briggs and others.
And thanks to the IBM LTC and Power test teams and SuSE testers for
finding multiple bugs during excellent stress test runs.
Version 1.17
------------
Update number of blocks in file so du command is happier (in Linux a fake
blocksize of 512 is required for calculating number of blocks in inode).
Fix prepare write of partial pages to read in data from server if possible.
Fix race on tcpStatus field between unmount and reconnection code, causing
cifsd process sometimes to hang around forever. Improve out of memory
checks in cifs_filldir
Version 1.16 Version 1.16
------------ ------------
Fix incorrect file size in file handle based setattr on big endian hardware. Fix incorrect file size in file handle based setattr on big endian hardware.
......
...@@ -142,30 +142,10 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, ...@@ -142,30 +142,10 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
sprintf(buf, " type: %d ", sprintf(buf, " type: %d ",
tcon->fsDevInfo.DeviceType); tcon->fsDevInfo.DeviceType);
buf += length; buf += length;
if(tcon->tidStatus == CifsNeedReconnect) if(tcon->tidStatus == CifsNeedReconnect) {
buf += sprintf(buf, "\tDISCONNECTED "); buf += sprintf(buf, "\tDISCONNECTED ");
#ifdef CONFIG_CIFS_STATS length += 14;
length = sprintf(buf,"\nSMBs: %d Oplock Breaks: %d", }
atomic_read(&tcon->num_smbs_sent),
atomic_read(&tcon->num_oplock_brks));
buf += length;
length = sprintf(buf,"\nReads: %d Bytes %lld",
atomic_read(&tcon->num_reads),
(long long)(tcon->bytes_read));
buf += length;
length = sprintf(buf,"\nWrites: %d Bytes: %lld",
atomic_read(&tcon->num_writes),
(long long)(tcon->bytes_written));
buf += length;
length = sprintf(buf,
"\nOpens: %d Deletes: %d\nMkdirs: %d Rmdirs: %d",
atomic_read(&tcon->num_opens),
atomic_read(&tcon->num_deletes),
atomic_read(&tcon->num_mkdirs),
atomic_read(&tcon->num_rmdirs));
buf += length;
#endif
} }
read_unlock(&GlobalSMBSeslock); read_unlock(&GlobalSMBSeslock);
...@@ -200,32 +180,80 @@ cifs_total_xid_read(char *buf, char **beginBuffer, off_t offset, ...@@ -200,32 +180,80 @@ cifs_total_xid_read(char *buf, char **beginBuffer, off_t offset,
return length; return length;
} }
#ifdef CONFIG_CIFS_STATS
int int
cifs_stats_read(char *buf, char **beginBuffer, off_t offset, cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
int length, int *eof, void *data) int length, int *eof, void *data)
{ {
int item_length; int item_length,i;
length = struct list_head *tmp;
sprintf(buf, struct cifsTconInfo *tcon;
"Currently Allocated structures\nCIFS Sessions: %d\n",sesInfoAllocCount.counter);
length = sprintf(buf,
"Currently Allocated structures\nCIFS Sessions: %d\n",
sesInfoAllocCount.counter);
buf += length; buf += length;
item_length = item_length =
sprintf(buf,"Shares (unique mount targets): %d\n",tconInfoAllocCount.counter); sprintf(buf,"Shares (unique mount targets): %d\n",
tconInfoAllocCount.counter);
length += item_length; length += item_length;
buf += item_length; buf += item_length;
item_length = item_length =
sprintf(buf,"Allocated SMB Request and Response Buffers: %d\n",bufAllocCount.counter); sprintf(buf,"Allocated SMB Request/Response Buffers: %d\n",
bufAllocCount.counter);
length += item_length; length += item_length;
buf += item_length; buf += item_length;
item_length = item_length =
sprintf(buf,"Active Operations (MIDs in use): %d\n",midCount.counter); sprintf(buf,"Active Operations (MIDs in use): %d\n",
midCount.counter);
length += item_length; length += item_length;
buf += item_length; buf += item_length;
item_length = sprintf(buf,"%d sessions and %d shares reconnected after failure\n",tcpSesReconnectCount.counter,tconInfoReconnectCount.counter); item_length = sprintf(buf,
"%d sessions and %d shares reconnected after failure\n",
tcpSesReconnectCount.counter,tconInfoReconnectCount.counter);
length += item_length; length += item_length;
buf += item_length;
i = 0;
read_lock(&GlobalSMBSeslock);
list_for_each(tmp, &GlobalTreeConnectionList) {
i++;
tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
item_length = sprintf(buf,"\n%d) %s",i, tcon->treeName);
buf += item_length;
length += item_length;
if(tcon->tidStatus == CifsNeedReconnect) {
buf += sprintf(buf, "\tDISCONNECTED ");
length += 14;
}
item_length = sprintf(buf,"\nSMBs: %d Oplock Breaks: %d",
atomic_read(&tcon->num_smbs_sent),
atomic_read(&tcon->num_oplock_brks));
buf += item_length;
length += item_length;
item_length = sprintf(buf,"\nReads: %d Bytes %lld",
atomic_read(&tcon->num_reads),
(long long)(tcon->bytes_read));
buf += item_length;
item_length = sprintf(buf,"\nWrites: %d Bytes: %lld",
atomic_read(&tcon->num_writes),
(long long)(tcon->bytes_written));
buf += item_length;
item_length = sprintf(buf,
"\nOpens: %d Deletes: %d\nMkdirs: %d Rmdirs: %d",
atomic_read(&tcon->num_opens),
atomic_read(&tcon->num_deletes),
atomic_read(&tcon->num_mkdirs),
atomic_read(&tcon->num_rmdirs));
buf += item_length;
length += item_length;
}
read_unlock(&GlobalSMBSeslock);
return length; return length;
} }
#endif
struct proc_dir_entry *proc_fs_cifs; struct proc_dir_entry *proc_fs_cifs;
read_proc_t cifs_txanchor_read; read_proc_t cifs_txanchor_read;
...@@ -265,10 +293,10 @@ cifs_proc_init(void) ...@@ -265,10 +293,10 @@ cifs_proc_init(void)
create_proc_read_entry("SimultaneousOps", 0, proc_fs_cifs, create_proc_read_entry("SimultaneousOps", 0, proc_fs_cifs,
cifs_total_xid_read, 0); cifs_total_xid_read, 0);
#ifdef CONFIG_CIFS_STATS
create_proc_read_entry("Stats", 0, proc_fs_cifs, create_proc_read_entry("Stats", 0, proc_fs_cifs,
cifs_stats_read, 0); cifs_stats_read, 0);
#endif
pde = create_proc_read_entry("cifsFYI", 0, proc_fs_cifs, pde = create_proc_read_entry("cifsFYI", 0, proc_fs_cifs,
cifsFYI_read, 0); cifsFYI_read, 0);
if (pde) if (pde)
...@@ -336,7 +364,9 @@ cifs_proc_clean(void) ...@@ -336,7 +364,9 @@ cifs_proc_clean(void)
remove_proc_entry("cifsFYI", proc_fs_cifs); remove_proc_entry("cifsFYI", proc_fs_cifs);
remove_proc_entry("traceSMB", proc_fs_cifs); remove_proc_entry("traceSMB", proc_fs_cifs);
remove_proc_entry("SimultaneousOps", proc_fs_cifs); remove_proc_entry("SimultaneousOps", proc_fs_cifs);
#ifdef CONFIG_CIFS_STATS
remove_proc_entry("Stats", proc_fs_cifs); remove_proc_entry("Stats", proc_fs_cifs);
#endif
remove_proc_entry("MultiuserMount", proc_fs_cifs); remove_proc_entry("MultiuserMount", proc_fs_cifs);
remove_proc_entry("OplockEnabled", proc_fs_cifs); remove_proc_entry("OplockEnabled", proc_fs_cifs);
remove_proc_entry("NTLMV2Enabled",proc_fs_cifs); remove_proc_entry("NTLMV2Enabled",proc_fs_cifs);
......
...@@ -93,5 +93,5 @@ extern int cifs_setxattr(struct dentry *, const char *, const void *, ...@@ -93,5 +93,5 @@ extern int cifs_setxattr(struct dentry *, const char *, const void *,
size_t, int); size_t, int);
extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
#define CIFS_VERSION "1.16" #define CIFS_VERSION "1.17"
#endif /* _CIFSFS_H */ #endif /* _CIFSFS_H */
...@@ -862,6 +862,10 @@ typedef struct smb_com_create_directory_rsp { ...@@ -862,6 +862,10 @@ typedef struct smb_com_create_directory_rsp {
__u16 ByteCount; /* bct = 0 */ __u16 ByteCount; /* bct = 0 */
} CREATE_DIRECTORY_RSP; } CREATE_DIRECTORY_RSP;
/***************************************************/
/* NT Transact structure defintions follow */
/* Currently only ioctl and notify are implemented */
/***************************************************/
typedef struct smb_com_transaction_ioctl_req { typedef struct smb_com_transaction_ioctl_req {
struct smb_hdr hdr; /* wct = 23 */ struct smb_hdr hdr; /* wct = 23 */
__u8 MaxSetupCount; __u8 MaxSetupCount;
...@@ -904,29 +908,45 @@ typedef struct smb_com_transaction_ioctl_rsp { ...@@ -904,29 +908,45 @@ typedef struct smb_com_transaction_ioctl_rsp {
} TRANSACT_IOCTL_RSP; } TRANSACT_IOCTL_RSP;
typedef struct smb_com_transaction_change_notify_req { typedef struct smb_com_transaction_change_notify_req {
struct smb_hdr hdr; /* wct = 23 */ struct smb_hdr hdr; /* wct = 23 */
__u8 MaxSetupCount; __u8 MaxSetupCount;
__u16 Reserved; __u16 Reserved;
__u32 TotalParameterCount; __u32 TotalParameterCount;
__u32 TotalDataCount; __u32 TotalDataCount;
__u32 MaxParameterCount; __u32 MaxParameterCount;
__u32 MaxDataCount; __u32 MaxDataCount;
__u32 ParameterCount; __u32 ParameterCount;
__u32 ParameterOffset; __u32 ParameterOffset;
__u32 DataCount; __u32 DataCount;
__u32 DataOffset; __u32 DataOffset;
__u8 SetupCount; /* four setup words follow subcommand */ __u8 SetupCount; /* four setup words follow subcommand */
/* SNIA spec incorrectly included spurious pad here */ /* SNIA spec incorrectly included spurious pad here */
__u16 SubCommand;/* 4 = Change Notify */ __u16 SubCommand;/* 4 = Change Notify */
__u32 CompletionFilter; /* operation to monitor */ __u32 CompletionFilter; /* operation to monitor */
__u16 Fid; __u16 Fid;
__u8 WatchTree; /* 1 = Monitor subdirectories */ __u8 WatchTree; /* 1 = Monitor subdirectories */
__u8 Reserved2;
__u16 ByteCount; __u16 ByteCount;
__u8 Pad[3]; /* __u8 Pad[3];*/
__u8 Data[1]; /* __u8 Data[1];*/
} TRANSACT_CHANGE_NOTIFY_REQ; } TRANSACT_CHANGE_NOTIFY_REQ;
/* Completion Filter flags */ typedef struct smb_com_transaction_change_notify_rsp {
struct smb_hdr hdr; /* wct = 18 */
__u8 Reserved[3];
__u32 TotalParameterCount;
__u32 TotalDataCount;
__u32 ParameterCount;
__u32 ParameterOffset;
__u32 ParameterDisplacement;
__u32 DataCount;
__u32 DataOffset;
__u32 DataDisplacement;
__u8 SetupCount; /* 0 */
__u16 ByteCount;
/* __u8 Pad[3]; */
} TRANSACT_CHANGE_NOTIFY_RSP;
/* Completion Filter flags for Notify */
#define FILE_NOTIFY_CHANGE_FILE_NAME 0x00000001 #define FILE_NOTIFY_CHANGE_FILE_NAME 0x00000001
#define FILE_NOTIFY_CHANGE_DIR_NAME 0x00000002 #define FILE_NOTIFY_CHANGE_DIR_NAME 0x00000002
#define FILE_NOTIFY_CHANGE_NAME 0x00000003 #define FILE_NOTIFY_CHANGE_NAME 0x00000003
......
...@@ -244,4 +244,7 @@ extern int CIFSSMBCopy(int xid, ...@@ -244,4 +244,7 @@ extern int CIFSSMBCopy(int xid,
const __u16 target_tid, const __u16 target_tid,
const char *toName, const int flags, const char *toName, const int flags,
const struct nls_table *nls_codepage); const struct nls_table *nls_codepage);
extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
const int notify_subdirs,const __u16 netfid,__u32 filter,
const struct nls_table *nls_codepage);
#endif /* _CIFSPROTO_H */ #endif /* _CIFSPROTO_H */
...@@ -383,8 +383,11 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses) ...@@ -383,8 +383,11 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
smb_buffer_response, &length, 0); smb_buffer_response, &length, 0);
if (ses->server) { if (ses->server) {
atomic_dec(&ses->server->socketUseCount); atomic_dec(&ses->server->socketUseCount);
if (atomic_read(&ses->server->socketUseCount) == 0) if (atomic_read(&ses->server->socketUseCount) == 0) {
spin_lock(&GlobalMid_Lock);
ses->server->tcpStatus = CifsExiting; ses->server->tcpStatus = CifsExiting;
spin_unlock(&GlobalMid_Lock);
}
} }
if (pSMB) if (pSMB)
cifs_buf_release(pSMB); cifs_buf_release(pSMB);
...@@ -1464,9 +1467,9 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, ...@@ -1464,9 +1467,9 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
pSMB->TotalParameterCount = 0 ; pSMB->TotalParameterCount = 0 ;
pSMB->TotalDataCount = 0; pSMB->TotalDataCount = 0;
pSMB->MaxParameterCount = cpu_to_le16(2); pSMB->MaxParameterCount = cpu_to_le32(2);
/* BB find exact data count max from sess structure BB */ /* BB find exact data count max from sess structure BB */
pSMB->MaxDataCount = cpu_to_le16(4000); pSMB->MaxDataCount = cpu_to_le32(4000);
pSMB->MaxSetupCount = 4; pSMB->MaxSetupCount = 4;
pSMB->Reserved = 0; pSMB->Reserved = 0;
pSMB->ParameterOffset = 0; pSMB->ParameterOffset = 0;
...@@ -2828,3 +2831,51 @@ CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon, ...@@ -2828,3 +2831,51 @@ CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
goto setPermsRetry; goto setPermsRetry;
return rc; return rc;
} }
int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
const int notify_subdirs, const __u16 netfid,
__u32 filter, const struct nls_table *nls_codepage)
{
int rc = 0;
struct smb_com_transaction_change_notify_req * pSMB = NULL;
struct smb_com_transaction_change_notify_rsp * pSMBr = NULL;
int bytes_returned;
cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
(void **) &pSMBr);
if (rc)
return rc;
pSMB->TotalParameterCount = 0 ;
pSMB->TotalDataCount = 0;
pSMB->MaxParameterCount = cpu_to_le32(2);
/* BB find exact data count max from sess structure BB */
pSMB->MaxDataCount = 0; /* same in little endian or be */
pSMB->MaxSetupCount = 4;
pSMB->Reserved = 0;
pSMB->ParameterOffset = 0;
pSMB->DataCount = 0;
pSMB->DataOffset = 0;
pSMB->SetupCount = 4; /* single byte does not need le conversion */
pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
pSMB->ParameterCount = pSMB->TotalParameterCount;
if(notify_subdirs)
pSMB->WatchTree = 1; /* one byte - no le conversion needed */
pSMB->Reserved2 = 0;
pSMB->CompletionFilter = cpu_to_le32(filter);
pSMB->Fid = netfid; /* file handle always le */
pSMB->ByteCount = 0;
pSMB->hdr.smb_buf_length += pSMB->ByteCount;
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
cFYI(1, ("Error in Notify = %d", rc));
}
if (pSMB)
cifs_buf_release(pSMB);
/* if (rc == -EAGAIN)
goto NotifyRetry; */
return rc;
}
...@@ -95,9 +95,15 @@ cifs_reconnect(struct TCP_Server_Info *server) ...@@ -95,9 +95,15 @@ cifs_reconnect(struct TCP_Server_Info *server)
struct cifsTconInfo *tcon; struct cifsTconInfo *tcon;
struct mid_q_entry * mid_entry; struct mid_q_entry * mid_entry;
if(server->tcpStatus == CifsExiting) spin_lock(&GlobalMid_Lock);
if(server->tcpStatus == CifsExiting) {
/* the demux thread will exit normally
next time through the loop */
spin_unlock(&GlobalMid_Lock);
return rc; return rc;
server->tcpStatus = CifsNeedReconnect; } else
server->tcpStatus = CifsNeedReconnect;
spin_unlock(&GlobalMid_Lock);
server->maxBuf = 0; server->maxBuf = 0;
cFYI(1, ("Reconnecting tcp session ")); cFYI(1, ("Reconnecting tcp session "));
...@@ -164,7 +170,10 @@ cifs_reconnect(struct TCP_Server_Info *server) ...@@ -164,7 +170,10 @@ cifs_reconnect(struct TCP_Server_Info *server)
schedule_timeout(3 * HZ); schedule_timeout(3 * HZ);
} else { } else {
atomic_inc(&tcpSesReconnectCount); atomic_inc(&tcpSesReconnectCount);
server->tcpStatus = CifsGood; spin_lock(&GlobalMid_Lock);
if(server->tcpStatus != CifsExiting)
server->tcpStatus = CifsGood;
spin_unlock(&GlobalMid_Lock);
atomic_set(&server->inFlight,0); atomic_set(&server->inFlight,0);
wake_up(&server->response_q); wake_up(&server->response_q);
} }
...@@ -243,12 +252,14 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -243,12 +252,14 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
/* some servers kill tcp session rather than returning /* some servers kill tcp session rather than returning
smb negprot error in which case reconnecting here is smb negprot error in which case reconnecting here is
not going to help - return error to mount */ not going to help - return error to mount */
spin_lock(&GlobalMid_Lock);
server->tcpStatus = CifsExiting; server->tcpStatus = CifsExiting;
spin_unlock(&GlobalMid_Lock);
wake_up(&server->response_q); wake_up(&server->response_q);
break; break;
} }
cFYI(1,("Reconnecting after unexpected rcvmsg error ")); cFYI(1,("Reconnecting after unexpected peek error %d",length));
cifs_reconnect(server); cifs_reconnect(server);
csocket = server->ssocket; csocket = server->ssocket;
wake_up(&server->response_q); wake_up(&server->response_q);
...@@ -280,7 +291,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -280,7 +291,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
/* if nack on negprot (rather than /* if nack on negprot (rather than
ret of smb negprot error) reconnecting ret of smb negprot error) reconnecting
not going to help, ret error to mount */ not going to help, ret error to mount */
spin_lock(&GlobalMid_Lock);
server->tcpStatus = CifsExiting; server->tcpStatus = CifsExiting;
spin_unlock(&GlobalMid_Lock);
/* wake up thread doing negprot */ /* wake up thread doing negprot */
wake_up(&server->response_q); wake_up(&server->response_q);
break; break;
...@@ -391,7 +404,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -391,7 +404,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
} }
} }
} }
spin_lock(&GlobalMid_Lock);
server->tcpStatus = CifsExiting; server->tcpStatus = CifsExiting;
spin_unlock(&GlobalMid_Lock);
atomic_set(&server->inFlight, 0); atomic_set(&server->inFlight, 0);
/* Although there should not be any requests blocked on /* Although there should not be any requests blocked on
this queue it can not hurt to be paranoid and try to wake up requests this queue it can not hurt to be paranoid and try to wake up requests
...@@ -595,6 +610,8 @@ cifs_parse_mount_options(char *options, const char *devname, struct smb_vol *vol ...@@ -595,6 +610,8 @@ cifs_parse_mount_options(char *options, const char *devname, struct smb_vol *vol
} }
if ((temp_len = strnlen(value, 300)) < 300) { if ((temp_len = strnlen(value, 300)) < 300) {
vol->UNC = kmalloc(temp_len+1,GFP_KERNEL); vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
if(vol->UNC == NULL)
return 1;
strcpy(vol->UNC,value); strcpy(vol->UNC,value);
if (strncmp(vol->UNC, "//", 2) == 0) { if (strncmp(vol->UNC, "//", 2) == 0) {
vol->UNC[0] = '\\'; vol->UNC[0] = '\\';
...@@ -742,6 +759,8 @@ cifs_parse_mount_options(char *options, const char *devname, struct smb_vol *vol ...@@ -742,6 +759,8 @@ cifs_parse_mount_options(char *options, const char *devname, struct smb_vol *vol
} }
if ((temp_len = strnlen(devname, 300)) < 300) { if ((temp_len = strnlen(devname, 300)) < 300) {
vol->UNC = kmalloc(temp_len+1,GFP_KERNEL); vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
if(vol->UNC == NULL)
return 1;
strcpy(vol->UNC,devname); strcpy(vol->UNC,devname);
if (strncmp(vol->UNC, "//", 2) == 0) { if (strncmp(vol->UNC, "//", 2) == 0) {
vol->UNC[0] = '\\'; vol->UNC[0] = '\\';
...@@ -1030,7 +1049,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket) ...@@ -1030,7 +1049,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
} else { } else {
/* BB other socket options to set KEEPALIVE, NODELAY? */ /* BB other socket options to set KEEPALIVE, NODELAY? */
cFYI(1,("ipv6 Socket created")); cFYI(1,("ipv6 Socket created"));
(*csocket)->sk->sk_allocation = GFP_NOFS; (*csocket)->sk->sk_allocation = GFP_NOFS;
} }
} }
...@@ -1226,6 +1245,9 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, ...@@ -1226,6 +1245,9 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
init_waitqueue_head(&srvTcp->response_q); init_waitqueue_head(&srvTcp->response_q);
init_waitqueue_head(&srvTcp->request_q); init_waitqueue_head(&srvTcp->request_q);
INIT_LIST_HEAD(&srvTcp->pending_mid_q); INIT_LIST_HEAD(&srvTcp->pending_mid_q);
/* at this point we are the only ones with the pointer
to the struct since the kernel thread not created yet
so no need to spinlock this init of tcpStatus */
srvTcp->tcpStatus = CifsNew; srvTcp->tcpStatus = CifsNew;
init_MUTEX(&srvTcp->tcpSem); init_MUTEX(&srvTcp->tcpSem);
kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp, kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
...@@ -1342,9 +1364,12 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, ...@@ -1342,9 +1364,12 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
/* on error free sesinfo and tcon struct if needed */ /* on error free sesinfo and tcon struct if needed */
if (rc) { if (rc) {
if(atomic_read(&srvTcp->socketUseCount) == 0) if(atomic_read(&srvTcp->socketUseCount) == 0) {
srvTcp->tcpStatus = CifsExiting; spin_lock(&GlobalMid_Lock);
/* If find_unc succeeded then rc == 0 so we can not end */ srvTcp->tcpStatus = CifsExiting;
spin_unlock(&GlobalMid_Lock);
}
/* If find_unc succeeded then rc == 0 so we can not end */
if (tcon) /* up here accidently freeing someone elses tcon struct */ if (tcon) /* up here accidently freeing someone elses tcon struct */
tconInfoFree(tcon); tconInfoFree(tcon);
if (existingCifsSes == 0) { if (existingCifsSes == 0) {
...@@ -2791,7 +2816,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, ...@@ -2791,7 +2816,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
char ntlm_session_key[CIFS_SESSION_KEY_SIZE]; char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
int ntlmv2_flag = FALSE; int ntlmv2_flag = FALSE;
/* what if server changes its buffer size after dropping the session? */ /* what if server changes its buffer size after dropping the session? */
if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ { if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
rc = CIFSSMBNegotiate(xid, pSesInfo); rc = CIFSSMBNegotiate(xid, pSesInfo);
if(rc == -EAGAIN) /* retry only once on 1st time connection */ { if(rc == -EAGAIN) /* retry only once on 1st time connection */ {
...@@ -2799,8 +2824,15 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, ...@@ -2799,8 +2824,15 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
if(rc == -EAGAIN) if(rc == -EAGAIN)
rc = -EHOSTDOWN; rc = -EHOSTDOWN;
} }
if(rc == 0) if(rc == 0) {
pSesInfo->server->tcpStatus = CifsGood; spin_lock(&GlobalMid_Lock);
if(pSesInfo->server->tcpStatus != CifsExiting)
pSesInfo->server->tcpStatus = CifsGood;
else
rc = -EHOSTDOWN;
spin_unlock(&GlobalMid_Lock);
}
} }
if (!rc) { if (!rc) {
pSesInfo->capabilities = pSesInfo->server->capabilities; pSesInfo->capabilities = pSesInfo->server->capabilities;
......
...@@ -159,6 +159,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -159,6 +159,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
struct cifsFileInfo * pCifsFile = NULL; struct cifsFileInfo * pCifsFile = NULL;
struct cifsInodeInfo * pCifsInode; struct cifsInodeInfo * pCifsInode;
int disposition = FILE_OVERWRITE_IF; int disposition = FILE_OVERWRITE_IF;
int write_only = FALSE;
xid = GetXid(); xid = GetXid();
...@@ -176,9 +177,10 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -176,9 +177,10 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
if(nd) { if(nd) {
if ((nd->intent.open.flags & O_ACCMODE) == O_RDONLY) if ((nd->intent.open.flags & O_ACCMODE) == O_RDONLY)
desiredAccess = GENERIC_READ; desiredAccess = GENERIC_READ;
else if ((nd->intent.open.flags & O_ACCMODE) == O_WRONLY) else if ((nd->intent.open.flags & O_ACCMODE) == O_WRONLY) {
desiredAccess = GENERIC_WRITE; desiredAccess = GENERIC_WRITE;
else if ((nd->intent.open.flags & O_ACCMODE) == O_RDWR) { write_only = TRUE;
} else if ((nd->intent.open.flags & O_ACCMODE) == O_RDWR) {
/* GENERIC_ALL is too much permission to request */ /* GENERIC_ALL is too much permission to request */
/* can cause unnecessary access denied on create */ /* can cause unnecessary access denied on create */
/* desiredAccess = GENERIC_ALL; */ /* desiredAccess = GENERIC_ALL; */
...@@ -262,16 +264,25 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -262,16 +264,25 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
pCifsFile->invalidHandle = FALSE; pCifsFile->invalidHandle = FALSE;
pCifsFile->closePend = FALSE; pCifsFile->closePend = FALSE;
init_MUTEX(&pCifsFile->fh_sem); init_MUTEX(&pCifsFile->fh_sem);
/* pCifsFile->pfile = file; */ /* put in at open time */ /* put the following in at open now */
/* pCifsFile->pfile = file; */
write_lock(&GlobalSMBSeslock); write_lock(&GlobalSMBSeslock);
list_add(&pCifsFile->tlist,&pTcon->openFileList); list_add(&pCifsFile->tlist,&pTcon->openFileList);
pCifsInode = CIFS_I(newinode); pCifsInode = CIFS_I(newinode);
if(pCifsInode) { if(pCifsInode) {
list_add(&pCifsFile->flist,&pCifsInode->openFileList); /* if readable file instance put first in list*/
if (write_only == TRUE) {
list_add_tail(&pCifsFile->flist,
&pCifsInode->openFileList);
} else {
list_add(&pCifsFile->flist,
&pCifsInode->openFileList);
}
if((oplock & 0xF) == OPLOCK_EXCLUSIVE) { if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
pCifsInode->clientCanCacheAll = TRUE; pCifsInode->clientCanCacheAll = TRUE;
pCifsInode->clientCanCacheRead = TRUE; pCifsInode->clientCanCacheRead = TRUE;
cFYI(1,("Exclusive Oplock granted on inode %p",newinode)); cFYI(1,("Exclusive Oplock granted on inode %p",
newinode));
} else if((oplock & 0xF) == OPLOCK_READ) } else if((oplock & 0xF) == OPLOCK_READ)
pCifsInode->clientCanCacheRead = TRUE; pCifsInode->clientCanCacheRead = TRUE;
} }
......
...@@ -32,9 +32,12 @@ int cifs_directory_notify(unsigned long arg, struct file * file) ...@@ -32,9 +32,12 @@ int cifs_directory_notify(unsigned long arg, struct file * file)
{ {
int xid; int xid;
int rc = -EINVAL; int rc = -EINVAL;
int oplock = FALSE;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
char *full_path = NULL; char *full_path = NULL;
__u32 filter = FILE_NOTIFY_CHANGE_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES;
__u16 netfid;
xid = GetXid(); xid = GetXid();
cifs_sb = CIFS_SB(file->f_dentry->d_sb); cifs_sb = CIFS_SB(file->f_dentry->d_sb);
...@@ -48,7 +51,20 @@ int cifs_directory_notify(unsigned long arg, struct file * file) ...@@ -48,7 +51,20 @@ int cifs_directory_notify(unsigned long arg, struct file * file)
rc = -ENOMEM; rc = -ENOMEM;
} else { } else {
cFYI(1,("cifs dir notify on file %s",full_path)); cFYI(1,("cifs dir notify on file %s",full_path));
/* CIFSSMBNotify(xid, pTcon, full_path, cifs_sb->local_nls);*/ rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
GENERIC_READ | SYNCHRONIZE, 0 /* create options */,
&netfid, &oplock,NULL, cifs_sb->local_nls);
/* BB fixme - add this handle to a notify handle list */
if(rc) {
cFYI(1,("Could not open directory for notify"));
} else {
rc = CIFSSMBNotify(xid, pTcon, 1 /* subdirs */, netfid,
filter, cifs_sb->local_nls);
/* BB add code to close file eventually (at unmount
it would close automatically but may be a way
to do it easily when inode freed or when
notify info is cleared/changed */
}
} }
FreeXid(xid); FreeXid(xid);
......
This diff is collapsed.
...@@ -130,8 +130,18 @@ cifs_get_inode_info_unix(struct inode **pinode, ...@@ -130,8 +130,18 @@ cifs_get_inode_info_unix(struct inode **pinode,
and blkbits set in superblock so 2**blkbits and blksize will match */ and blkbits set in superblock so 2**blkbits and blksize will match */
/* inode->i_blksize = /* inode->i_blksize =
(pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/ (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
inode->i_blocks =
(inode->i_blksize - 1 + findData.NumOfBytes) >> inode->i_blkbits; /* This seems incredibly stupid but it turns out that
i_blocks is not related to (i_size / i_blksize), instead a
size of 512 is required to be used for calculating num blocks */
/* inode->i_blocks =
(inode->i_blksize - 1 + findData.NumOfBytes) >> inode->i_blkbits;*/
/* 512 bytes (2**9) is the fake blocksize that must be used */
/* for this calculation */
inode->i_blocks = (512 - 1 + findData.NumOfBytes) >> 9;
if (findData.NumOfBytes < findData.EndOfFile) if (findData.NumOfBytes < findData.EndOfFile)
cFYI(1, ("Server inconsistency Error: it says allocation size less than end of file ")); cFYI(1, ("Server inconsistency Error: it says allocation size less than end of file "));
...@@ -275,8 +285,10 @@ cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path, ...@@ -275,8 +285,10 @@ cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path,
} }
i_size_write(inode,le64_to_cpu(pfindData->EndOfFile)); i_size_write(inode,le64_to_cpu(pfindData->EndOfFile));
pfindData->AllocationSize = le64_to_cpu(pfindData->AllocationSize); pfindData->AllocationSize = le64_to_cpu(pfindData->AllocationSize);
inode->i_blocks =
(inode->i_blksize - 1 + pfindData->AllocationSize) >> inode->i_blkbits; /* 512 bytes (2**9) is the fake blocksize that must be used */
/* for this calculation */
inode->i_blocks = (512 - 1 + pfindData->AllocationSize) >> 9;
inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks); inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks);
......
...@@ -126,7 +126,6 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer, ...@@ -126,7 +126,6 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
if(ssocket == NULL) if(ssocket == NULL)
return -ENOTSOCK; /* BB eventually add reconnect code here */ return -ENOTSOCK; /* BB eventually add reconnect code here */
/* ssocket->sk->allocation = GFP_BUFFER; *//* BB is this spurious? */
iov.iov_base = smb_buffer; iov.iov_base = smb_buffer;
iov.iov_len = smb_buf_length + 4; iov.iov_len = smb_buf_length + 4;
......
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