aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/file.c')
-rw-r--r--fs/cifs/file.c112
1 files changed, 35 insertions, 77 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 941108352547..94875455d7fa 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -904,6 +904,25 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
904 return total_written; 904 return total_written;
905} 905}
906 906
907static struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
908{
909 struct cifsFileInfo *open_file;
910
911 read_lock(&GlobalSMBSeslock);
912 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
913 if (open_file->closePend)
914 continue;
915 if (open_file->pfile &&
916 ((open_file->pfile->f_flags & O_RDWR) ||
917 (open_file->pfile->f_flags & O_WRONLY))) {
918 read_unlock(&GlobalSMBSeslock);
919 return open_file;
920 }
921 }
922 read_unlock(&GlobalSMBSeslock);
923 return NULL;
924}
925
907static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to) 926static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
908{ 927{
909 struct address_space *mapping = page->mapping; 928 struct address_space *mapping = page->mapping;
@@ -914,10 +933,7 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
914 struct cifs_sb_info *cifs_sb; 933 struct cifs_sb_info *cifs_sb;
915 struct cifsTconInfo *pTcon; 934 struct cifsTconInfo *pTcon;
916 struct inode *inode; 935 struct inode *inode;
917 struct cifsInodeInfo *cifsInode; 936 struct cifsFileInfo *open_file;
918 struct cifsFileInfo *open_file = NULL;
919 struct list_head *tmp;
920 struct list_head *tmp1;
921 937
922 if (!mapping || !mapping->host) 938 if (!mapping || !mapping->host)
923 return -EFAULT; 939 return -EFAULT;
@@ -945,49 +961,19 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
945 if (mapping->host->i_size - offset < (loff_t)to) 961 if (mapping->host->i_size - offset < (loff_t)to)
946 to = (unsigned)(mapping->host->i_size - offset); 962 to = (unsigned)(mapping->host->i_size - offset);
947 963
948 cifsInode = CIFS_I(mapping->host); 964 open_file = find_writable_file(CIFS_I(mapping->host));
949 read_lock(&GlobalSMBSeslock); 965 if (open_file) {
950 /* BB we should start at the end */ 966 bytes_written = cifs_write(open_file->pfile, write_data,
951 list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) { 967 to-from, &offset);
952 open_file = list_entry(tmp, struct cifsFileInfo, flist);
953 if (open_file->closePend)
954 continue;
955 /* We check if file is open for writing first */
956 if ((open_file->pfile) &&
957 ((open_file->pfile->f_flags & O_RDWR) ||
958 (open_file->pfile->f_flags & O_WRONLY))) {
959 read_unlock(&GlobalSMBSeslock);
960 bytes_written = cifs_write(open_file->pfile,
961 write_data, to-from,
962 &offset);
963 read_lock(&GlobalSMBSeslock);
964 /* Does mm or vfs already set times? */ 968 /* Does mm or vfs already set times? */
965 inode->i_atime = 969 inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb);
966 inode->i_mtime = current_fs_time(inode->i_sb); 970 if ((bytes_written > 0) && (offset)) {
967 if ((bytes_written > 0) && (offset)) { 971 rc = 0;
968 rc = 0; 972 } else if (bytes_written < 0) {
969 } else if (bytes_written < 0) { 973 if (rc != -EBADF)
970 if (rc == -EBADF) { 974 rc = bytes_written;
971 /* have seen a case in which kernel seemed to
972 have closed/freed a file even with writes
973 active so we might as well see if there are
974 other file structs to try for the same
975 inode before giving up */
976 continue;
977 } else
978 rc = bytes_written;
979 }
980 break; /* now that we found a valid file handle and
981 tried to write to it we are done, no sense
982 continuing to loop looking for another */
983 }
984 if (tmp->next == NULL) {
985 cFYI(1, ("File instance %p removed", tmp));
986 break;
987 } 975 }
988 } 976 } else {
989 read_unlock(&GlobalSMBSeslock);
990 if (open_file == NULL) {
991 cFYI(1, ("No writeable filehandles for inode")); 977 cFYI(1, ("No writeable filehandles for inode"));
992 rc = -EIO; 978 rc = -EIO;
993 } 979 }
@@ -1604,40 +1590,12 @@ static int cifs_readpage(struct file *file, struct page *page)
1604 page caching in the current Linux kernel design */ 1590 page caching in the current Linux kernel design */
1605int is_size_safe_to_change(struct cifsInodeInfo *cifsInode) 1591int is_size_safe_to_change(struct cifsInodeInfo *cifsInode)
1606{ 1592{
1607 struct list_head *tmp; 1593 if (cifsInode && find_writable_file(cifsInode))
1608 struct list_head *tmp1; 1594 return 0;
1609 struct cifsFileInfo *open_file = NULL; 1595 else
1610 int rc = TRUE; 1596 return 1;
1611
1612 if (cifsInode == NULL)
1613 return rc;
1614
1615 read_lock(&GlobalSMBSeslock);
1616 list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) {
1617 open_file = list_entry(tmp, struct cifsFileInfo, flist);
1618 if (open_file == NULL)
1619 break;
1620 if (open_file->closePend)
1621 continue;
1622 /* We check if file is open for writing,
1623 BB we could supplement this with a check to see if file size
1624 changes have been flushed to server - ie inode metadata dirty */
1625 if ((open_file->pfile) &&
1626 ((open_file->pfile->f_flags & O_RDWR) ||
1627 (open_file->pfile->f_flags & O_WRONLY))) {
1628 rc = FALSE;
1629 break;
1630 }
1631 if (tmp->next == NULL) {
1632 cFYI(1, ("File instance %p removed", tmp));
1633 break;
1634 }
1635 }
1636 read_unlock(&GlobalSMBSeslock);
1637 return rc;
1638} 1597}
1639 1598
1640
1641static int cifs_prepare_write(struct file *file, struct page *page, 1599static int cifs_prepare_write(struct file *file, struct page *page,
1642 unsigned from, unsigned to) 1600 unsigned from, unsigned to)
1643{ 1601{