aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/cifs/file.c241
1 files changed, 99 insertions, 142 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index c672afef0c09..00b926ce7935 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -1092,58 +1092,20 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
1092static int cifs_writepages(struct address_space *mapping, 1092static int cifs_writepages(struct address_space *mapping,
1093 struct writeback_control *wbc) 1093 struct writeback_control *wbc)
1094{ 1094{
1095 unsigned int bytes_to_write; 1095 struct cifs_sb_info *cifs_sb = CIFS_SB(mapping->host->i_sb);
1096 unsigned int bytes_written; 1096 bool done = false, scanned = false, range_whole = false;
1097 struct cifs_sb_info *cifs_sb; 1097 pgoff_t end, index;
1098 int done = 0; 1098 struct cifs_writedata *wdata;
1099 pgoff_t end;
1100 pgoff_t index;
1101 int range_whole = 0;
1102 struct kvec *iov;
1103 int len;
1104 int n_iov = 0;
1105 pgoff_t next;
1106 int nr_pages;
1107 __u64 offset = 0;
1108 struct cifsFileInfo *open_file;
1109 struct cifsTconInfo *tcon;
1110 struct cifsInodeInfo *cifsi = CIFS_I(mapping->host);
1111 struct page *page; 1099 struct page *page;
1112 struct pagevec pvec;
1113 int rc = 0; 1100 int rc = 0;
1114 int scanned = 0;
1115 int xid;
1116
1117 cifs_sb = CIFS_SB(mapping->host->i_sb);
1118 1101
1119 /* 1102 /*
1120 * If wsize is smaller that the page cache size, default to writing 1103 * If wsize is smaller than the page cache size, default to writing
1121 * one page at a time via cifs_writepage 1104 * one page at a time via cifs_writepage
1122 */ 1105 */
1123 if (cifs_sb->wsize < PAGE_CACHE_SIZE) 1106 if (cifs_sb->wsize < PAGE_CACHE_SIZE)
1124 return generic_writepages(mapping, wbc); 1107 return generic_writepages(mapping, wbc);
1125 1108
1126 iov = kmalloc(32 * sizeof(struct kvec), GFP_KERNEL);
1127 if (iov == NULL)
1128 return generic_writepages(mapping, wbc);
1129
1130 /*
1131 * if there's no open file, then this is likely to fail too,
1132 * but it'll at least handle the return. Maybe it should be
1133 * a BUG() instead?
1134 */
1135 open_file = find_writable_file(CIFS_I(mapping->host), false);
1136 if (!open_file) {
1137 kfree(iov);
1138 return generic_writepages(mapping, wbc);
1139 }
1140
1141 tcon = tlink_tcon(open_file->tlink);
1142 cifsFileInfo_put(open_file);
1143
1144 xid = GetXid();
1145
1146 pagevec_init(&pvec, 0);
1147 if (wbc->range_cyclic) { 1109 if (wbc->range_cyclic) {
1148 index = mapping->writeback_index; /* Start from prev offset */ 1110 index = mapping->writeback_index; /* Start from prev offset */
1149 end = -1; 1111 end = -1;
@@ -1151,24 +1113,49 @@ static int cifs_writepages(struct address_space *mapping,
1151 index = wbc->range_start >> PAGE_CACHE_SHIFT; 1113 index = wbc->range_start >> PAGE_CACHE_SHIFT;
1152 end = wbc->range_end >> PAGE_CACHE_SHIFT; 1114 end = wbc->range_end >> PAGE_CACHE_SHIFT;
1153 if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX) 1115 if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
1154 range_whole = 1; 1116 range_whole = true;
1155 scanned = 1; 1117 scanned = true;
1156 } 1118 }
1157retry: 1119retry:
1158 while (!done && (index <= end) && 1120 while (!done && index <= end) {
1159 (nr_pages = pagevec_lookup_tag(&pvec, mapping, &index, 1121 unsigned int i, nr_pages, found_pages;
1160 PAGECACHE_TAG_DIRTY, 1122 pgoff_t next = 0, tofind;
1161 min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1))) { 1123 struct page **pages;
1162 int first; 1124
1163 unsigned int i; 1125 tofind = min((cifs_sb->wsize / PAGE_CACHE_SIZE) - 1,
1164 1126 end - index) + 1;
1165 first = -1; 1127
1166 next = 0; 1128 wdata = cifs_writedata_alloc((unsigned int)tofind);
1167 n_iov = 0; 1129 if (!wdata) {
1168 bytes_to_write = 0; 1130 rc = -ENOMEM;
1169 1131 break;
1170 for (i = 0; i < nr_pages; i++) { 1132 }
1171 page = pvec.pages[i]; 1133
1134 /*
1135 * find_get_pages_tag seems to return a max of 256 on each
1136 * iteration, so we must call it several times in order to
1137 * fill the array or the wsize is effectively limited to
1138 * 256 * PAGE_CACHE_SIZE.
1139 */
1140 found_pages = 0;
1141 pages = wdata->pages;
1142 do {
1143 nr_pages = find_get_pages_tag(mapping, &index,
1144 PAGECACHE_TAG_DIRTY,
1145 tofind, pages);
1146 found_pages += nr_pages;
1147 tofind -= nr_pages;
1148 pages += nr_pages;
1149 } while (nr_pages && tofind && index <= end);
1150
1151 if (found_pages == 0) {
1152 kref_put(&wdata->refcount, cifs_writedata_release);
1153 break;
1154 }
1155
1156 nr_pages = 0;
1157 for (i = 0; i < found_pages; i++) {
1158 page = wdata->pages[i];
1172 /* 1159 /*
1173 * At this point we hold neither mapping->tree_lock nor 1160 * At this point we hold neither mapping->tree_lock nor
1174 * lock on the page itself: the page may be truncated or 1161 * lock on the page itself: the page may be truncated or
@@ -1177,7 +1164,7 @@ retry:
1177 * mapping 1164 * mapping
1178 */ 1165 */
1179 1166
1180 if (first < 0) 1167 if (nr_pages == 0)
1181 lock_page(page); 1168 lock_page(page);
1182 else if (!trylock_page(page)) 1169 else if (!trylock_page(page))
1183 break; 1170 break;
@@ -1188,7 +1175,7 @@ retry:
1188 } 1175 }
1189 1176
1190 if (!wbc->range_cyclic && page->index > end) { 1177 if (!wbc->range_cyclic && page->index > end) {
1191 done = 1; 1178 done = true;
1192 unlock_page(page); 1179 unlock_page(page);
1193 break; 1180 break;
1194 } 1181 }
@@ -1215,119 +1202,89 @@ retry:
1215 set_page_writeback(page); 1202 set_page_writeback(page);
1216 1203
1217 if (page_offset(page) >= mapping->host->i_size) { 1204 if (page_offset(page) >= mapping->host->i_size) {
1218 done = 1; 1205 done = true;
1219 unlock_page(page); 1206 unlock_page(page);
1220 end_page_writeback(page); 1207 end_page_writeback(page);
1221 break; 1208 break;
1222 } 1209 }
1223 1210
1224 /* 1211 wdata->pages[i] = page;
1225 * BB can we get rid of this? pages are held by pvec 1212 next = page->index + 1;
1226 */ 1213 ++nr_pages;
1227 page_cache_get(page); 1214 }
1228 1215
1229 len = min(mapping->host->i_size - page_offset(page), 1216 /* reset index to refind any pages skipped */
1230 (loff_t)PAGE_CACHE_SIZE); 1217 if (nr_pages == 0)
1218 index = wdata->pages[0]->index + 1;
1231 1219
1232 /* reserve iov[0] for the smb header */ 1220 /* put any pages we aren't going to use */
1233 n_iov++; 1221 for (i = nr_pages; i < found_pages; i++) {
1234 iov[n_iov].iov_base = kmap(page); 1222 page_cache_release(wdata->pages[i]);
1235 iov[n_iov].iov_len = len; 1223 wdata->pages[i] = NULL;
1236 bytes_to_write += len; 1224 }
1237 1225
1238 if (first < 0) { 1226 /* nothing to write? */
1239 first = i; 1227 if (nr_pages == 0) {
1240 offset = page_