diff options
author | Jeff Layton <jlayton@redhat.com> | 2008-07-23 17:28:12 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2008-07-23 17:28:12 -0400 |
commit | 8efdbde647f542ce0d303273df7ad4157caa03d0 (patch) | |
tree | d672ae108f45a0288c43605b5b39652a441aa996 /fs/cifs | |
parent | 09e50d55a9490e9b7a6fdfbf8fc078924b25ecb5 (diff) |
[CIFS] break ATTR_SIZE changes out into their own function
Move the code that handles ATTR_SIZE changes to its own function. This
makes for a smaller function and reduces the level of indentation.
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/inode.c | 151 |
1 files changed, 78 insertions, 73 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 2e904bd111c8..46e54d39461d 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -1413,6 +1413,82 @@ out_busy: | |||
1413 | return -ETXTBSY; | 1413 | return -ETXTBSY; |
1414 | } | 1414 | } |
1415 | 1415 | ||
1416 | static int | ||
1417 | cifs_set_file_size(struct inode *inode, struct iattr *attrs, | ||
1418 | int xid, char *full_path) | ||
1419 | { | ||
1420 | int rc; | ||
1421 | struct cifsFileInfo *open_file; | ||
1422 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); | ||
1423 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | ||
1424 | struct cifsTconInfo *pTcon = cifs_sb->tcon; | ||
1425 | |||
1426 | /* | ||
1427 | * To avoid spurious oplock breaks from server, in the case of | ||
1428 | * inodes that we already have open, avoid doing path based | ||
1429 | * setting of file size if we can do it by handle. | ||
1430 | * This keeps our caching token (oplock) and avoids timeouts | ||
1431 | * when the local oplock break takes longer to flush | ||
1432 | * writebehind data than the SMB timeout for the SetPathInfo | ||
1433 | * request would allow | ||
1434 | */ | ||
1435 | open_file = find_writable_file(cifsInode); | ||
1436 | if (open_file) { | ||
1437 | __u16 nfid = open_file->netfid; | ||
1438 | __u32 npid = open_file->pid; | ||
1439 | rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size, nfid, | ||
1440 | npid, false); | ||
1441 | atomic_dec(&open_file->wrtPending); | ||
1442 | cFYI(1, ("SetFSize for attrs rc = %d", rc)); | ||
1443 | if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { | ||
1444 | unsigned int bytes_written; | ||
1445 | rc = CIFSSMBWrite(xid, pTcon, nfid, 0, attrs->ia_size, | ||
1446 | &bytes_written, NULL, NULL, 1); | ||
1447 | cFYI(1, ("Wrt seteof rc %d", rc)); | ||
1448 | } | ||
1449 | } else | ||
1450 | rc = -EINVAL; | ||
1451 | |||
1452 | if (rc != 0) { | ||
1453 | /* Set file size by pathname rather than by handle | ||
1454 | either because no valid, writeable file handle for | ||
1455 | it was found or because there was an error setting | ||
1456 | it by handle */ | ||
1457 | rc = CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size, | ||
1458 | false, cifs_sb->local_nls, | ||
1459 | cifs_sb->mnt_cifs_flags & | ||
1460 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
1461 | cFYI(1, ("SetEOF by path (setattrs) rc = %d", rc)); | ||
1462 | if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { | ||
1463 | __u16 netfid; | ||
1464 | int oplock = 0; | ||
1465 | |||
1466 | rc = SMBLegacyOpen(xid, pTcon, full_path, | ||
1467 | FILE_OPEN, GENERIC_WRITE, | ||
1468 | CREATE_NOT_DIR, &netfid, &oplock, NULL, | ||
1469 | cifs_sb->local_nls, | ||
1470 | cifs_sb->mnt_cifs_flags & | ||
1471 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
1472 | if (rc == 0) { | ||
1473 | unsigned int bytes_written; | ||
1474 | rc = CIFSSMBWrite(xid, pTcon, netfid, 0, | ||
1475 | attrs->ia_size, | ||
1476 | &bytes_written, NULL, | ||
1477 | NULL, 1); | ||
1478 | cFYI(1, ("wrt seteof rc %d", rc)); | ||
1479 | CIFSSMBClose(xid, pTcon, netfid); | ||
1480 | } | ||
1481 | } | ||
1482 | } | ||
1483 | |||
1484 | if (rc == 0) { | ||
1485 | rc = cifs_vmtruncate(inode, attrs->ia_size); | ||
1486 | cifs_truncate_page(inode->i_mapping, inode->i_size); | ||
1487 | } | ||
1488 | |||
1489 | return rc; | ||
1490 | } | ||
1491 | |||
1416 | int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | 1492 | int cifs_setattr(struct dentry *direntry, struct iattr *attrs) |
1417 | { | 1493 | { |
1418 | int xid; | 1494 | int xid; |
@@ -1420,7 +1496,6 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1420 | struct cifsTconInfo *pTcon; | 1496 | struct cifsTconInfo *pTcon; |
1421 | char *full_path = NULL; | 1497 | char *full_path = NULL; |
1422 | int rc = -EACCES; | 1498 | int rc = -EACCES; |
1423 | struct cifsFileInfo *open_file = NULL; | ||
1424 | FILE_BASIC_INFO time_buf; | 1499 | FILE_BASIC_INFO time_buf; |
1425 | bool set_time = false; | 1500 | bool set_time = false; |
1426 | bool set_dosattr = false; | 1501 | bool set_dosattr = false; |
@@ -1472,78 +1547,8 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1472 | } | 1547 | } |
1473 | 1548 | ||
1474 | if (attrs->ia_valid & ATTR_SIZE) { | 1549 | if (attrs->ia_valid & ATTR_SIZE) { |
1475 | /* To avoid spurious oplock breaks from server, in the case of | 1550 | rc = cifs_set_file_size(inode, attrs, xid, full_path); |
1476 | inodes that we already have open, avoid doing path based | 1551 | if (rc != 0) |
1477 | setting of file size if we can do it by handle. | ||
1478 | This keeps our caching token (oplock) and avoids timeouts | ||
1479 | when the local oplock break takes longer to flush | ||
1480 | writebehind data than the SMB timeout for the SetPathInfo | ||
1481 | request would allow */ | ||
1482 | |||
1483 | open_file = find_writable_file(cifsInode); | ||
1484 | if (open_file) { | ||
1485 | __u16 nfid = open_file->netfid; | ||
1486 | __u32 npid = open_file->pid; | ||
1487 | rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size, | ||
1488 | nfid, npid, false); | ||
1489 | atomic_dec(&open_file->wrtPending); | ||
1490 | cFYI(1, ("SetFSize for attrs rc = %d", rc)); | ||
1491 | if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { | ||
1492 | unsigned int bytes_written; | ||
1493 | rc = CIFSSMBWrite(xid, pTcon, | ||
1494 | nfid, 0, attrs->ia_size, | ||
1495 | &bytes_written, NULL, NULL, | ||
1496 | 1 /* 45 seconds */); | ||
1497 | cFYI(1, ("Wrt seteof rc %d", rc)); | ||
1498 | } | ||
1499 | } else | ||
1500 | rc = -EINVAL; | ||
1501 | |||
1502 | if (rc != 0) { | ||
1503 | /* Set file size by pathname rather than by handle | ||
1504 | either because no valid, writeable file handle for | ||
1505 | it was found or because there was an error setting | ||
1506 | it by handle */ | ||
1507 | rc = CIFSSMBSetEOF(xid, pTcon, full_path, | ||
1508 | attrs->ia_size, false, | ||
1509 | cifs_sb->local_nls, | ||
1510 | cifs_sb->mnt_cifs_flags & | ||
1511 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
1512 | cFYI(1, ("SetEOF by path (setattrs) rc = %d", rc)); | ||
1513 | if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { | ||
1514 | __u16 netfid; | ||
1515 | int oplock = 0; | ||
1516 | |||
1517 | rc = SMBLegacyOpen(xid, pTcon, full_path, | ||
1518 | FILE_OPEN, GENERIC_WRITE, | ||
1519 | CREATE_NOT_DIR, &netfid, &oplock, | ||
1520 | NULL, cifs_sb->local_nls, | ||
1521 | cifs_sb->mnt_cifs_flags & | ||
1522 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
1523 | if (rc == 0) { | ||
1524 | unsigned int bytes_written; | ||
1525 | rc = CIFSSMBWrite(xid, pTcon, | ||
1526 | netfid, 0, | ||
1527 | attrs->ia_size, | ||
1528 | &bytes_written, NULL, | ||
1529 | NULL, 1 /* 45 sec */); | ||
1530 | cFYI(1, ("wrt seteof rc %d", rc)); | ||
1531 | CIFSSMBClose(xid, pTcon, netfid); | ||
1532 | } | ||
1533 | |||
1534 | } | ||
1535 | } | ||
1536 | |||
1537 | /* Server is ok setting allocation size implicitly - no need | ||
1538 | to call: | ||
1539 | CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size, true, | ||
1540 | cifs_sb->local_nls); | ||
1541 | */ | ||
1542 | |||
1543 | if (rc == 0) { | ||
1544 | rc = cifs_vmtruncate(inode, attrs->ia_size); | ||
1545 | cifs_truncate_page(inode->i_mapping, inode->i_size); | ||
1546 | } else | ||
1547 | goto cifs_setattr_exit; | 1552 | goto cifs_setattr_exit; |
1548 | } | 1553 | } |
1549 | 1554 | ||