bk://cifs.bkbits.net/linux-2.5cifs stevef@steveft21.ltcsamba|ChangeSet|20040602050452|42494 stevef # This is a BitKeeper generated diff -Nru style patch. # # 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/CHANGES b/fs/cifs/CHANGES --- a/fs/cifs/CHANGES 2004-06-02 23:35:26 -07:00 +++ b/fs/cifs/CHANGES 2004-06-02 23:35:26 -07:00 @@ -1,3 +1,9 @@ +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. + Version 1.16 ------------ Fix incorrect file size in file handle based setattr on big endian hardware. diff -Nru a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h --- a/fs/cifs/cifsfs.h 2004-06-02 23:35:26 -07:00 +++ b/fs/cifs/cifsfs.h 2004-06-02 23:35:26 -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-02 23:35:26 -07:00 +++ b/fs/cifs/cifspdu.h 2004-06-02 23:35:26 -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-02 23:35:26 -07:00 +++ b/fs/cifs/cifsproto.h 2004-06-02 23:35:26 -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-02 23:35:26 -07:00 +++ b/fs/cifs/cifssmb.c 2004-06-02 23:35:26 -07:00 @@ -1464,9 +1464,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 +2827,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/dir.c b/fs/cifs/dir.c --- a/fs/cifs/dir.c 2004-06-02 23:35:26 -07:00 +++ b/fs/cifs/dir.c 2004-06-02 23:35:26 -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-02 23:35:26 -07:00 +++ b/fs/cifs/fcntl.c 2004-06-02 23:35:26 -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-02 23:35:26 -07:00 +++ b/fs/cifs/file.c 2004-06-02 23:35:26 -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) { @@ -924,6 +931,11 @@ } 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,11 +1181,42 @@ return rc; } +static int cifs_readpage_worker(struct file *file, struct page *page, loff_t * poffset) +{ + char * read_data; + 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, 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); + 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; - char * read_data; int rc = -EACCES; int xid; @@ -1184,34 +1227,12 @@ return -EBADF; } - cFYI(0,("readpage %p at offset %d 0x%x\n",page,(int)offset,(int)offset)); - - 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); - - if (rc < 0) - goto io_error; - else { - cFYI(1,("Bytes read %d ",rc)); - } - - file->f_dentry->d_inode->i_atime = CURRENT_TIME; + cFYI(1,("readpage %p at offset %d 0x%x\n",page,(int)offset,(int)offset)); - if(PAGE_CACHE_SIZE > rc) { - memset(read_data+rc, 0, PAGE_CACHE_SIZE - rc); - } - flush_dcache_page(page); - SetPageUptodate(page); - rc = 0; + rc = cifs_readpage_worker(file,page,&offset); -io_error: - kunmap(page); unlock_page(page); - page_cache_release(page); FreeXid(xid); return rc; } @@ -1276,8 +1297,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 +1374,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 +1419,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 +1435,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 +1493,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 +1521,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 +1986,30 @@ 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); - } - SetPageUptodate(page); + } */ + /* 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 */ + rc = cifs_readpage_worker(file,page,&offset); + /* if this returns an error 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? */ } + + /* BB should we pass any errors back? e.g. if we do not have read access to the file */ return 0; } @@ -1969,8 +2018,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-02 23:35:26 -07:00 +++ b/fs/cifs/inode.c 2004-06-02 23:35:26 -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);