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.c466
1 files changed, 333 insertions, 133 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 3497125189df..da4f5e10b3cc 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -21,11 +21,15 @@
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */ 22 */
23#include <linux/fs.h> 23#include <linux/fs.h>
24#include <linux/backing-dev.h>
24#include <linux/stat.h> 25#include <linux/stat.h>
25#include <linux/fcntl.h> 26#include <linux/fcntl.h>
27#include <linux/mpage.h>
26#include <linux/pagemap.h> 28#include <linux/pagemap.h>
27#include <linux/pagevec.h> 29#include <linux/pagevec.h>
28#include <linux/smp_lock.h> 30#include <linux/smp_lock.h>
31#include <linux/writeback.h>
32#include <linux/delay.h>
29#include <asm/div64.h> 33#include <asm/div64.h>
30#include "cifsfs.h" 34#include "cifsfs.h"
31#include "cifspdu.h" 35#include "cifspdu.h"
@@ -47,6 +51,11 @@ static inline struct cifsFileInfo *cifs_init_private(
47 private_data->pInode = inode; 51 private_data->pInode = inode;
48 private_data->invalidHandle = FALSE; 52 private_data->invalidHandle = FALSE;
49 private_data->closePend = FALSE; 53 private_data->closePend = FALSE;
54 /* we have to track num writers to the inode, since writepages
55 does not tell us which handle the write is for so there can
56 be a close (overlapping with write) of the filehandle that
57 cifs_writepages chose to use */
58 atomic_set(&private_data->wrtPending,0);
50 59
51 return private_data; 60 return private_data;
52} 61}
@@ -256,6 +265,13 @@ int cifs_open(struct inode *inode, struct file *file)
256 CREATE_NOT_DIR, &netfid, &oplock, buf, 265 CREATE_NOT_DIR, &netfid, &oplock, buf,
257 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags 266 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
258 & CIFS_MOUNT_MAP_SPECIAL_CHR); 267 & CIFS_MOUNT_MAP_SPECIAL_CHR);
268 if (rc == -EIO) {
269 /* Old server, try legacy style OpenX */
270 rc = SMBLegacyOpen(xid, pTcon, full_path, disposition,
271 desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf,
272 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
273 & CIFS_MOUNT_MAP_SPECIAL_CHR);
274 }
259 if (rc) { 275 if (rc) {
260 cFYI(1, ("cifs_open returned 0x%x ", rc)); 276 cFYI(1, ("cifs_open returned 0x%x ", rc));
261 goto out; 277 goto out;
@@ -463,6 +479,20 @@ int cifs_close(struct inode *inode, struct file *file)
463 /* no sense reconnecting to close a file that is 479 /* no sense reconnecting to close a file that is
464 already closed */ 480 already closed */
465 if (pTcon->tidStatus != CifsNeedReconnect) { 481 if (pTcon->tidStatus != CifsNeedReconnect) {
482 int timeout = 2;
483 while((atomic_read(&pSMBFile->wrtPending) != 0)
484 && (timeout < 1000) ) {
485 /* Give write a better chance to get to
486 server ahead of the close. We do not
487 want to add a wait_q here as it would
488 increase the memory utilization as
489 the struct would be in each open file,
490 but this should give enough time to
491 clear the socket */
492 cERROR(1,("close with pending writes"));
493 msleep(timeout);
494 timeout *= 4;
495 }
466 write_unlock(&file->f_owner.lock); 496 write_unlock(&file->f_owner.lock);
467 rc = CIFSSMBClose(xid, pTcon, 497 rc = CIFSSMBClose(xid, pTcon,
468 pSMBFile->netfid); 498 pSMBFile->netfid);
@@ -744,14 +774,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
744 15 seconds is plenty */ 774 15 seconds is plenty */
745 } 775 }
746 776
747#ifdef CONFIG_CIFS_STATS 777 cifs_stats_bytes_written(pTcon, total_written);
748 if (total_written > 0) {
749 atomic_inc(&pTcon->num_writes);
750 spin_lock(&pTcon->stat_lock);
751 pTcon->bytes_written += total_written;
752 spin_unlock(&pTcon->stat_lock);
753 }
754#endif
755 778
756 /* since the write may have blocked check these pointers again */ 779 /* since the write may have blocked check these pointers again */
757 if (file->f_dentry) { 780 if (file->f_dentry) {
@@ -791,9 +814,8 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
791 814
792 pTcon = cifs_sb->tcon; 815 pTcon = cifs_sb->tcon;
793 816
794 /* cFYI(1, 817 cFYI(1,("write %zd bytes to offset %lld of %s", write_size,
795 (" write %d bytes to offset %lld of %s", write_size, 818 *poffset, file->f_dentry->d_name.name));
796 *poffset, file->f_dentry->d_name.name)); */
797 819
798 if (file->private_data == NULL) 820 if (file->private_data == NULL)
799 return -EBADF; 821 return -EBADF;
@@ -846,7 +868,26 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
846 if (rc != 0) 868 if (rc != 0)
847 break; 869 break;
848 } 870 }
849 871#ifdef CONFIG_CIFS_EXPERIMENTAL
872 /* BB FIXME We can not sign across two buffers yet */
873 if((experimEnabled) && ((pTcon->ses->server->secMode &
874 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) == 0)) {
875 struct kvec iov[2];
876 unsigned int len;
877
878 len = min((size_t)cifs_sb->wsize,
879 write_size - total_written);
880 /* iov[0] is reserved for smb header */
881 iov[1].iov_base = (char *)write_data +
882 total_written;
883 iov[1].iov_len = len;
884 rc = CIFSSMBWrite2(xid, pTcon,
885 open_file->netfid, len,
886 *poffset, &bytes_written,
887 iov, 1, long_op);
888 } else
889 /* BB FIXME fixup indentation of line below */
890#endif
850 rc = CIFSSMBWrite(xid, pTcon, 891 rc = CIFSSMBWrite(xid, pTcon,
851 open_file->netfid, 892 open_file->netfid,
852 min_t(const int, cifs_sb->wsize, 893 min_t(const int, cifs_sb->wsize,
@@ -867,14 +908,7 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
867 15 seconds is plenty */ 908 15 seconds is plenty */
868 } 909 }
869 910
870#ifdef CONFIG_CIFS_STATS 911 cifs_stats_bytes_written(pTcon, total_written);
871 if (total_written > 0) {
872 atomic_inc(&pTcon->num_writes);
873 spin_lock(&pTcon->stat_lock);
874 pTcon->bytes_written += total_written;
875 spin_unlock(&pTcon->stat_lock);
876 }
877#endif
878 912
879 /* since the write may have blocked check these pointers again */ 913 /* since the write may have blocked check these pointers again */
880 if (file->f_dentry) { 914 if (file->f_dentry) {
@@ -893,6 +927,43 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
893 return total_written; 927 return total_written;
894} 928}
895 929
930struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
931{
932 struct cifsFileInfo *open_file;
933 int rc;
934
935 read_lock(&GlobalSMBSeslock);
936 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
937 if (open_file->closePend)
938 continue;
939 if (open_file->pfile &&
940 ((open_file->pfile->f_flags & O_RDWR) ||
941 (open_file->pfile->f_flags & O_WRONLY))) {
942 atomic_inc(&open_file->wrtPending);
943 read_unlock(&GlobalSMBSeslock);
944 if((open_file->invalidHandle) &&
945 (!open_file->closePend) /* BB fixme -since the second clause can not be true remove it BB */) {
946 rc = cifs_reopen_file(&cifs_inode->vfs_inode,
947 open_file->pfile, FALSE);
948 /* if it fails, try another handle - might be */
949 /* dangerous to hold up writepages with retry */
950 if(rc) {
951 cFYI(1,("failed on reopen file in wp"));
952 read_lock(&GlobalSMBSeslock);
953 /* can not use this handle, no write
954 pending on this one after all */
955 atomic_dec
956 (&open_file->wrtPending);
957 continue;
958 }
959 }
960 return open_file;
961 }
962 }
963 read_unlock(&GlobalSMBSeslock);
964 return NULL;
965}
966
896static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to) 967static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
897{ 968{
898 struct address_space *mapping = page->mapping; 969 struct address_space *mapping = page->mapping;
@@ -903,10 +974,7 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
903 struct cifs_sb_info *cifs_sb; 974 struct cifs_sb_info *cifs_sb;
904 struct cifsTconInfo *pTcon; 975 struct cifsTconInfo *pTcon;
905 struct inode *inode; 976 struct inode *inode;
906 struct cifsInodeInfo *cifsInode; 977 struct cifsFileInfo *open_file;
907 struct cifsFileInfo *open_file = NULL;
908 struct list_head *tmp;
909 struct list_head *tmp1;
910 978
911 if (!mapping || !mapping->host) 979 if (!mapping || !mapping->host)
912 return -EFAULT; 980 return -EFAULT;
@@ -934,49 +1002,20 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
934 if (mapping->host->i_size - offset < (loff_t)to) 1002 if (mapping->host->i_size - offset < (loff_t)to)
935 to = (unsigned)(mapping->host->i_size - offset); 1003 to = (unsigned)(mapping->host->i_size - offset);
936 1004
937 cifsInode = CIFS_I(mapping->host); 1005 open_file = find_writable_file(CIFS_I(mapping->host));
938 read_lock(&GlobalSMBSeslock); 1006 if (open_file) {
939 /* BB we should start at the end */ 1007 bytes_written = cifs_write(open_file->pfile, write_data,
940 list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) { 1008 to-from, &offset);
941 open_file = list_entry(tmp, struct cifsFileInfo, flist); 1009 atomic_dec(&open_file->wrtPending);
942 if (open_file->closePend)
943 continue;
944 /* We check if file is open for writing first */
945 if ((open_file->pfile) &&
946 ((open_file->pfile->f_flags & O_RDWR) ||
947 (open_file->pfile->f_flags & O_WRONLY))) {
948 read_unlock(&GlobalSMBSeslock);
949 bytes_written = cifs_write(open_file->pfile,
950 write_data, to-from,
951 &offset);
952 read_lock(&GlobalSMBSeslock);
953 /* Does mm or vfs already set times? */ 1010 /* Does mm or vfs already set times? */
954 inode->i_atime = 1011 inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb);
955 inode->i_mtime = current_fs_time(inode->i_sb); 1012 if ((bytes_written > 0) && (offset)) {
956 if ((bytes_written > 0) && (offset)) { 1013 rc = 0;
957 rc = 0; 1014 } else if (bytes_written < 0) {
958 } else if (bytes_written < 0) { 1015 if (rc != -EBADF)
959 if (rc == -EBADF) { 1016 rc = bytes_written;
960 /* have seen a case in which kernel seemed to
961 have closed/freed a file even with writes
962 active so we might as well see if there are
963 other file structs to try for the same
964 inode before giving up */
965 continue;
966 } else
967 rc = bytes_written;
968 }
969 break; /* now that we found a valid file handle and
970 tried to write to it we are done, no sense
971 continuing to loop looking for another */
972 }
973 if (tmp->next == NULL) {
974 cFYI(1, ("File instance %p removed", tmp));
975 break;
976 } 1017 }
977 } 1018 } else {
978 read_unlock(&GlobalSMBSeslock);
979 if (open_file == NULL) {
980 cFYI(1, ("No writeable filehandles for inode")); 1019 cFYI(1, ("No writeable filehandles for inode"));
981 rc = -EIO; 1020 rc = -EIO;
982 } 1021 }
@@ -985,20 +1024,207 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
985 return rc; 1024 return rc;
986} 1025}
987 1026
988#if 0 1027#ifdef CONFIG_CIFS_EXPERIMENTAL
989static int cifs_writepages(struct address_space *mapping, 1028static int cifs_writepages(struct address_space *mapping,
990 struct writeback_control *wbc) 1029 struct writeback_control *wbc)
991{ 1030{
992 int rc = -EFAULT; 1031 struct backing_dev_info *bdi = mapping->backing_dev_info;
1032 unsigned int bytes_to_write;
1033 unsigned int bytes_written;
1034 struct cifs_sb_info *cifs_sb;
1035 int done = 0;
1036 pgoff_t end = -1;
1037 pgoff_t index;
1038 int is_range = 0;
1039 struct kvec iov[32];
1040 int len;
1041 int n_iov = 0;
1042 pgoff_t next;
1043 int nr_pages;
1044 __u64 offset = 0;
1045 struct cifsFileInfo *open_file;
1046 struct page *page;
1047 struct pagevec pvec;
1048 int rc = 0;
1049 int scanned = 0;
993 int xid; 1050 int xid;
994 1051
1052 cifs_sb = CIFS_SB(mapping->host->i_sb);
1053
1054 /*
1055 * If wsize is smaller that the page cache size, default to writing
1056 * one page at a time via cifs_writepage
1057 */
1058 if (cifs_sb->wsize < PAGE_CACHE_SIZE)
1059 return generic_writepages(mapping, wbc);
1060
1061 /* BB FIXME we do not have code to sign across multiple buffers yet,
1062 so go to older writepage style write which we can sign if needed */
1063 if((cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->server))
1064 if(cifs_sb->tcon->ses->server->secMode &
1065 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1066 return generic_writepages(mapping, wbc);
1067
1068 /*
1069 * BB: Is this meaningful for a non-block-device file system?
1070 * If it is, we should test it again after we do I/O
1071 */
1072 if (wbc->nonblocking && bdi_write_congested(bdi)) {
1073 wbc->encountered_congestion = 1;
1074 return 0;
1075 }
1076
995 xid = GetXid(); 1077 xid = GetXid();
996 1078
997 /* Find contiguous pages then iterate through repeating 1079 pagevec_init(&pvec, 0);
998 call 16K write then Setpageuptodate or if LARGE_WRITE_X 1080 if (wbc->sync_mode == WB_SYNC_NONE)
999 support then send larger writes via kevec so as to eliminate 1081 index = mapping->writeback_index; /* Start from prev offset */
1000 a memcpy */ 1082 else {
1083 index = 0;
1084 scanned = 1;
1085 }
1086 if (wbc->start || wbc->end) {
1087 index = wbc->start >> PAGE_CACHE_SHIFT;
1088 end = wbc->end >> PAGE_CACHE_SHIFT;
1089 is_range = 1;
1090 scanned = 1;
1091 }
1092retry:
1093 while (!done && (index <= end) &&
1094 (nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
1095 PAGECACHE_TAG_DIRTY,
1096 min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1))) {
1097 int first;
1098 unsigned int i;
1099
1100 first = -1;
1101 next = 0;
1102 n_iov = 0;
1103 bytes_to_write = 0;
1104
1105 for (i = 0; i < nr_pages; i++) {
1106 page = pvec.pages[i];
1107 /*
1108 * At this point we hold neither mapping->tree_lock nor
1109 * lock on the page itself: the page may be truncated or
1110 * invalidated (changing page->mapping to NULL), or even
1111 * swizzled back from swapper_space to tmpfs file
1112 * mapping
1113 */
1114
1115 if (first < 0)
1116 lock_page(page);
1117 else if (TestSetPageLocked(page))
1118 break;
1119
1120 if (unlikely(page->mapping != mapping)) {
1121 unlock_page(page);
1122 break;
1123 }
1124
1125 if (unlikely(is_range) && (page->index > end)) {
1126 done = 1;
1127 unlock_page(page);
1128 break;
1129 }
1130
1131 if (next && (page->index != next)) {
1132 /* Not next consecutive page */
1133 unlock_page(page);
1134 break;
1135 }
1136
1137 if (wbc->sync_mode != WB_SYNC_NONE)
1138 wait_on_page_writeback(page);
1139
1140 if (PageWriteback(page) ||
1141 !test_clear_page_dirty(page)) {
1142 unlock_page(page);
1143 break;
1144 }
1145
1146 if (page_offset(page) >= mapping->host->i_size) {
1147 done = 1;
1148 unlock_page(page);
1149 break;
1150 }
1151
1152 /*
1153 * BB can we get rid of this? pages are held by pvec
1154 */
1155 page_cache_get(page);
1156
1157 len = min(mapping->host->i_size - page_offset(page),
1158 (loff_t)PAGE_CACHE_SIZE);
1159
1160 /* reserve iov[0] for the smb header */
1161 n_iov++;
1162 iov[n_iov].iov_base = kmap(page);
1163 iov[n_iov].iov_len = len;
1164 bytes_to_write += len;
1165
1166 if (first < 0) {
1167 first = i;
1168 offset = page_offset(page);
1169 }
1170 next = page->index + 1;
1171 if (bytes_to_write + PAGE_CACHE_SIZE > cifs_sb->wsize)
1172 break;
1173 }
1174 if (n_iov) {
1175 /* Search for a writable handle every time we call
1176 * CIFSSMBWrite2. We can't rely on the last handle
1177 * we used to still be valid
1178 */
1179 open_file = find_writable_file(CIFS_I(mapping->host));
1180 if (!open_file) {
1181 cERROR(1, ("No writable handles for inode"));
1182 rc = -EBADF;
1183 } else {
1184 rc = CIFSSMBWrite2(xid, cifs_sb->tcon,
1185 open_file->netfid,
1186 bytes_to_write, offset,
1187 &bytes_written, iov, n_iov,
1188 1);
1189 atomic_dec(&open_file->wrtPending);
1190 if (rc || bytes_written < bytes_to_write) {
1191 cERROR(1,("Write2 ret %d, written = %d",
1192 rc, bytes_written));
1193 /* BB what if continued retry is
1194 requested via mount flags? */
1195 set_bit(AS_EIO, &mapping->flags);
1196 SetPageError(page);
1197 } else {
1198 cifs_stats_bytes_written(cifs_sb->tcon,
1199 bytes_written);
1200 }
1201 }
1202 for (i = 0; i < n_iov; i++) {
1203 page = pvec.pages[first + i];
1204 kunmap(page);
1205 unlock_page(page);
1206 page_cache_release(page);
1207 }
1208 if ((wbc->nr_to_write -= n_iov) <= 0)
1209 done = 1;
1210 index = next;
1211 }
1212 pagevec_release(&pvec);
1213 }
1214 if (!scanned && !done) {
1215 /*
1216 * We hit the last page and there is more work to be done: wrap
1217 * back to the start of the file
1218 */
1219 scanned = 1;
1220 index = 0;
1221 goto retry;
1222 }
1223 if (!is_range)
1224 mapping->writeback_index = index;
1225
1001 FreeXid(xid); 1226 FreeXid(xid);
1227
1002 return rc; 1228 return rc;
1003} 1229}
1004#endif 1230#endif
@@ -1207,12 +1433,10 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
1207 if (rc != 0) 1433 if (rc != 0)
1208 break; 1434 break;
1209 } 1435 }
1210
1211 rc = CIFSSMBRead(xid, pTcon, 1436 rc = CIFSSMBRead(xid, pTcon,
1212 open_file->netfid, 1437 open_file->netfid,
1213 current_read_size, *poffset, 1438 current_read_size, *poffset,
1214 &bytes_read, &smb_read_data); 1439 &bytes_read, &smb_read_data);
1215
1216 pSMBr = (struct smb_com_read_rsp *)smb_read_data; 1440 pSMBr = (struct smb_com_read_rsp *)smb_read_data;
1217 if (copy_to_user(current_offset, 1441 if (copy_to_user(current_offset,
1218 smb_read_data + 4 /* RFC1001 hdr */ 1442 smb_read_data + 4 /* RFC1001 hdr */
@@ -1235,12 +1459,7 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
1235 return rc; 1459 return rc;
1236 } 1460 }
1237 } else { 1461 } else {
1238#ifdef CONFIG_CIFS_STATS 1462 cifs_stats_bytes_read(pTcon, bytes_read);
1239 atomic_inc(&pTcon->num_reads);
1240 spin_lock(&pTcon->stat_lock);
1241 pTcon->bytes_read += total_read;
1242 spin_unlock(&pTcon->stat_lock);
1243#endif
1244 *poffset += bytes_read; 1463 *poffset += bytes_read;
1245 } 1464 }
1246 } 1465 }
@@ -1280,6 +1499,13 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
1280 total_read += bytes_read, current_offset += bytes_read) { 1499 total_read += bytes_read, current_offset += bytes_read) {
1281 current_read_size = min_t(const int, read_size - total_read, 1500 current_read_size = min_t(const int, read_size - total_read,
1282 cifs_sb->rsize); 1501 cifs_sb->rsize);
1502 /* For windows me and 9x we do not want to request more
1503 than it negotiated since it will refuse the read then */
1504 if((pTcon->ses) &&
1505 !(pTcon->ses->capabilities & CAP_LARGE_FILES)) {
1506 current_read_size = min_t(const int, current_read_size,
1507 pTcon->ses->server->maxBuf - 128);
1508 }
1283 rc = -EAGAIN; 1509 rc = -EAGAIN;
1284 while (rc == -EAGAIN) { 1510 while (rc == -EAGAIN) {
1285 if ((open_file->invalidHandle) && 1511 if ((open_file->invalidHandle) &&
@@ -1289,11 +1515,10 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
1289 if (rc != 0) 1515 if (rc != 0)
1290 break; 1516 break;
1291 } 1517 }
1292
1293 rc = CIFSSMBRead(xid, pTcon, 1518 rc = CIFSSMBRead(xid, pTcon,
1294 open_file->netfid, 1519 open_file->netfid,
1295 current_read_size, *poffset, 1520 current_read_size, *poffset,
1296 &bytes_read, &current_offset); 1521 &bytes_read, &current_offset);
1297 } 1522 }
1298 if (rc || (bytes_read == 0)) { 1523 if (rc || (bytes_read == 0)) {
1299 if (total_read) { 1524 if (total_read) {
@@ -1303,12 +1528,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
1303 return rc; 1528 return rc;
1304 } 1529 }
1305 } else { 1530 } else {
1306#ifdef CONFIG_CIFS_STATS 1531 cifs_stats_bytes_read(pTcon, total_read);
1307 atomic_inc(&pTcon->num_reads);
1308 spin_lock(&pTcon->stat_lock);
1309 pTcon->bytes_read += total_read;
1310 spin_unlock(&pTcon->stat_lock);
1311#endif
1312 *poffset += bytes_read; 1532 *poffset += bytes_read;
1313 } 1533 }
1314 } 1534 }
@@ -1452,10 +1672,11 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
1452 } 1672 }
1453 1673
1454 rc = CIFSSMBRead(xid, pTcon, 1674 rc = CIFSSMBRead(xid, pTcon,
1455 open_file->netfid, 1675 open_file->netfid,
1456 read_size, offset, 1676 read_size, offset,
1457 &bytes_read, &smb_read_data); 1677 &bytes_read, &smb_read_data);
1458 /* BB need to check return code here */ 1678
1679 /* BB more RC checks ? */
1459 if (rc== -EAGAIN) { 1680 if (rc== -EAGAIN) {
1460 if (smb_read_data) { 1681 if (smb_read_data) {
1461 cifs_buf_release(smb_read_data); 1682 cifs_buf_release(smb_read_data);
@@ -1480,12 +1701,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
1480 le16_to_cpu(pSMBr->DataOffset), &lru_pvec); 1701 le16_to_cpu(pSMBr->DataOffset), &lru_pvec);
1481 1702
1482 i += bytes_read >> PAGE_CACHE_SHIFT; 1703 i += bytes_read >> PAGE_CACHE_SHIFT;
1483#ifdef CONFIG_CIFS_STATS 1704 cifs_stats_bytes_read(pTcon, bytes_read);
1484 atomic_inc(&pTcon->num_reads);
1485 spin_lock(&pTcon->stat_lock);
1486 pTcon->bytes_read += bytes_read;
1487 spin_unlock(&pTcon->stat_lock);
1488#endif
1489 if ((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) { 1705 if ((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) {
1490 i++; /* account for partial page */ 1706 i++; /* account for partial page */
1491 1707
@@ -1603,40 +1819,21 @@ static int cifs_readpage(struct file *file, struct page *page)
1603 page caching in the current Linux kernel design */ 1819 page caching in the current Linux kernel design */
1604int is_size_safe_to_change(struct cifsInodeInfo *cifsInode) 1820int is_size_safe_to_change(struct cifsInodeInfo *cifsInode)
1605{ 1821{
1606 struct list_head *tmp;
1607 struct list_head *tmp1;
1608 struct cifsFileInfo *open_file = NULL; 1822 struct cifsFileInfo *open_file = NULL;
1609 int rc = TRUE;
1610 1823
1611 if (cifsInode == NULL) 1824 if (cifsInode)
1612 return rc; 1825 open_file = find_writable_file(cifsInode);
1613 1826
1614 read_lock(&GlobalSMBSeslock); 1827 if(open_file) {
1615 list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) { 1828 /* there is not actually a write pending so let
1616 open_file = list_entry(tmp, struct cifsFileInfo, flist); 1829 this handle go free and allow it to
1617 if (open_file == NULL) 1830 be closable if needed */
1618 break; 1831 atomic_dec(&open_file->wrtPending);
1619 if (open_file->closePend) 1832 return 0;
1620 continue; 1833 } else
1621 /* We check if file is open for writing, 1834 return 1;
1622 BB we could supplement this with a check to see if file size
1623 changes have been flushed to server - ie inode metadata dirty */
1624 if ((open_file->pfile) &&
1625 ((open_file->pfile->f_flags & O_RDWR) ||
1626 (open_file->pfile->f_flags & O_WRONLY))) {
1627 rc = FALSE;
1628 break;
1629 }
1630 if (tmp->next == NULL) {
1631 cFYI(1, ("File instance %p removed", tmp));
1632 break;
1633 }
1634 }
1635 read_unlock(&GlobalSMBSeslock);
1636 return rc;
1637} 1835}
1638 1836
1639
1640static int cifs_prepare_write(struct file *file, struct page *page, 1837static int cifs_prepare_write(struct file *file, struct page *page,
1641 unsigned from, unsigned to) 1838 unsigned from, unsigned to)
1642{ 1839{
@@ -1676,6 +1873,9 @@ struct address_space_operations cifs_addr_ops = {
1676 .readpage = cifs_readpage, 1873 .readpage = cifs_readpage,
1677 .readpages = cifs_readpages, 1874 .readpages = cifs_readpages,
1678 .writepage = cifs_writepage, 1875 .writepage = cifs_writepage,
1876#ifdef CONFIG_CIFS_EXPERIMENTAL
1877 .writepages = cifs_writepages,
1878#endif
1679 .prepare_write = cifs_prepare_write, 1879 .prepare_write = cifs_prepare_write,
1680 .commit_write = cifs_commit_write, 1880 .commit_write = cifs_commit_write,
1681 .set_page_dirty = __set_page_dirty_nobuffers, 1881 .set_page_dirty = __set_page_dirty_nobuffers,