Commit 31661eda authored by Steve French's avatar Steve French

cifs_prepare_write fixes to remove problem in which we were not populating...

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
parent dfc2505c
...@@ -93,5 +93,5 @@ extern int cifs_setxattr(struct dentry *, const char *, const void *, ...@@ -93,5 +93,5 @@ extern int cifs_setxattr(struct dentry *, const char *, const void *,
size_t, int); size_t, int);
extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
extern ssize_t cifs_listxattr(struct dentry *, char *, 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 */ #endif /* _CIFSFS_H */
...@@ -159,6 +159,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -159,6 +159,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
struct cifsFileInfo * pCifsFile = NULL; struct cifsFileInfo * pCifsFile = NULL;
struct cifsInodeInfo * pCifsInode; struct cifsInodeInfo * pCifsInode;
int disposition = FILE_OVERWRITE_IF; int disposition = FILE_OVERWRITE_IF;
int write_only = FALSE;
xid = GetXid(); xid = GetXid();
...@@ -176,9 +177,10 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -176,9 +177,10 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
if(nd) { if(nd) {
if ((nd->intent.open.flags & O_ACCMODE) == O_RDONLY) if ((nd->intent.open.flags & O_ACCMODE) == O_RDONLY)
desiredAccess = GENERIC_READ; 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; 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 */ /* GENERIC_ALL is too much permission to request */
/* can cause unnecessary access denied on create */ /* can cause unnecessary access denied on create */
/* desiredAccess = GENERIC_ALL; */ /* desiredAccess = GENERIC_ALL; */
...@@ -262,16 +264,25 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -262,16 +264,25 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
pCifsFile->invalidHandle = FALSE; pCifsFile->invalidHandle = FALSE;
pCifsFile->closePend = FALSE; pCifsFile->closePend = FALSE;
init_MUTEX(&pCifsFile->fh_sem); 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); write_lock(&GlobalSMBSeslock);
list_add(&pCifsFile->tlist,&pTcon->openFileList); list_add(&pCifsFile->tlist,&pTcon->openFileList);
pCifsInode = CIFS_I(newinode); pCifsInode = CIFS_I(newinode);
if(pCifsInode) { 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) { if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
pCifsInode->clientCanCacheAll = TRUE; pCifsInode->clientCanCacheAll = TRUE;
pCifsInode->clientCanCacheRead = 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) } else if((oplock & 0xF) == OPLOCK_READ)
pCifsInode->clientCanCacheRead = TRUE; pCifsInode->clientCanCacheRead = TRUE;
} }
......
...@@ -173,7 +173,14 @@ cifs_open(struct inode *inode, struct file *file) ...@@ -173,7 +173,14 @@ cifs_open(struct inode *inode, struct file *file)
list_add(&pCifsFile->tlist,&pTcon->openFileList); list_add(&pCifsFile->tlist,&pTcon->openFileList);
pCifsInode = CIFS_I(file->f_dentry->d_inode); pCifsInode = CIFS_I(file->f_dentry->d_inode);
if(pCifsInode) { if(pCifsInode) {
/* 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); list_add(&pCifsFile->flist,&pCifsInode->openFileList);
}
write_unlock(&GlobalSMBSeslock); write_unlock(&GlobalSMBSeslock);
write_unlock(&file->f_owner.lock); write_unlock(&file->f_owner.lock);
if(pCifsInode->clientCanCacheRead) { if(pCifsInode->clientCanCacheRead) {
...@@ -924,6 +931,11 @@ cifs_read(struct file * file, char *read_data, size_t read_size, ...@@ -924,6 +931,11 @@ cifs_read(struct file * file, char *read_data, size_t read_size,
} }
open_file = (struct cifsFileInfo *)file->private_data; 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; for (total_read = 0,current_offset=read_data; read_size > total_read;
total_read += bytes_read,current_offset+=bytes_read) { total_read += bytes_read,current_offset+=bytes_read) {
current_read_size = min_t(const int,read_size - total_read,cifs_sb->rsize); current_read_size = min_t(const int,read_size - total_read,cifs_sb->rsize);
...@@ -1169,28 +1181,16 @@ cifs_readpages(struct file *file, struct address_space *mapping, ...@@ -1169,28 +1181,16 @@ cifs_readpages(struct file *file, struct address_space *mapping,
return rc; return rc;
} }
static int static int cifs_readpage_worker(struct file *file, struct page *page, loff_t * poffset)
cifs_readpage(struct file *file, struct page *page)
{ {
loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
char * read_data; char * read_data;
int rc = -EACCES; int rc;
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));
page_cache_get(page); page_cache_get(page);
read_data = kmap(page); read_data = kmap(page);
/* for reads over a certain size could initiate async read ahead */ /* 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) if (rc < 0)
goto io_error; goto io_error;
...@@ -1209,9 +1209,30 @@ cifs_readpage(struct file *file, struct page *page) ...@@ -1209,9 +1209,30 @@ cifs_readpage(struct file *file, struct page *page)
io_error: 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); unlock_page(page);
page_cache_release(page);
FreeXid(xid); FreeXid(xid);
return rc; return rc;
} }
...@@ -1950,17 +1971,27 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir) ...@@ -1950,17 +1971,27 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
int cifs_prepare_write(struct file *file, struct page *page, int cifs_prepare_write(struct file *file, struct page *page,
unsigned from, unsigned to) unsigned from, unsigned to)
{ {
cFYI(1,("prepare write for page %p from %d to %d",page,from,to)); int rc = 0;
loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
cERROR(1,("prepare write for page %p from %d to %d",page,from,to));
if (!PageUptodate(page)) { if (!PageUptodate(page)) {
if (to - from != PAGE_CACHE_SIZE) { /* if (to - from != PAGE_CACHE_SIZE) {
void *kaddr = kmap_atomic(page, KM_USER0); void *kaddr = kmap_atomic(page, KM_USER0);
memset(kaddr, 0, from); memset(kaddr, 0, from);
memset(kaddr + to, 0, PAGE_CACHE_SIZE - to); memset(kaddr + to, 0, PAGE_CACHE_SIZE - to);
flush_dcache_page(page); flush_dcache_page(page);
kunmap_atomic(kaddr, KM_USER0); 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); SetPageUptodate(page);
/* might as well read a page, it is fast enough */
rc = cifs_readpage_worker(file,page,&offset);
} }
/* BB should we pass any errors back? e.g. if we do not have read access to the file */
return 0; return 0;
} }
...@@ -1969,8 +2000,7 @@ struct address_space_operations cifs_addr_ops = { ...@@ -1969,8 +2000,7 @@ struct address_space_operations cifs_addr_ops = {
.readpage = cifs_readpage, .readpage = cifs_readpage,
.readpages = cifs_readpages, .readpages = cifs_readpages,
.writepage = cifs_writepage, .writepage = cifs_writepage,
.prepare_write = simple_prepare_write, /* BB fixme BB */ .prepare_write = cifs_prepare_write,
/* .prepare_write = cifs_prepare_write, */ /* BB removeme BB */
.commit_write = cifs_commit_write, .commit_write = cifs_commit_write,
/* .sync_page = cifs_sync_page, */ /* .sync_page = cifs_sync_page, */
/*.direct_IO = */ /*.direct_IO = */
......
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