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

fix hang in truncate setting file size

parent 7ad16251
Version 0.74
------------
Fix truncate bug (set file size) that could cause hangs e.g. running fsx
Version 0.73
------------
unload nls if mount fails.
......
......@@ -2020,21 +2020,21 @@ CIFSSMBSetEOF(int xid, struct cifsTconInfo *tcon, char *fileName,
pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
InformationLevel) - 4;
pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
if(SetAllocation) {
if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
pSMB->InformationLevel =
cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
else
pSMB->InformationLevel =
cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
} else /* Set File Size */ {
if(SetAllocation) {
if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
pSMB->InformationLevel =
cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
else
pSMB->InformationLevel =
cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
} else /* Set File Size */ {
if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
pSMB->InformationLevel =
cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
else
pSMB->InformationLevel =
cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
}
}
parm_data =
(struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
......@@ -2071,10 +2071,10 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
struct smb_com_transaction2_sfi_req *pSMB = NULL;
struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
char *data_offset;
struct file_end_of_file_info *parm_data;
struct file_end_of_file_info *parm_data;
int rc = 0;
int bytes_returned = 0;
__u32 tmp;
__u32 tmp;
cFYI(1, ("SetFileSize (via SetFileInfo)"));
......
......@@ -21,6 +21,7 @@
#include <linux/fs.h>
#include <linux/buffer_head.h>
#include <linux/stat.h>
#include <linux/pagemap.h>
#include <asm/div64.h>
#include "cifsfs.h"
#include "cifspdu.h"
......@@ -587,6 +588,29 @@ cifs_truncate_file(struct inode *inode)
return;
}
static int cifs_trunc_page(struct address_space *mapping, loff_t from)
{
pgoff_t index = from >> PAGE_CACHE_SHIFT;
unsigned offset = from & (PAGE_CACHE_SIZE-1);
struct page *page;
char *kaddr;
int rc = 0;
page = grab_cache_page(mapping, index);
if (!page)
return -ENOMEM;
kaddr = kmap_atomic(page, KM_USER0);
memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset);
flush_dcache_page(page);
kunmap_atomic(kaddr, KM_USER0);
set_page_dirty(page);
unlock_page(page);
page_cache_release(page);
return rc;
}
int
cifs_setattr(struct dentry *direntry, struct iattr *attrs)
{
......@@ -639,7 +663,8 @@ cifs_setattr(struct dentry *direntry, struct iattr *attrs)
/* CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size, TRUE, cifs_sb->local_nls);*/
if (rc == 0) {
rc = vmtruncate(direntry->d_inode, attrs->ia_size);
nobh_truncate_page(direntry->d_inode->i_mapping, direntry->d_inode->i_size);
cifs_trunc_page(direntry->d_inode->i_mapping, direntry->d_inode->i_size);
/* cFYI(1,("truncate_page to 0x%lx \n",direntry->d_inode->i_size)); */
}
}
......
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