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 *,
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 */
......@@ -159,6 +159,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
struct cifsFileInfo * pCifsFile = NULL;
struct cifsInodeInfo * pCifsInode;
int disposition = FILE_OVERWRITE_IF;
int write_only = FALSE;
xid = GetXid();
......@@ -176,9 +177,10 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
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 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
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;
}
......
......@@ -173,7 +173,14 @@ cifs_open(struct inode *inode, struct file *file)
list_add(&pCifsFile->tlist,&pTcon->openFileList);
pCifsInode = CIFS_I(file->f_dentry->d_inode);
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);
}
write_unlock(&GlobalSMBSeslock);
write_unlock(&file->f_owner.lock);
if(pCifsInode->clientCanCacheRead) {
......@@ -924,6 +931,11 @@ cifs_read(struct file * file, char *read_data, size_t read_size,
}
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,28 +1181,16 @@ cifs_readpages(struct file *file, struct address_space *mapping,
return rc;
}
static int
cifs_readpage(struct file *file, struct page *page)
static int cifs_readpage_worker(struct file *file, struct page *page, loff_t * poffset)
{
loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
char * read_data;
int rc = -EACCES;
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));
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, &offset);
rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, poffset);
if (rc < 0)
goto io_error;
......@@ -1209,9 +1209,30 @@ cifs_readpage(struct file *file, struct page *page)
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;
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);
page_cache_release(page);
FreeXid(xid);
return rc;
}
......@@ -1950,17 +1971,27 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
int cifs_prepare_write(struct file *file, struct page *page,
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 (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);
}
} */
/* 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);
}
/* BB should we pass any errors back? e.g. if we do not have read access to the file */
return 0;
}
......@@ -1969,8 +2000,7 @@ struct address_space_operations cifs_addr_ops = {
.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 = */
......
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