bk://cifs.bkbits.net/linux-2.5cifs cifs.adm@hostme.bitkeeper.com|ChangeSet|20040608174704|39536 cifs.adm # This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2004/06/07 23:01:51-05:00 stevef@smfhome1.smfdom # handle partial page update of page in cache that is not uptodate better for the situation in which file is open writeonly # # Signed-off-by: Steve French # # fs/cifs/file.c # 2004/06/07 23:01:29-05:00 stevef@smfhome1.smfdom +35 -5 # handle partial page update of page in cache that is not uptodate better for the situation in which file is open writeonly # # ChangeSet # 2004/06/07 22:13:21-05:00 stevef@smfhome1.smfdom # Make stats display more consistent - under /proc/fs/cifs/Stats # # Signed-off-by: Steve French # # fs/cifs/cifs_debug.c # 2004/06/07 22:13:15-05:00 stevef@smfhome1.smfdom +63 -33 # Make stats display more consistent - under /proc/fs/cifs/Stats # # fs/cifs/CHANGES # 2004/06/07 22:13:15-05:00 stevef@smfhome1.smfdom +2 -1 # Update cifs change log for 1.17c # # ChangeSet # 2004/06/07 18:02:58-05:00 stevef@stevef95.austin.ibm.com # fix up whitespace # # Signed-off-by: Steve French # # fs/cifs/file.c # 2004/06/07 18:02:50-05:00 stevef@stevef95.austin.ibm.com +17 -17 # fix up whitespace # # ChangeSet # 2004/06/07 17:14:26-05:00 stevef@stevef95.austin.ibm.com # Add 2 missing kmalloc failure checks during cifs mount time # # Signed-off-by: Yury Umanets # Signed-off-by: Steve French # # fs/cifs/connect.c # 2004/06/07 17:14:18-05:00 stevef@stevef95.austin.ibm.com +4 -0 # Add 2 missing kmalloc failure checks during cifs mount time # # fs/cifs/AUTHORS # 2004/06/07 17:14:18-05:00 stevef@stevef95.austin.ibm.com +1 -0 # Update list of contributors # # ChangeSet # 2004/06/07 14:00:04-07:00 akpm@bix.(none) # Merge bk://cifs.bkbits.net/linux-2.5cifs # into bix.(none):/usr/src/bk-cifs # # fs/cifs/cifssmb.c # 2004/06/07 14:00:00-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/06/07 15:33:40-05:00 stevef@stevef95.austin.ibm.com # Fix race in updating tcpStatus field # # fs/cifs/connect.c # 2004/06/07 15:33:32-05:00 stevef@stevef95.austin.ibm.com +38 -10 # Fix race in updating tcpStatus field # # fs/cifs/cifssmb.c # 2004/06/07 15:33:32-05:00 stevef@stevef95.austin.ibm.com +4 -1 # Fix race in updating tcpStatus field # # fs/cifs/CHANGES # 2004/06/07 15:33:32-05:00 stevef@stevef95.austin.ibm.com +2 -0 # update change list for cifs 1.17a # # fs/cifs/AUTHORS # 2004/06/07 15:33:31-05:00 stevef@stevef95.austin.ibm.com +2 -0 # Update list of bug reporters # # ChangeSet # 2004/06/03 17:29:27-05:00 stevef@stevef95.austin.ibm.com # whitespace and comment cleanup # # Signed-off-by: Steve French (sfrench@us.ibm.com) # # fs/cifs/transport.c # 2004/06/03 17:29:17-05:00 stevef@stevef95.austin.ibm.com +0 -1 # remove obsolete comment # # fs/cifs/connect.c # 2004/06/03 17:29:17-05:00 stevef@stevef95.austin.ibm.com +1 -1 # fix whitespace # # fs/cifs/AUTHORS # 2004/06/03 17:29:17-05:00 stevef@stevef95.austin.ibm.com +1 -1 # update bug report contributors # # ChangeSet # 2004/06/02 13:18:48-07:00 akpm@bix.(none) # Merge bk://cifs.bkbits.net/linux-2.5cifs # into bix.(none):/usr/src/bk-cifs # # fs/cifs/cifssmb.c # 2004/06/02 13:18:44-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/06/02 00:04:52-05:00 stevef@steveft21.ltcsamba # Merge bk://cifs.bkbits.net/linux-2.5cifs # into steveft21.ltcsamba:/usr/src/bk/linux-2.5cifs # # fs/cifs/fcntl.c # 2004/06/02 00:04:29-05:00 stevef@steveft21.ltcsamba +0 -0 # Auto merged # # fs/cifs/cifssmb.c # 2004/06/02 00:04:24-05:00 stevef@steveft21.ltcsamba +0 -0 # Auto merged # # fs/cifs/cifspdu.h # 2004/06/02 00:04:23-05:00 stevef@steveft21.ltcsamba +0 -0 # Auto merged # # ChangeSet # 2004/06/01 23:44:42-05:00 stevef@steveft21.ltcsamba # Initial protocol definitions for cifs dirnotify (directory change notification) support # # Signed-off-by: Steve French # # fs/cifs/fcntl.c # 2004/06/01 23:44:15-05:00 stevef@steveft21.ltcsamba +17 -1 # cifs dirnotify (directory change notification) support # # fs/cifs/cifssmb.c # 2004/06/01 23:44:15-05:00 stevef@steveft21.ltcsamba +50 -2 # cifs dirnotify (directory change notification) support, and fix minor big endian bug on QuerySymLink (windows style query) # # fs/cifs/cifsproto.h # 2004/06/01 23:44:15-05:00 stevef@steveft21.ltcsamba +3 -0 # cifs dirnotify (directory change notification) support # # fs/cifs/cifspdu.h # 2004/06/01 23:44:14-05:00 stevef@steveft21.ltcsamba +37 -17 # cifs dirnotify (directory change notification) support # # ChangeSet # 2004/05/31 20:01:23-05:00 stevef@smfhome1.smfdom # Handle out of memory on allocating dentry or inode during filldir # # fs/cifs/file.c # 2004/05/31 20:01:17-05:00 stevef@smfhome1.smfdom +11 -1 # Handle out of memory on allocating dentry or inode during filldir # # ChangeSet # 2004/05/31 19:23:23-05:00 stevef@smfhome1.smfdom # Update cifs change log for cifs 1.17 # # fs/cifs/CHANGES # 2004/05/31 19:23:17-05:00 stevef@smfhome1.smfdom +6 -0 # Update cifs change log for cifs 1.17 # # ChangeSet # 2004/05/31 19:19:47-05:00 stevef@smfhome1.smfdom # Remove temporary debug message # # fs/cifs/file.c # 2004/05/31 19:19:41-05:00 stevef@smfhome1.smfdom +4 -1 # Remove temporary debug message # # ChangeSet # 2004/05/31 19:16:30-05:00 stevef@smfhome1.smfdom # No matter what the blocksize, we are required to use fake blocksize of 512 when calculating # number of blocks in a file (otherwise this confuses the du command) # # fs/cifs/inode.c # 2004/05/31 19:16:24-05:00 stevef@smfhome1.smfdom +16 -4 # No matter what the blocksize, we are required to use fake blocksize of 512 when calculating # number of blocks in a file (otherwise this confuses the du command) # # fs/cifs/file.c # 2004/05/31 19:16:24-05:00 stevef@smfhome1.smfdom +9 -4 # No matter what the blocksize, we are required to use fake blocksize of 512 when calculating # number of blocks in a file (otherwise this confuses the du command) # # ChangeSet # 2004/05/31 17:31:11-05:00 stevef@smfhome1.smfdom # cifs_prepare_write fixes to remove problem in which we were not populating page data from the server copy when writing to non-uptodate page # # fs/cifs/file.c # 2004/05/31 17:27:25-05:00 stevef@smfhome1.smfdom +62 -32 # Fix cifs_prepare_write for most cases in which page is not up to date. Put readable open file instances at beginning of our open file list, so we can use them in populating file data in partial page write # # fs/cifs/dir.c # 2004/05/31 17:27:25-05:00 stevef@smfhome1.smfdom +16 -5 # put readable open file instances at beginning of our open file list, so we can use them in populating file data in partial page write (part 1) # # fs/cifs/cifsfs.h # 2004/05/31 17:27:25-05:00 stevef@smfhome1.smfdom +1 -1 # put readable open file instances at beginning of our open file list, so we can use them in populating file data in partial page write # # ChangeSet # 2004/05/27 21:24:47-07:00 akpm@bix.(none) # Merge bk://cifs.bkbits.net/linux-2.5cifs # into bix.(none):/usr/src/bk-cifs # # fs/cifs/cifssmb.c # 2004/05/27 21:24:44-07:00 akpm@bix.(none) +0 -0 # Auto merged # # fs/cifs/cifsfs.c # 2004/05/27 21:24:43-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/27 12:36:56-07:00 akpm@bix.(none) # Merge bk://cifs.bkbits.net/linux-2.5cifs # into bix.(none):/usr/src/bk-cifs # # fs/cifs/cifssmb.c # 2004/05/27 12:36:53-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/25 21:18:56-07:00 akpm@bix.(none) # Merge bk://cifs.bkbits.net/linux-2.5cifs # into bix.(none):/usr/src/bk-cifs # # fs/cifs/cifssmb.c # 2004/05/25 21:18:53-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/24 18:04:01-07:00 akpm@bix.(none) # Merge bk://cifs.bkbits.net/linux-2.5cifs # into bix.(none):/usr/src/bk-cifs # # fs/cifs/cifssmb.c # 2004/05/24 18:03:57-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/22 23:28:34-07:00 akpm@bix.(none) # Merge bk://cifs.bkbits.net/linux-2.5cifs # into bix.(none):/usr/src/bk-cifs # # fs/cifs/cifssmb.c # 2004/05/22 23:28:31-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/18 14:31:25-07:00 akpm@bix.(none) # Merge bk://cifs.bkbits.net/linux-2.5cifs # into bix.(none):/usr/src/bk-cifs # # fs/cifs/cifsfs.c # 2004/05/18 14:31:22-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/11 16:37:09-07:00 akpm@bix.(none) # Merge bk://cifs.bkbits.net/linux-2.5cifs # into bix.(none):/usr/src/bk-cifs # # fs/cifs/cifssmb.c # 2004/05/11 16:37:06-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/04 13:51:19-07:00 akpm@bix.(none) # Merge bk://cifs.bkbits.net/linux-2.5cifs # into bix.(none):/usr/src/bk-cifs # # fs/cifs/cifssmb.c # 2004/05/04 13:51:17-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/02 21:56:11-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-cifs # # fs/cifs/cifssmb.c # 2004/05/02 21:56:09-07:00 akpm@bix.(none) +0 -0 # Auto merged # # fs/cifs/cifsfs.c # 2004/05/02 21:56:08-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/01 15:05:17-07:00 akpm@bix.(none) # Merge bk://cifs.bkbits.net/linux-2.5cifs # into bix.(none):/usr/src/bk-cifs # # fs/cifs/cifssmb.c # 2004/05/01 15:05:14-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/04/29 15:41:50-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-cifs # # fs/cifs/cifssmb.c # 2004/04/29 15:41:48-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/04/26 18:11:55-07:00 akpm@bix.(none) # Merge bk://cifs.bkbits.net/linux-2.5cifs # into bix.(none):/usr/src/bk-cifs # # fs/cifs/cifsfs.c # 2004/04/26 18:11:52-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/04/23 12:36:52-07:00 akpm@bix.(none) # Merge bk://cifs.bkbits.net/linux-2.5cifs # into bix.(none):/usr/src/bk-cifs # # fs/cifs/cifsfs.c # 2004/04/23 12:36:49-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/04/19 19:23:58-07:00 akpm@bix.(none) # Merge bk://cifs.bkbits.net/linux-2.5cifs # into bix.(none):/usr/src/bk-cifs # # fs/cifs/cifsfs.c # 2004/04/19 19:23:56-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/04/16 20:19:53-07:00 akpm@bix.(none) # Merge bk://cifs.bkbits.net/linux-2.5cifs # into bix.(none):/usr/src/bk-cifs # # fs/cifs/cifsfs.c # 2004/04/16 20:19:51-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/04/16 20:18:59-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-cifs # # fs/cifs/cifsfs.c # 2004/04/16 20:18:56-07:00 akpm@bix.(none) +0 -0 # Auto merged # diff -Nru a/fs/cifs/AUTHORS b/fs/cifs/AUTHORS --- a/fs/cifs/AUTHORS 2004-06-08 21:37:36 -07:00 +++ b/fs/cifs/AUTHORS 2004-06-08 21:37:36 -07:00 @@ -23,6 +23,7 @@ Shobhit Dayal Sergey Vlasov Richard Hughes +Yury Umanets Test case and Bug Report contributors ------------------------------------- @@ -30,5 +31,7 @@ and debug of problems they have found: Jochen Dolze, David Blaine, Rene Scharfe, Martin Josefsson, Alexander Wild, Anthony Liguori, 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. diff -Nru a/fs/cifs/CHANGES b/fs/cifs/CHANGES --- a/fs/cifs/CHANGES 2004-06-08 21:37:36 -07:00 +++ b/fs/cifs/CHANGES 2004-06-08 21:37:36 -07:00 @@ -1,3 +1,12 @@ +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 ------------ Fix incorrect file size in file handle based setattr on big endian hardware. diff -Nru a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c --- a/fs/cifs/cifs_debug.c 2004-06-08 21:37:36 -07:00 +++ b/fs/cifs/cifs_debug.c 2004-06-08 21:37:36 -07:00 @@ -142,30 +142,10 @@ sprintf(buf, " type: %d ", tcon->fsDevInfo.DeviceType); buf += length; - if(tcon->tidStatus == CifsNeedReconnect) + if(tcon->tidStatus == CifsNeedReconnect) { buf += sprintf(buf, "\tDISCONNECTED "); -#ifdef CONFIG_CIFS_STATS - 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 - + length += 14; + } } read_unlock(&GlobalSMBSeslock); @@ -200,32 +180,80 @@ return length; } +#ifdef CONFIG_CIFS_STATS int cifs_stats_read(char *buf, char **beginBuffer, off_t offset, int length, int *eof, void *data) { - int item_length; - length = - sprintf(buf, - "Currently Allocated structures\nCIFS Sessions: %d\n",sesInfoAllocCount.counter); + int item_length,i; + struct list_head *tmp; + struct cifsTconInfo *tcon; + + length = sprintf(buf, + "Currently Allocated structures\nCIFS Sessions: %d\n", + sesInfoAllocCount.counter); buf += 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; buf += 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; buf += 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; 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; + 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; } +#endif struct proc_dir_entry *proc_fs_cifs; read_proc_t cifs_txanchor_read; @@ -265,10 +293,10 @@ create_proc_read_entry("SimultaneousOps", 0, proc_fs_cifs, cifs_total_xid_read, 0); - +#ifdef CONFIG_CIFS_STATS create_proc_read_entry("Stats", 0, proc_fs_cifs, cifs_stats_read, 0); - +#endif pde = create_proc_read_entry("cifsFYI", 0, proc_fs_cifs, cifsFYI_read, 0); if (pde) @@ -336,7 +364,9 @@ remove_proc_entry("cifsFYI", proc_fs_cifs); remove_proc_entry("traceSMB", proc_fs_cifs); remove_proc_entry("SimultaneousOps", proc_fs_cifs); +#ifdef CONFIG_CIFS_STATS remove_proc_entry("Stats", proc_fs_cifs); +#endif remove_proc_entry("MultiuserMount", proc_fs_cifs); remove_proc_entry("OplockEnabled", proc_fs_cifs); remove_proc_entry("NTLMV2Enabled",proc_fs_cifs); diff -Nru a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h --- a/fs/cifs/cifsfs.h 2004-06-08 21:37:36 -07:00 +++ b/fs/cifs/cifsfs.h 2004-06-08 21:37:36 -07:00 @@ -93,5 +93,5 @@ size_t, int); extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, 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 */ diff -Nru a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h --- a/fs/cifs/cifspdu.h 2004-06-08 21:37:36 -07:00 +++ b/fs/cifs/cifspdu.h 2004-06-08 21:37:36 -07:00 @@ -862,6 +862,10 @@ __u16 ByteCount; /* bct = 0 */ } CREATE_DIRECTORY_RSP; +/***************************************************/ +/* NT Transact structure defintions follow */ +/* Currently only ioctl and notify are implemented */ +/***************************************************/ typedef struct smb_com_transaction_ioctl_req { struct smb_hdr hdr; /* wct = 23 */ __u8 MaxSetupCount; @@ -904,29 +908,45 @@ } TRANSACT_IOCTL_RSP; typedef struct smb_com_transaction_change_notify_req { - struct smb_hdr hdr; /* wct = 23 */ - __u8 MaxSetupCount; - __u16 Reserved; - __u32 TotalParameterCount; - __u32 TotalDataCount; - __u32 MaxParameterCount; - __u32 MaxDataCount; - __u32 ParameterCount; - __u32 ParameterOffset; - __u32 DataCount; - __u32 DataOffset; - __u8 SetupCount; /* four setup words follow subcommand */ - /* SNIA spec incorrectly included spurious pad here */ - __u16 SubCommand;/* 4 = Change Notify */ + struct smb_hdr hdr; /* wct = 23 */ + __u8 MaxSetupCount; + __u16 Reserved; + __u32 TotalParameterCount; + __u32 TotalDataCount; + __u32 MaxParameterCount; + __u32 MaxDataCount; + __u32 ParameterCount; + __u32 ParameterOffset; + __u32 DataCount; + __u32 DataOffset; + __u8 SetupCount; /* four setup words follow subcommand */ + /* SNIA spec incorrectly included spurious pad here */ + __u16 SubCommand;/* 4 = Change Notify */ __u32 CompletionFilter; /* operation to monitor */ __u16 Fid; __u8 WatchTree; /* 1 = Monitor subdirectories */ + __u8 Reserved2; __u16 ByteCount; - __u8 Pad[3]; - __u8 Data[1]; +/* __u8 Pad[3];*/ +/* __u8 Data[1];*/ } 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_DIR_NAME 0x00000002 #define FILE_NOTIFY_CHANGE_NAME 0x00000003 diff -Nru a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h --- a/fs/cifs/cifsproto.h 2004-06-08 21:37:36 -07:00 +++ b/fs/cifs/cifsproto.h 2004-06-08 21:37:36 -07:00 @@ -244,4 +244,7 @@ const __u16 target_tid, const char *toName, const int flags, 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 */ diff -Nru a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c --- a/fs/cifs/cifssmb.c 2004-06-08 21:37:36 -07:00 +++ b/fs/cifs/cifssmb.c 2004-06-08 21:37:36 -07:00 @@ -383,8 +383,11 @@ smb_buffer_response, &length, 0); if (ses->server) { 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; + spin_unlock(&GlobalMid_Lock); + } } if (pSMB) cifs_buf_release(pSMB); @@ -1464,9 +1467,9 @@ pSMB->TotalParameterCount = 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 */ - pSMB->MaxDataCount = cpu_to_le16(4000); + pSMB->MaxDataCount = cpu_to_le32(4000); pSMB->MaxSetupCount = 4; pSMB->Reserved = 0; pSMB->ParameterOffset = 0; @@ -2827,4 +2830,52 @@ if (rc == -EAGAIN) goto setPermsRetry; 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; } diff -Nru a/fs/cifs/connect.c b/fs/cifs/connect.c --- a/fs/cifs/connect.c 2004-06-08 21:37:36 -07:00 +++ b/fs/cifs/connect.c 2004-06-08 21:37:36 -07:00 @@ -95,9 +95,15 @@ struct cifsTconInfo *tcon; 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; - server->tcpStatus = CifsNeedReconnect; + } else + server->tcpStatus = CifsNeedReconnect; + spin_unlock(&GlobalMid_Lock); server->maxBuf = 0; cFYI(1, ("Reconnecting tcp session ")); @@ -164,7 +170,10 @@ schedule_timeout(3 * HZ); } else { 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); wake_up(&server->response_q); } @@ -243,12 +252,14 @@ /* some servers kill tcp session rather than returning smb negprot error in which case reconnecting here is not going to help - return error to mount */ + spin_lock(&GlobalMid_Lock); server->tcpStatus = CifsExiting; + spin_unlock(&GlobalMid_Lock); wake_up(&server->response_q); break; } - cFYI(1,("Reconnecting after unexpected rcvmsg error ")); + cFYI(1,("Reconnecting after unexpected peek error %d",length)); cifs_reconnect(server); csocket = server->ssocket; wake_up(&server->response_q); @@ -280,7 +291,9 @@ /* if nack on negprot (rather than ret of smb negprot error) reconnecting not going to help, ret error to mount */ + spin_lock(&GlobalMid_Lock); server->tcpStatus = CifsExiting; + spin_unlock(&GlobalMid_Lock); /* wake up thread doing negprot */ wake_up(&server->response_q); break; @@ -391,7 +404,9 @@ } } } + spin_lock(&GlobalMid_Lock); server->tcpStatus = CifsExiting; + spin_unlock(&GlobalMid_Lock); atomic_set(&server->inFlight, 0); /* Although there should not be any requests blocked on this queue it can not hurt to be paranoid and try to wake up requests @@ -595,6 +610,8 @@ } if ((temp_len = strnlen(value, 300)) < 300) { vol->UNC = kmalloc(temp_len+1,GFP_KERNEL); + if(vol->UNC == NULL) + return 1; strcpy(vol->UNC,value); if (strncmp(vol->UNC, "//", 2) == 0) { vol->UNC[0] = '\\'; @@ -742,6 +759,8 @@ } if ((temp_len = strnlen(devname, 300)) < 300) { vol->UNC = kmalloc(temp_len+1,GFP_KERNEL); + if(vol->UNC == NULL) + return 1; strcpy(vol->UNC,devname); if (strncmp(vol->UNC, "//", 2) == 0) { vol->UNC[0] = '\\'; @@ -1030,7 +1049,7 @@ } else { /* BB other socket options to set KEEPALIVE, NODELAY? */ cFYI(1,("ipv6 Socket created")); - (*csocket)->sk->sk_allocation = GFP_NOFS; + (*csocket)->sk->sk_allocation = GFP_NOFS; } } @@ -1226,6 +1245,9 @@ init_waitqueue_head(&srvTcp->response_q); init_waitqueue_head(&srvTcp->request_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; init_MUTEX(&srvTcp->tcpSem); kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp, @@ -1342,9 +1364,12 @@ /* on error free sesinfo and tcon struct if needed */ if (rc) { - if(atomic_read(&srvTcp->socketUseCount) == 0) - srvTcp->tcpStatus = CifsExiting; - /* If find_unc succeeded then rc == 0 so we can not end */ + if(atomic_read(&srvTcp->socketUseCount) == 0) { + spin_lock(&GlobalMid_Lock); + 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 */ tconInfoFree(tcon); if (existingCifsSes == 0) { @@ -2791,7 +2816,7 @@ char ntlm_session_key[CIFS_SESSION_KEY_SIZE]; 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 */ { rc = CIFSSMBNegotiate(xid, pSesInfo); if(rc == -EAGAIN) /* retry only once on 1st time connection */ { @@ -2799,8 +2824,15 @@ if(rc == -EAGAIN) rc = -EHOSTDOWN; } - if(rc == 0) - pSesInfo->server->tcpStatus = CifsGood; + if(rc == 0) { + spin_lock(&GlobalMid_Lock); + if(pSesInfo->server->tcpStatus != CifsExiting) + pSesInfo->server->tcpStatus = CifsGood; + else + rc = -EHOSTDOWN; + spin_unlock(&GlobalMid_Lock); + + } } if (!rc) { pSesInfo->capabilities = pSesInfo->server->capabilities; diff -Nru a/fs/cifs/dir.c b/fs/cifs/dir.c --- a/fs/cifs/dir.c 2004-06-08 21:37:36 -07:00 +++ b/fs/cifs/dir.c 2004-06-08 21:37:36 -07:00 @@ -159,6 +159,7 @@ struct cifsFileInfo * pCifsFile = NULL; struct cifsInodeInfo * pCifsInode; int disposition = FILE_OVERWRITE_IF; + int write_only = FALSE; xid = GetXid(); @@ -176,9 +177,10 @@ if(nd) { if ((nd->intent.open.flags & O_ACCMODE) == O_RDONLY) 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; - 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 */ /* can cause unnecessary access denied on create */ /* desiredAccess = GENERIC_ALL; */ @@ -262,16 +264,25 @@ pCifsFile->invalidHandle = FALSE; pCifsFile->closePend = FALSE; 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); list_add(&pCifsFile->tlist,&pTcon->openFileList); pCifsInode = CIFS_I(newinode); 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) { pCifsInode->clientCanCacheAll = 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) pCifsInode->clientCanCacheRead = TRUE; } diff -Nru a/fs/cifs/fcntl.c b/fs/cifs/fcntl.c --- a/fs/cifs/fcntl.c 2004-06-08 21:37:36 -07:00 +++ b/fs/cifs/fcntl.c 2004-06-08 21:37:36 -07:00 @@ -32,9 +32,12 @@ { int xid; int rc = -EINVAL; + int oplock = FALSE; struct cifs_sb_info *cifs_sb; struct cifsTconInfo *pTcon; char *full_path = NULL; + __u32 filter = FILE_NOTIFY_CHANGE_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES; + __u16 netfid; xid = GetXid(); cifs_sb = CIFS_SB(file->f_dentry->d_sb); @@ -48,7 +51,20 @@ rc = -ENOMEM; } else { 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); diff -Nru a/fs/cifs/file.c b/fs/cifs/file.c --- a/fs/cifs/file.c 2004-06-08 21:37:36 -07:00 +++ b/fs/cifs/file.c 2004-06-08 21:37:36 -07:00 @@ -173,7 +173,14 @@ list_add(&pCifsFile->tlist,&pTcon->openFileList); pCifsInode = CIFS_I(file->f_dentry->d_inode); if(pCifsInode) { - list_add(&pCifsFile->flist,&pCifsInode->openFileList); + /* want handles we can use to read with first */ + /* in the list so we do not have to walk the */ + /* list to search for one in prepare_write */ + if ((file->f_flags & O_ACCMODE) == O_WRONLY) { + list_add_tail(&pCifsFile->flist,&pCifsInode->openFileList); + } else { + list_add(&pCifsFile->flist,&pCifsInode->openFileList); + } write_unlock(&GlobalSMBSeslock); write_unlock(&file->f_owner.lock); if(pCifsInode->clientCanCacheRead) { @@ -701,6 +708,7 @@ cifsInode = CIFS_I(mapping->host); read_lock(&GlobalSMBSeslock); + /* BB we should start at the end */ list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) { open_file = list_entry(tmp,struct cifsFileInfo, flist); if(open_file->closePend) @@ -770,6 +778,9 @@ xid = GetXid(); /* BB add check for wbc flags */ page_cache_get(page); + if (!PageUptodate(page)) { + cFYI(1,("ppw - page not up to date")); + } rc = cifs_partialpagewrite(page,0,PAGE_CACHE_SIZE); SetPageUptodate(page); /* BB add check for error and Clearuptodate? */ @@ -787,8 +798,7 @@ int rc = 0; struct inode *inode = page->mapping->host; loff_t position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to; - /* struct cifsFileInfo *open_file; - struct cifs_sb_info *cifs_sb; */ + char * page_data; xid = GetXid(); cFYI(1,("commit write for page %p up to position %lld for %d",page,position,to)); @@ -819,7 +829,31 @@ cFYI(1,(" SetEOF (commit write) rc = %d",rc)); }*/ } - set_page_dirty(page); + if (!PageUptodate(page)) { + position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + offset; + /* can not rely on (or let) writepage write this data */ + if(to < offset) { + cFYI(1,("Illegal offsets, can not copy from %d to %d", + offset,to)); + FreeXid(xid); + return rc; + } + /* this is probably better than directly calling + partialpage_write since in this function + the file handle is known which we might as well + leverage */ + /* BB check if anything else missing out of ppw */ + /* such as updating last write time */ + page_data = kmap(page); + rc = cifs_write(file, page_data+offset,to-offset, + &position); + if(rc > 0) + rc = 0; + /* else if rc < 0 should we set writebehind rc? */ + kunmap(page); + } else { + set_page_dirty(page); + } FreeXid(xid); return rc; @@ -924,6 +958,10 @@ } open_file = (struct cifsFileInfo *)file->private_data; + if((file->f_flags & O_ACCMODE) == O_WRONLY) { + cFYI(1,("attempting read on write only file instance")); + } + for (total_read = 0,current_offset=read_data; read_size > total_read; total_read += bytes_read,current_offset+=bytes_read) { current_read_size = min_t(const int,read_size - total_read,cifs_sb->rsize); @@ -1169,49 +1207,58 @@ return rc; } -static int -cifs_readpage(struct file *file, struct page *page) +static int cifs_readpage_worker(struct file *file, struct page *page, loff_t * poffset) { - loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT; char * read_data; - int rc = -EACCES; - int xid; - - xid = GetXid(); - - if (file->private_data == NULL) { - FreeXid(xid); - return -EBADF; - } - - cFYI(0,("readpage %p at offset %d 0x%x\n",page,(int)offset,(int)offset)); + int rc; page_cache_get(page); read_data = kmap(page); /* for reads over a certain size could initiate async read ahead */ - - rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, &offset); - + + rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, poffset); + if (rc < 0) goto io_error; else { cFYI(1,("Bytes read %d ",rc)); } - + file->f_dentry->d_inode->i_atime = CURRENT_TIME; - + if(PAGE_CACHE_SIZE > rc) { memset(read_data+rc, 0, PAGE_CACHE_SIZE - rc); } flush_dcache_page(page); SetPageUptodate(page); rc = 0; - + io_error: - kunmap(page); + kunmap(page); + page_cache_release(page); + return rc; +} + +static int +cifs_readpage(struct file *file, struct page *page) +{ + loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT; + int rc = -EACCES; + int xid; + + xid = GetXid(); + + if (file->private_data == NULL) { + FreeXid(xid); + return -EBADF; + } + + cFYI(1,("readpage %p at offset %d 0x%x\n",page,(int)offset,(int)offset)); + + rc = cifs_readpage_worker(file,page,&offset); + unlock_page(page); - page_cache_release(page); FreeXid(xid); return rc; } @@ -1276,8 +1323,11 @@ } i_size_write(tmp_inode,pfindData->EndOfFile); - tmp_inode->i_blocks = - (tmp_inode->i_blksize - 1 + pfindData->AllocationSize) >> tmp_inode->i_blkbits; + + /* 512 bytes (2**9) is the fake blocksize that must be used */ + /* for this calculation, even though the reported blocksize is larger */ + tmp_inode->i_blocks = (512 - 1 + pfindData->AllocationSize) >> 9; + if (pfindData->AllocationSize < pfindData->EndOfFile) cFYI(1, ("Possible sparse file: allocation size less than end of file ")); cFYI(1, @@ -1350,8 +1400,10 @@ pfindData->NumOfBytes = le64_to_cpu(pfindData->NumOfBytes); pfindData->EndOfFile = le64_to_cpu(pfindData->EndOfFile); i_size_write(tmp_inode,pfindData->EndOfFile); - tmp_inode->i_blocks = - (tmp_inode->i_blksize - 1 + pfindData->NumOfBytes) >> tmp_inode->i_blkbits; + + /* 512 bytes (2**9) is the fake blocksize that must be used */ + /* for this calculation, not the real blocksize */ + tmp_inode->i_blocks = (512 - 1 + pfindData->NumOfBytes) >> 9; if (S_ISREG(tmp_inode->i_mode)) { cFYI(1, ("File inode")); @@ -1393,12 +1445,15 @@ /* BB overwrite the old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len ?? */ if(*ptmp_inode == NULL) { *ptmp_inode = new_inode(file->f_dentry->d_sb); + if(*ptmp_inode == NULL) + return; d_instantiate(tmp_dentry, *ptmp_inode); } } else { tmp_dentry = d_alloc(file->f_dentry, qstring); if(tmp_dentry == NULL) { cERROR(1,("Failed allocating dentry")); + *ptmp_inode = NULL; return; } @@ -1406,6 +1461,8 @@ tmp_dentry->d_op = &cifs_dentry_ops; cFYI(0, (" instantiate dentry 0x%p with inode 0x%p ", tmp_dentry, *ptmp_inode)); + if(*ptmp_inode == NULL) + return; d_instantiate(tmp_dentry, *ptmp_inode); d_rehash(tmp_dentry); } @@ -1462,7 +1519,9 @@ pqstring->len = pfindData->FileNameLength; construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry); - + if((tmp_inode == NULL) || (tmp_dentry == NULL)) { + return -ENOMEM; + } fill_in_inode(tmp_inode, pfindData, &object_type); rc = filldir(direntry, pfindData->FileName, pqstring->len, file->f_pos, tmp_inode->i_ino, object_type); @@ -1488,6 +1547,9 @@ pqstring->len = strnlen(pUnixFindData->FileName, MAX_PATHCONF); construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry); + if((tmp_inode == NULL) || (tmp_dentry == NULL)) { + return -ENOMEM; + } unix_fill_in_inode(tmp_inode, pUnixFindData, &object_type); rc = filldir(direntry, pUnixFindData->FileName, pqstring->len, @@ -1950,17 +2012,34 @@ int cifs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to) { + int rc = 0; + loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT; cFYI(1,("prepare write for page %p from %d to %d",page,from,to)); if (!PageUptodate(page)) { - if (to - from != PAGE_CACHE_SIZE) { + /* if (to - from != PAGE_CACHE_SIZE) { void *kaddr = kmap_atomic(page, KM_USER0); memset(kaddr, 0, from); memset(kaddr + to, 0, PAGE_CACHE_SIZE - to); flush_dcache_page(page); kunmap_atomic(kaddr, KM_USER0); + } */ + /* If we are writing a full page it will be up to date, + no need to read from the server */ + if((to==PAGE_CACHE_SIZE) && (from == 0)) + SetPageUptodate(page); + + /* might as well read a page, it is fast enough */ + if((file->f_flags & O_ACCMODE) != O_WRONLY) { + rc = cifs_readpage_worker(file,page,&offset); + } else { + /* should we try using another + file handle if there is one - how would we lock it + to prevent close of that handle racing with this read? */ + /* In any case this will be written out by commit_write */ } - SetPageUptodate(page); } + + /* BB should we pass any errors back? e.g. if we do not have read access to the file */ return 0; } @@ -1969,8 +2048,7 @@ .readpage = cifs_readpage, .readpages = cifs_readpages, .writepage = cifs_writepage, - .prepare_write = simple_prepare_write, /* BB fixme BB */ -/* .prepare_write = cifs_prepare_write, */ /* BB removeme BB */ + .prepare_write = cifs_prepare_write, .commit_write = cifs_commit_write, /* .sync_page = cifs_sync_page, */ /*.direct_IO = */ diff -Nru a/fs/cifs/inode.c b/fs/cifs/inode.c --- a/fs/cifs/inode.c 2004-06-08 21:37:36 -07:00 +++ b/fs/cifs/inode.c 2004-06-08 21:37:36 -07:00 @@ -130,8 +130,18 @@ and blkbits set in superblock so 2**blkbits and blksize will match */ /* inode->i_blksize = (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) cFYI(1, ("Server inconsistency Error: it says allocation size less than end of file ")); @@ -275,8 +285,10 @@ } i_size_write(inode,le64_to_cpu(pfindData->EndOfFile)); 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); diff -Nru a/fs/cifs/transport.c b/fs/cifs/transport.c --- a/fs/cifs/transport.c 2004-06-08 21:37:36 -07:00 +++ b/fs/cifs/transport.c 2004-06-08 21:37:36 -07:00 @@ -126,7 +126,6 @@ if(ssocket == NULL) return -ENOTSOCK; /* BB eventually add reconnect code here */ -/* ssocket->sk->allocation = GFP_BUFFER; *//* BB is this spurious? */ iov.iov_base = smb_buffer; iov.iov_len = smb_buf_length + 4;