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 Version 0.73
------------ ------------
unload nls if mount fails. unload nls if mount fails.
......
...@@ -2020,21 +2020,21 @@ CIFSSMBSetEOF(int xid, struct cifsTconInfo *tcon, char *fileName, ...@@ -2020,21 +2020,21 @@ CIFSSMBSetEOF(int xid, struct cifsTconInfo *tcon, char *fileName,
pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req, pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
InformationLevel) - 4; InformationLevel) - 4;
pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount; pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
if(SetAllocation) { if(SetAllocation) {
if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU) if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
pSMB->InformationLevel = pSMB->InformationLevel =
cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2); cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
else else
pSMB->InformationLevel = pSMB->InformationLevel =
cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO); cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
} else /* Set File Size */ { } else /* Set File Size */ {
if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU) if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
pSMB->InformationLevel = pSMB->InformationLevel =
cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2); cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
else else
pSMB->InformationLevel = pSMB->InformationLevel =
cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO); cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
} }
parm_data = parm_data =
(struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) + (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
...@@ -2071,10 +2071,10 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size, ...@@ -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_req *pSMB = NULL;
struct smb_com_transaction2_sfi_rsp *pSMBr = NULL; struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
char *data_offset; char *data_offset;
struct file_end_of_file_info *parm_data; struct file_end_of_file_info *parm_data;
int rc = 0; int rc = 0;
int bytes_returned = 0; int bytes_returned = 0;
__u32 tmp; __u32 tmp;
cFYI(1, ("SetFileSize (via SetFileInfo)")); cFYI(1, ("SetFileSize (via SetFileInfo)"));
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/buffer_head.h> #include <linux/buffer_head.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/pagemap.h>
#include <asm/div64.h> #include <asm/div64.h>
#include "cifsfs.h" #include "cifsfs.h"
#include "cifspdu.h" #include "cifspdu.h"
...@@ -587,6 +588,29 @@ cifs_truncate_file(struct inode *inode) ...@@ -587,6 +588,29 @@ cifs_truncate_file(struct inode *inode)
return; 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 int
cifs_setattr(struct dentry *direntry, struct iattr *attrs) cifs_setattr(struct dentry *direntry, struct iattr *attrs)
{ {
...@@ -639,7 +663,8 @@ 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);*/ /* CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size, TRUE, cifs_sb->local_nls);*/
if (rc == 0) { if (rc == 0) {
rc = vmtruncate(direntry->d_inode, attrs->ia_size); 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)); */ /* 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