Commit dc70efa7 authored by Steve French's avatar Steve French Committed by Steve French

Fix blocksize and allocation size miscalculation

parent 7dbb0435
Version 0.87
------------
Fix oops on big endian readdir. Set blksize to be even power of two (2**blkbits) to fix
allocation size miscalculation. After oplock token lost do not read through
cache.
Version 0.86
------------
Fix oops on empty file readahead. Fix for file size handling for locally cached files.
Version 0.85
------------
Fix oops in mkdir when server fails to return inode info. Fix oops in reopen_files
......
......@@ -90,10 +90,10 @@ cifs_read_super(struct super_block *sb, void *data,
sb->s_magic = CIFS_MAGIC_NUMBER;
sb->s_op = &cifs_super_ops;
if(cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512)
sb->s_blocksize = cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE;
else
sb->s_blocksize = CIFSMaximumBufferSize;
/* if(cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512)
sb->s_blocksize = cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; */
sb->s_blocksize = CIFS_MAX_MSGSIZE;
sb->s_blocksize_bits = 14; /* default 2**14 = CIFS_MAX_MSGSIZE */
inode = iget(sb, ROOT_I);
......@@ -282,6 +282,27 @@ cifs_get_sb(struct file_system_type *fs_type,
return sb;
}
ssize_t
cifs_read_wrapper(struct file * file, char *read_data, size_t read_size,
loff_t * poffset)
{
if(CIFS_I(file->f_dentry->d_inode)->clientCanCacheRead)
return generic_file_read(file,read_data,read_size,poffset);
else
return cifs_read(file,read_data,read_size,poffset);
}
ssize_t
cifs_write_wrapper(struct file * file, const char *write_data,
size_t write_size, loff_t * poffset)
{
if(CIFS_I(file->f_dentry->d_inode)->clientCanCacheAll) /* check caching for write */
return generic_file_write(file,write_data, write_size,poffset);
else
return cifs_write(file,write_data,write_size,poffset);
}
static struct file_system_type cifs_fs_type = {
.owner = THIS_MODULE,
.name = "cifs",
......
......@@ -985,7 +985,7 @@ fill_in_inode(struct inode *tmp_inode,
/* can not fill in nlink here as in qpathinfo version and Unx search */
tmp_inode->i_size = pfindData->EndOfFile;
tmp_inode->i_blocks =
do_div(pfindData->AllocationSize, tmp_inode->i_blksize);
(tmp_inode->i_blksize - 1 + pfindData->AllocationSize) >> tmp_inode->i_blkbits;
if (pfindData->AllocationSize < pfindData->EndOfFile)
cFYI(1, ("Possible sparse file: allocation size less than end of file "));
cFYI(1,
......@@ -1059,7 +1059,8 @@ unix_fill_in_inode(struct inode *tmp_inode,
pfindData->EndOfFile = le64_to_cpu(pfindData->EndOfFile);
tmp_inode->i_size = pfindData->EndOfFile;
tmp_inode->i_blocks =
do_div(pfindData->NumOfBytes, tmp_inode->i_blksize);
(tmp_inode->i_blksize - 1 + pfindData->NumOfBytes) >> tmp_inode->i_blkbits;
if (S_ISREG(tmp_inode->i_mode)) {
cFYI(1, (" File inode "));
tmp_inode->i_op = &cifs_file_inode_ops;
......@@ -1255,7 +1256,7 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
renew_parental_timestamps(file->f_dentry);
lastFindData =
(FILE_DIRECTORY_INFO *) ((char *) pfindData +
le32_to_cpu(findParms.LastNameOffset));
findParms.LastNameOffset);
if((char *)lastFindData > (char *)pfindData + bufsize) {
cFYI(1,("last search entry past end of packet"));
rc = -EIO;
......@@ -1415,7 +1416,7 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
/* BB save off resume key, key name and name length */
lastFindData =
(FILE_DIRECTORY_INFO *) ((char *) pfindData
+ le32_to_cpu(findNextParms.LastNameOffset));
+ findNextParms.LastNameOffset);
if((char *)lastFindData > (char *)pfindData + bufsize) {
cFYI(1,("last search entry past end of packet"));
rc = -EIO;
......
......@@ -126,9 +126,13 @@ cifs_get_inode_info_unix(struct inode **pinode,
findData.NumOfBytes = le64_to_cpu(findData.NumOfBytes);
findData.EndOfFile = le64_to_cpu(findData.EndOfFile);
inode->i_size = findData.EndOfFile;
inode->i_blksize =
(pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;
inode->i_blocks = do_div(findData.NumOfBytes, inode->i_blksize);
/* blksize needs to be multiple of two. So safer to default to blksize
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;
if (findData.NumOfBytes < findData.EndOfFile)
cFYI(1, ("Server inconsistency Error: it says allocation size less than end of file "));
cFYI(1,
......@@ -236,8 +240,11 @@ cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path,
cFYI(1, (" New time %ld ", cifsInfo->time));
atomic_inc(&cifsInfo->inUse); /* inc on every refresh of inode */
inode->i_blksize =
(pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;
/* blksize needs to be multiple of two. So safer to default to blksize
and blkbits set in superblock so 2**blkbits and blksize will match */
/* inode->i_blksize =
(pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
/* Linux can not store file creation time unfortunately so we ignore it */
inode->i_atime =
cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
......@@ -268,7 +275,8 @@ cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path,
inode->i_size = le64_to_cpu(pfindData->EndOfFile);
pfindData->AllocationSize = le64_to_cpu(pfindData->AllocationSize);
inode->i_blocks =
do_div(pfindData->AllocationSize, inode->i_blksize);
(inode->i_blksize - 1 + pfindData->AllocationSize) >> inode->i_blkbits;
cFYI(1,
(" Size %ld and blocks %ld ",
(unsigned long) inode->i_size, inode->i_blocks));
......
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