aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2010-09-22 19:17:40 -0400
committerSteve French <sfrench@us.ibm.com>2010-09-29 15:04:33 -0400
commitf3983c2133e9bea9c8b4f690737d15e3e9b02491 (patch)
tree89cc00b209368a41e5554ac1be103ef6e79d8fe1 /fs/cifs
parentf7a40689fd1e963cb1006349e050c07584895db5 (diff)
cifs: fix handling of signing with writepages (try #6)
Get a reference to the file early so we can eventually base the decision about signing on the correct tcon. If that doesn't work for some reason, then fall back to generic_writepages. That's just as likely to fail, but it simplifies the error handling. In truth, I'm not sure how that could occur anyway, so maybe a NULL open_file here ought to be a BUG()? After that, we drop the reference to the open_file and then we re-get one prior to each WriteAndX call. This helps ensure that the filehandle isn't held open any longer than necessary and that open files are reclaimed prior to each write call. Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/file.c68
1 files changed, 37 insertions, 31 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index e5f463e15c9b..de046e183d12 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -1353,6 +1353,15 @@ static int cifs_writepages(struct address_space *mapping,
1353 int scanned = 0; 1353 int scanned = 0;
1354 int xid, long_op; 1354 int xid, long_op;
1355 1355
1356 /*
1357 * BB: Is this meaningful for a non-block-device file system?
1358 * If it is, we should test it again after we do I/O
1359 */
1360 if (wbc->nonblocking && bdi_write_congested(bdi)) {
1361 wbc->encountered_congestion = 1;
1362 return 0;
1363 }
1364
1356 cifs_sb = CIFS_SB(mapping->host->i_sb); 1365 cifs_sb = CIFS_SB(mapping->host->i_sb);
1357 1366
1358 /* 1367 /*
@@ -1362,26 +1371,28 @@ static int cifs_writepages(struct address_space *mapping,
1362 if (cifs_sb->wsize < PAGE_CACHE_SIZE) 1371 if (cifs_sb->wsize < PAGE_CACHE_SIZE)
1363 return generic_writepages(mapping, wbc); 1372 return generic_writepages(mapping, wbc);
1364 1373
1365 if ((cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->server))
1366 if (cifs_sb->tcon->ses->server->secMode &
1367 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1368 if (!experimEnabled)
1369 return generic_writepages(mapping, wbc);
1370
1371 iov = kmalloc(32 * sizeof(struct kvec), GFP_KERNEL); 1374 iov = kmalloc(32 * sizeof(struct kvec), GFP_KERNEL);
1372 if (iov == NULL) 1375 if (iov == NULL)
1373 return generic_writepages(mapping, wbc); 1376 return generic_writepages(mapping, wbc);
1374 1377
1375
1376 /* 1378 /*
1377 * BB: Is this meaningful for a non-block-device file system? 1379 * if there's no open file, then this is likely to fail too,
1378 * If it is, we should test it again after we do I/O 1380 * but it'll at least handle the return. Maybe it should be
1381 * a BUG() instead?
1379 */ 1382 */
1380 if (wbc->nonblocking && bdi_write_congested(bdi)) { 1383 open_file = find_writable_file(CIFS_I(mapping->host));
1381 wbc->encountered_congestion = 1; 1384 if (!open_file) {
1382 kfree(iov); 1385 kfree(iov);
1383 return 0; 1386 return generic_writepages(mapping, wbc);
1387 }
1388
1389 tcon = open_file->tcon;
1390 if (!experimEnabled && tcon->ses->server->secMode &
1391 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
1392 cifsFileInfo_put(open_file);
1393 return generic_writepages(mapping, wbc);
1384 } 1394 }
1395 cifsFileInfo_put(open_file);
1385 1396
1386 xid = GetXid(); 1397 xid = GetXid();
1387 1398
@@ -1486,38 +1497,33 @@ retry:
1486 break; 1497 break;
1487 } 1498 }
1488 if (n_iov) { 1499 if (n_iov) {
1489 /* Search for a writable handle every time we call
1490 * CIFSSMBWrite2. We can't rely on the last handle
1491 * we used to still be valid
1492 */
1493 open_file = find_writable_file(CIFS_I(mapping->host)); 1500 open_file = find_writable_file(CIFS_I(mapping->host));
1494 if (!open_file) { 1501 if (!open_file) {
1495 cERROR(1, "No writable handles for inode"); 1502 cERROR(1, "No writable handles for inode");
1496 rc = -EBADF; 1503 rc = -EBADF;
1497 } else { 1504 } else {
1498 tcon = open_file->tcon;
1499 long_op = cifs_write_timeout(cifsi, offset); 1505 long_op = cifs_write_timeout(cifsi, offset);
1500 rc = CIFSSMBWrite2(xid, tcon, 1506 rc = CIFSSMBWrite2(xid, tcon, open_file->netfid,
1501 open_file->netfid,
1502 bytes_to_write, offset, 1507 bytes_to_write, offset,
1503 &bytes_written, iov, n_iov, 1508 &bytes_written, iov, n_iov,
1504 long_op); 1509 long_op);
1505 cifsFileInfo_put(open_file); 1510 cifsFileInfo_put(open_file);
1506 cifs_update_eof(cifsi, offset, bytes_written); 1511 cifs_update_eof(cifsi, offset, bytes_written);
1512 }
1507 1513
1508 if (rc || bytes_written < bytes_to_write) { 1514 if (rc || bytes_written < bytes_to_write) {
1509 cERROR(1, "Write2 ret %d, wrote %d", 1515 cERROR(1, "Write2 ret %d, wrote %d",
1510 rc, bytes_written); 1516 rc, bytes_written);
1511 /* BB what if continued retry is 1517 /* BB what if continued retry is
1512 requested via mount flags? */ 1518 requested via mount flags? */
1513 if (rc == -ENOSPC) 1519 if (rc == -ENOSPC)
1514 set_bit(AS_ENOSPC, &mapping->flags); 1520 set_bit(AS_ENOSPC, &mapping->flags);
1515 else 1521 else
1516 set_bit(AS_EIO, &mapping->flags); 1522 set_bit(AS_EIO, &mapping->flags);
1517 } else { 1523 } else {
1518 cifs_stats_bytes_written(tcon, bytes_written); 1524 cifs_stats_bytes_written(tcon, bytes_written);
1519 }
1520 } 1525 }
1526
1521 for (i = 0; i < n_iov; i++) { 1527 for (i = 0; i < n_iov; i++) {
1522 page = pvec.pages[first + i]; 1528 page = pvec.pages[first + i];
1523 /* Should we also set page error on 1529 /* Should we also set page error on