X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=fs%2Fcifs%2Ffile.c;h=2d3275bedb55b9a4667027404f5a811c5b0d5ef2;hb=55e924cf5772cbcf00549e448be35b392ff3084c;hp=07ff9351e9ee71d5586f47827f92f1f9c1f7b4ff;hpb=81450b73dde07f473a4a7208b209b4c8b7251d90;p=linux-2.6-omap-h63xx.git diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 07ff9351e9e..2d3275bedb5 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -879,18 +879,19 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, cifs_stats_bytes_written(pTcon, total_written); /* since the write may have blocked check these pointers again */ - if (file->f_path.dentry) { - if (file->f_path.dentry->d_inode) { - struct inode *inode = file->f_path.dentry->d_inode; - inode->i_ctime = inode->i_mtime = - current_fs_time(inode->i_sb); - if (total_written > 0) { - if (*poffset > file->f_path.dentry->d_inode->i_size) - i_size_write(file->f_path.dentry->d_inode, + if ((file->f_path.dentry) && (file->f_path.dentry->d_inode)) { + struct inode *inode = file->f_path.dentry->d_inode; +/* Do not update local mtime - server will set its actual value on write + * inode->i_ctime = inode->i_mtime = + * current_fs_time(inode->i_sb);*/ + if (total_written > 0) { + spin_lock(&inode->i_lock); + if (*poffset > file->f_path.dentry->d_inode->i_size) + i_size_write(file->f_path.dentry->d_inode, *poffset); - } - mark_inode_dirty_sync(file->f_path.dentry->d_inode); + spin_unlock(&inode->i_lock); } + mark_inode_dirty_sync(file->f_path.dentry->d_inode); } FreeXid(xid); return total_written; @@ -1012,17 +1013,18 @@ static ssize_t cifs_write(struct file *file, const char *write_data, cifs_stats_bytes_written(pTcon, total_written); /* since the write may have blocked check these pointers again */ - if (file->f_path.dentry) { - if (file->f_path.dentry->d_inode) { - file->f_path.dentry->d_inode->i_ctime = - file->f_path.dentry->d_inode->i_mtime = CURRENT_TIME; - if (total_written > 0) { - if (*poffset > file->f_path.dentry->d_inode->i_size) - i_size_write(file->f_path.dentry->d_inode, - *poffset); - } - mark_inode_dirty_sync(file->f_path.dentry->d_inode); + if ((file->f_path.dentry) && (file->f_path.dentry->d_inode)) { +/*BB We could make this contingent on superblock ATIME flag too */ +/* file->f_path.dentry->d_inode->i_ctime = + file->f_path.dentry->d_inode->i_mtime = CURRENT_TIME;*/ + if (total_written > 0) { + spin_lock(&file->f_path.dentry->d_inode->i_lock); + if (*poffset > file->f_path.dentry->d_inode->i_size) + i_size_write(file->f_path.dentry->d_inode, + *poffset); + spin_unlock(&file->f_path.dentry->d_inode->i_lock); } + mark_inode_dirty_sync(file->f_path.dentry->d_inode); } FreeXid(xid); return total_written; @@ -1399,6 +1401,7 @@ static int cifs_commit_write(struct file *file, struct page *page, xid = GetXid(); cFYI(1, ("commit write for page %p up to position %lld for %d", page, position, to)); + spin_lock(&inode->i_lock); if (position > inode->i_size) { i_size_write(inode, position); /* if (file->private_data == NULL) { @@ -1428,6 +1431,7 @@ static int cifs_commit_write(struct file *file, struct page *page, cFYI(1, (" SetEOF (commit write) rc = %d", rc)); } */ } + spin_unlock(&inode->i_lock); if (!PageUptodate(page)) { position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + offset; /* can not rely on (or let) writepage write this data */ @@ -1988,34 +1992,52 @@ static int cifs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to) { int rc = 0; - loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT; + loff_t i_size; + loff_t offset; + cFYI(1, ("prepare write for page %p from %d to %d",page,from,to)); - if (!PageUptodate(page)) { - /* if (to - from != PAGE_CACHE_SIZE) { - void *kaddr = kmap_atomic(page, KM_USER0); + if (PageUptodate(page)) + return 0; + + /* 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); + return 0; + } + + offset = (loff_t)page->index << PAGE_CACHE_SHIFT; + i_size = i_size_read(page->mapping->host); + + if ((offset >= i_size) || + ((from == 0) && (offset + to) >= i_size)) { + /* + * We don't need to read data beyond the end of the file. + * zero it, and set the page uptodate + */ + void *kaddr = kmap_atomic(page, KM_USER0); + + if (from) memset(kaddr, 0, from); + if (to < PAGE_CACHE_SIZE) 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); - + flush_dcache_page(page); + kunmap_atomic(kaddr, KM_USER0); + SetPageUptodate(page); + } else if ((file->f_flags & O_ACCMODE) != O_WRONLY) { /* might as well read a page, it is fast enough */ - if ((file->f_flags & O_ACCMODE) != O_WRONLY) { - rc = cifs_readpage_worker(file, page, &offset); - } else { - /* should we try using another file handle if there is one - - how would we lock it to prevent close of that handle - racing with this read? - In any case this will be written out by commit_write */ - } + rc = cifs_readpage_worker(file, page, &offset); + } else { + /* we could try using another file handle if there is one - + but how would we lock it to prevent close of that handle + racing with this read? In any case + this will be written out by commit_write so is fine */ } - /* BB should we pass any errors back? - e.g. if we do not have read access to the file */ + /* we do not need to pass errors back + e.g. if we do not have read access to the file + because cifs_commit_write will do the right thing. -- shaggy */ + return 0; }