aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_vnodeops.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_vnodeops.c')
-rw-r--r--fs/xfs/xfs_vnodeops.c260
1 files changed, 126 insertions, 134 deletions
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 7c1f74531463..eaab355f5a89 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -15,6 +15,9 @@
15 * along with this program; if not, write the Free Software Foundation, 15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */ 17 */
18
19#include <linux/capability.h>
20
18#include "xfs.h" 21#include "xfs.h"
19#include "xfs_fs.h" 22#include "xfs_fs.h"
20#include "xfs_types.h" 23#include "xfs_types.h"
@@ -182,8 +185,7 @@ xfs_getattr(
182 break; 185 break;
183 } 186 }
184 187
185 vap->va_atime.tv_sec = ip->i_d.di_atime.t_sec; 188 vn_atime_to_timespec(vp, &vap->va_atime);
186 vap->va_atime.tv_nsec = ip->i_d.di_atime.t_nsec;
187 vap->va_mtime.tv_sec = ip->i_d.di_mtime.t_sec; 189 vap->va_mtime.tv_sec = ip->i_d.di_mtime.t_sec;
188 vap->va_mtime.tv_nsec = ip->i_d.di_mtime.t_nsec; 190 vap->va_mtime.tv_nsec = ip->i_d.di_mtime.t_nsec;
189 vap->va_ctime.tv_sec = ip->i_d.di_ctime.t_sec; 191 vap->va_ctime.tv_sec = ip->i_d.di_ctime.t_sec;
@@ -336,7 +338,7 @@ xfs_setattr(
336 code = XFS_QM_DQVOPALLOC(mp, ip, uid, gid, projid, qflags, 338 code = XFS_QM_DQVOPALLOC(mp, ip, uid, gid, projid, qflags,
337 &udqp, &gdqp); 339 &udqp, &gdqp);
338 if (code) 340 if (code)
339 return (code); 341 return code;
340 } 342 }
341 343
342 /* 344 /*
@@ -541,24 +543,6 @@ xfs_setattr(
541 } 543 }
542 544
543 /* 545 /*
544 * Can't set extent size unless the file is marked, or
545 * about to be marked as a realtime file.
546 *
547 * This check will be removed when fixed size extents
548 * with buffered data writes is implemented.
549 *
550 */
551 if ((mask & XFS_AT_EXTSIZE) &&
552 ((ip->i_d.di_extsize << mp->m_sb.sb_blocklog) !=
553 vap->va_extsize) &&
554 (!((ip->i_d.di_flags & XFS_DIFLAG_REALTIME) ||
555 ((mask & XFS_AT_XFLAGS) &&
556 (vap->va_xflags & XFS_XFLAG_REALTIME))))) {
557 code = XFS_ERROR(EINVAL);
558 goto error_return;
559 }
560
561 /*
562 * Can't change realtime flag if any extents are allocated. 546 * Can't change realtime flag if any extents are allocated.
563 */ 547 */
564 if ((ip->i_d.di_nextents || ip->i_delayed_blks) && 548 if ((ip->i_d.di_nextents || ip->i_delayed_blks) &&
@@ -820,13 +804,17 @@ xfs_setattr(
820 di_flags |= XFS_DIFLAG_RTINHERIT; 804 di_flags |= XFS_DIFLAG_RTINHERIT;
821 if (vap->va_xflags & XFS_XFLAG_NOSYMLINKS) 805 if (vap->va_xflags & XFS_XFLAG_NOSYMLINKS)
822 di_flags |= XFS_DIFLAG_NOSYMLINKS; 806 di_flags |= XFS_DIFLAG_NOSYMLINKS;
823 } else { 807 if (vap->va_xflags & XFS_XFLAG_EXTSZINHERIT)
808 di_flags |= XFS_DIFLAG_EXTSZINHERIT;
809 } else if ((ip->i_d.di_mode & S_IFMT) == S_IFREG) {
824 if (vap->va_xflags & XFS_XFLAG_REALTIME) { 810 if (vap->va_xflags & XFS_XFLAG_REALTIME) {
825 di_flags |= XFS_DIFLAG_REALTIME; 811 di_flags |= XFS_DIFLAG_REALTIME;
826 ip->i_iocore.io_flags |= XFS_IOCORE_RT; 812 ip->i_iocore.io_flags |= XFS_IOCORE_RT;
827 } else { 813 } else {
828 ip->i_iocore.io_flags &= ~XFS_IOCORE_RT; 814 ip->i_iocore.io_flags &= ~XFS_IOCORE_RT;
829 } 815 }
816 if (vap->va_xflags & XFS_XFLAG_EXTSIZE)
817 di_flags |= XFS_DIFLAG_EXTSIZE;
830 } 818 }
831 ip->i_d.di_flags = di_flags; 819 ip->i_d.di_flags = di_flags;
832 } 820 }
@@ -996,10 +984,6 @@ xfs_readlink(
996 goto error_return; 984 goto error_return;
997 } 985 }
998 986
999 if (!(ioflags & IO_INVIS)) {
1000 xfs_ichgtime(ip, XFS_ICHGTIME_ACC);
1001 }
1002
1003 /* 987 /*
1004 * See if the symlink is stored inline. 988 * See if the symlink is stored inline.
1005 */ 989 */
@@ -1043,11 +1027,8 @@ xfs_readlink(
1043 1027
1044 } 1028 }
1045 1029
1046
1047error_return: 1030error_return:
1048
1049 xfs_iunlock(ip, XFS_ILOCK_SHARED); 1031 xfs_iunlock(ip, XFS_ILOCK_SHARED);
1050
1051 return error; 1032 return error;
1052} 1033}
1053 1034
@@ -1222,7 +1203,7 @@ xfs_inactive_free_eofblocks(
1222 last_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_MAXIOFFSET(mp)); 1203 last_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_MAXIOFFSET(mp));
1223 map_len = last_fsb - end_fsb; 1204 map_len = last_fsb - end_fsb;
1224 if (map_len <= 0) 1205 if (map_len <= 0)
1225 return (0); 1206 return 0;
1226 1207
1227 nimaps = 1; 1208 nimaps = 1;
1228 xfs_ilock(ip, XFS_ILOCK_SHARED); 1209 xfs_ilock(ip, XFS_ILOCK_SHARED);
@@ -1231,12 +1212,13 @@ xfs_inactive_free_eofblocks(
1231 xfs_iunlock(ip, XFS_ILOCK_SHARED); 1212 xfs_iunlock(ip, XFS_ILOCK_SHARED);
1232 1213
1233 if (!error && (nimaps != 0) && 1214 if (!error && (nimaps != 0) &&
1234 (imap.br_startblock != HOLESTARTBLOCK)) { 1215 (imap.br_startblock != HOLESTARTBLOCK ||
1216 ip->i_delayed_blks)) {
1235 /* 1217 /*
1236 * Attach the dquots to the inode up front. 1218 * Attach the dquots to the inode up front.
1237 */ 1219 */
1238 if ((error = XFS_QM_DQATTACH(mp, ip, 0))) 1220 if ((error = XFS_QM_DQATTACH(mp, ip, 0)))
1239 return (error); 1221 return error;
1240 1222
1241 /* 1223 /*
1242 * There are blocks after the end of file. 1224 * There are blocks after the end of file.
@@ -1264,7 +1246,7 @@ xfs_inactive_free_eofblocks(
1264 ASSERT(XFS_FORCED_SHUTDOWN(mp)); 1246 ASSERT(XFS_FORCED_SHUTDOWN(mp));
1265 xfs_trans_cancel(tp, 0); 1247 xfs_trans_cancel(tp, 0);
1266 xfs_iunlock(ip, XFS_IOLOCK_EXCL); 1248 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
1267 return (error); 1249 return error;
1268 } 1250 }
1269 1251
1270 xfs_ilock(ip, XFS_ILOCK_EXCL); 1252 xfs_ilock(ip, XFS_ILOCK_EXCL);
@@ -1292,7 +1274,7 @@ xfs_inactive_free_eofblocks(
1292 } 1274 }
1293 xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL); 1275 xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
1294 } 1276 }
1295 return (error); 1277 return error;
1296} 1278}
1297 1279
1298/* 1280/*
@@ -1470,7 +1452,7 @@ xfs_inactive_symlink_local(
1470 if (error) { 1452 if (error) {
1471 xfs_trans_cancel(*tpp, 0); 1453 xfs_trans_cancel(*tpp, 0);
1472 *tpp = NULL; 1454 *tpp = NULL;
1473 return (error); 1455 return error;
1474 } 1456 }
1475 xfs_ilock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); 1457 xfs_ilock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
1476 1458
@@ -1483,7 +1465,7 @@ xfs_inactive_symlink_local(
1483 XFS_DATA_FORK); 1465 XFS_DATA_FORK);
1484 ASSERT(ip->i_df.if_bytes == 0); 1466 ASSERT(ip->i_df.if_bytes == 0);
1485 } 1467 }
1486 return (0); 1468 return 0;
1487} 1469}
1488 1470
1489/* 1471/*
@@ -1509,7 +1491,7 @@ xfs_inactive_attrs(
1509 if (error) { 1491 if (error) {
1510 *tpp = NULL; 1492 *tpp = NULL;
1511 xfs_iunlock(ip, XFS_IOLOCK_EXCL); 1493 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
1512 return (error); /* goto out*/ 1494 return error; /* goto out */
1513 } 1495 }
1514 1496
1515 tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE); 1497 tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE);
@@ -1522,7 +1504,7 @@ xfs_inactive_attrs(
1522 xfs_trans_cancel(tp, 0); 1504 xfs_trans_cancel(tp, 0);
1523 *tpp = NULL; 1505 *tpp = NULL;
1524 xfs_iunlock(ip, XFS_IOLOCK_EXCL); 1506 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
1525 return (error); 1507 return error;
1526 } 1508 }
1527 1509
1528 xfs_ilock(ip, XFS_ILOCK_EXCL); 1510 xfs_ilock(ip, XFS_ILOCK_EXCL);
@@ -1533,7 +1515,7 @@ xfs_inactive_attrs(
1533 ASSERT(ip->i_d.di_anextents == 0); 1515 ASSERT(ip->i_d.di_anextents == 0);
1534 1516
1535 *tpp = tp; 1517 *tpp = tp;
1536 return (0); 1518 return 0;
1537} 1519}
1538 1520
1539STATIC int 1521STATIC int
@@ -1566,11 +1548,13 @@ xfs_release(
1566 1548
1567 if (ip->i_d.di_nlink != 0) { 1549 if (ip->i_d.di_nlink != 0) {
1568 if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) && 1550 if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) &&
1569 ((ip->i_d.di_size > 0) || (VN_CACHED(vp) > 0)) && 1551 ((ip->i_d.di_size > 0) || (VN_CACHED(vp) > 0 ||
1552 ip->i_delayed_blks > 0)) &&
1570 (ip->i_df.if_flags & XFS_IFEXTENTS)) && 1553 (ip->i_df.if_flags & XFS_IFEXTENTS)) &&
1571 (!(ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC|XFS_DIFLAG_APPEND)))) { 1554 (!(ip->i_d.di_flags &
1555 (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)))) {
1572 if ((error = xfs_inactive_free_eofblocks(mp, ip))) 1556 if ((error = xfs_inactive_free_eofblocks(mp, ip)))
1573 return (error); 1557 return error;
1574 /* Update linux inode block count after free above */ 1558 /* Update linux inode block count after free above */
1575 LINVFS_GET_IP(vp)->i_blocks = XFS_FSB_TO_BB(mp, 1559 LINVFS_GET_IP(vp)->i_blocks = XFS_FSB_TO_BB(mp,
1576 ip->i_d.di_nblocks + ip->i_delayed_blks); 1560 ip->i_d.di_nblocks + ip->i_delayed_blks);
@@ -1625,7 +1609,8 @@ xfs_inactive(
1625 * only one with a reference to the inode. 1609 * only one with a reference to the inode.
1626 */ 1610 */
1627 truncate = ((ip->i_d.di_nlink == 0) && 1611 truncate = ((ip->i_d.di_nlink == 0) &&
1628 ((ip->i_d.di_size != 0) || (ip->i_d.di_nextents > 0)) && 1612 ((ip->i_d.di_size != 0) || (ip->i_d.di_nextents > 0) ||
1613 (ip->i_delayed_blks > 0)) &&
1629 ((ip->i_d.di_mode & S_IFMT) == S_IFREG)); 1614 ((ip->i_d.di_mode & S_IFMT) == S_IFREG));
1630 1615
1631 mp = ip->i_mount; 1616 mp = ip->i_mount;
@@ -1643,12 +1628,14 @@ xfs_inactive(
1643 1628
1644 if (ip->i_d.di_nlink != 0) { 1629 if (ip->i_d.di_nlink != 0) {
1645 if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) && 1630 if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) &&
1646 ((ip->i_d.di_size > 0) || (VN_CACHED(vp) > 0)) && 1631 ((ip->i_d.di_size > 0) || (VN_CACHED(vp) > 0 ||
1647 (ip->i_df.if_flags & XFS_IFEXTENTS)) && 1632 ip->i_delayed_blks > 0)) &&
1648 (!(ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC|XFS_DIFLAG_APPEND)) || 1633 (ip->i_df.if_flags & XFS_IFEXTENTS) &&
1649 (ip->i_delayed_blks != 0))) { 1634 (!(ip->i_d.di_flags &
1635 (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)) ||
1636 (ip->i_delayed_blks != 0)))) {
1650 if ((error = xfs_inactive_free_eofblocks(mp, ip))) 1637 if ((error = xfs_inactive_free_eofblocks(mp, ip)))
1651 return (VN_INACTIVE_CACHE); 1638 return VN_INACTIVE_CACHE;
1652 /* Update linux inode block count after free above */ 1639 /* Update linux inode block count after free above */
1653 LINVFS_GET_IP(vp)->i_blocks = XFS_FSB_TO_BB(mp, 1640 LINVFS_GET_IP(vp)->i_blocks = XFS_FSB_TO_BB(mp,
1654 ip->i_d.di_nblocks + ip->i_delayed_blks); 1641 ip->i_d.di_nblocks + ip->i_delayed_blks);
@@ -1659,7 +1646,7 @@ xfs_inactive(
1659 ASSERT(ip->i_d.di_nlink == 0); 1646 ASSERT(ip->i_d.di_nlink == 0);
1660 1647
1661 if ((error = XFS_QM_DQATTACH(mp, ip, 0))) 1648 if ((error = XFS_QM_DQATTACH(mp, ip, 0)))
1662 return (VN_INACTIVE_CACHE); 1649 return VN_INACTIVE_CACHE;
1663 1650
1664 tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE); 1651 tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE);
1665 if (truncate) { 1652 if (truncate) {
@@ -1682,7 +1669,7 @@ xfs_inactive(
1682 ASSERT(XFS_FORCED_SHUTDOWN(mp)); 1669 ASSERT(XFS_FORCED_SHUTDOWN(mp));
1683 xfs_trans_cancel(tp, 0); 1670 xfs_trans_cancel(tp, 0);
1684 xfs_iunlock(ip, XFS_IOLOCK_EXCL); 1671 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
1685 return (VN_INACTIVE_CACHE); 1672 return VN_INACTIVE_CACHE;
1686 } 1673 }
1687 1674
1688 xfs_ilock(ip, XFS_ILOCK_EXCL); 1675 xfs_ilock(ip, XFS_ILOCK_EXCL);
@@ -1703,7 +1690,7 @@ xfs_inactive(
1703 xfs_trans_cancel(tp, 1690 xfs_trans_cancel(tp,
1704 XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); 1691 XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
1705 xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL); 1692 xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
1706 return (VN_INACTIVE_CACHE); 1693 return VN_INACTIVE_CACHE;
1707 } 1694 }
1708 } else if ((ip->i_d.di_mode & S_IFMT) == S_IFLNK) { 1695 } else if ((ip->i_d.di_mode & S_IFMT) == S_IFLNK) {
1709 1696
@@ -1717,7 +1704,7 @@ xfs_inactive(
1717 1704
1718 if (error) { 1705 if (error) {
1719 ASSERT(tp == NULL); 1706 ASSERT(tp == NULL);
1720 return (VN_INACTIVE_CACHE); 1707 return VN_INACTIVE_CACHE;
1721 } 1708 }
1722 1709
1723 xfs_trans_ijoin(tp, ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL); 1710 xfs_trans_ijoin(tp, ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
@@ -1730,7 +1717,7 @@ xfs_inactive(
1730 if (error) { 1717 if (error) {
1731 ASSERT(XFS_FORCED_SHUTDOWN(mp)); 1718 ASSERT(XFS_FORCED_SHUTDOWN(mp));
1732 xfs_trans_cancel(tp, 0); 1719 xfs_trans_cancel(tp, 0);
1733 return (VN_INACTIVE_CACHE); 1720 return VN_INACTIVE_CACHE;
1734 } 1721 }
1735 1722
1736 xfs_ilock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); 1723 xfs_ilock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
@@ -1752,7 +1739,7 @@ xfs_inactive(
1752 * cancelled, and the inode is unlocked. Just get out. 1739 * cancelled, and the inode is unlocked. Just get out.
1753 */ 1740 */
1754 if (error) 1741 if (error)
1755 return (VN_INACTIVE_CACHE); 1742 return VN_INACTIVE_CACHE;
1756 } else if (ip->i_afp) { 1743 } else if (ip->i_afp) {
1757 xfs_idestroy_fork(ip, XFS_ATTR_FORK); 1744 xfs_idestroy_fork(ip, XFS_ATTR_FORK);
1758 } 1745 }
@@ -2059,8 +2046,8 @@ std_return:
2059 abort_return: 2046 abort_return:
2060 cancel_flags |= XFS_TRANS_ABORT; 2047 cancel_flags |= XFS_TRANS_ABORT;
2061 /* FALLTHROUGH */ 2048 /* FALLTHROUGH */
2062 error_return:
2063 2049
2050 error_return:
2064 if (tp != NULL) 2051 if (tp != NULL)
2065 xfs_trans_cancel(tp, cancel_flags); 2052 xfs_trans_cancel(tp, cancel_flags);
2066 2053
@@ -2590,7 +2577,6 @@ xfs_link(
2590 int cancel_flags; 2577 int cancel_flags;
2591 int committed; 2578 int committed;
2592 vnode_t *target_dir_vp; 2579 vnode_t *target_dir_vp;
2593 bhv_desc_t *src_bdp;
2594 int resblks; 2580 int resblks;
2595 char *target_name = VNAME(dentry); 2581 char *target_name = VNAME(dentry);
2596 int target_namelen; 2582 int target_namelen;
@@ -2603,8 +2589,7 @@ xfs_link(
2603 if (VN_ISDIR(src_vp)) 2589 if (VN_ISDIR(src_vp))
2604 return XFS_ERROR(EPERM); 2590 return XFS_ERROR(EPERM);
2605 2591
2606 src_bdp = vn_bhv_lookup_unlocked(VN_BHV_HEAD(src_vp), &xfs_vnodeops); 2592 sip = xfs_vtoi(src_vp);
2607 sip = XFS_BHVTOI(src_bdp);
2608 tdp = XFS_BHVTOI(target_dir_bdp); 2593 tdp = XFS_BHVTOI(target_dir_bdp);
2609 mp = tdp->i_mount; 2594 mp = tdp->i_mount;
2610 if (XFS_FORCED_SHUTDOWN(mp)) 2595 if (XFS_FORCED_SHUTDOWN(mp))
@@ -2736,9 +2721,9 @@ std_return:
2736 abort_return: 2721 abort_return:
2737 cancel_flags |= XFS_TRANS_ABORT; 2722 cancel_flags |= XFS_TRANS_ABORT;
2738 /* FALLTHROUGH */ 2723 /* FALLTHROUGH */
2724
2739 error_return: 2725 error_return:
2740 xfs_trans_cancel(tp, cancel_flags); 2726 xfs_trans_cancel(tp, cancel_flags);
2741
2742 goto std_return; 2727 goto std_return;
2743} 2728}
2744/* 2729/*
@@ -3211,10 +3196,12 @@ std_return:
3211 } 3196 }
3212 return error; 3197 return error;
3213 3198
3214 error1: 3199error1:
3215 xfs_bmap_cancel(&free_list); 3200 xfs_bmap_cancel(&free_list);
3216 cancel_flags |= XFS_TRANS_ABORT; 3201 cancel_flags |= XFS_TRANS_ABORT;
3217 error_return: 3202 /* FALLTHROUGH */
3203
3204error_return:
3218 xfs_trans_cancel(tp, cancel_flags); 3205 xfs_trans_cancel(tp, cancel_flags);
3219 goto std_return; 3206 goto std_return;
3220} 3207}
@@ -3237,7 +3224,6 @@ xfs_readdir(
3237 xfs_trans_t *tp = NULL; 3224 xfs_trans_t *tp = NULL;
3238 int error = 0; 3225 int error = 0;
3239 uint lock_mode; 3226 uint lock_mode;
3240 xfs_off_t start_offset;
3241 3227
3242 vn_trace_entry(BHV_TO_VNODE(dir_bdp), __FUNCTION__, 3228 vn_trace_entry(BHV_TO_VNODE(dir_bdp), __FUNCTION__,
3243 (inst_t *)__return_address); 3229 (inst_t *)__return_address);
@@ -3248,11 +3234,7 @@ xfs_readdir(
3248 } 3234 }
3249 3235
3250 lock_mode = xfs_ilock_map_shared(dp); 3236 lock_mode = xfs_ilock_map_shared(dp);
3251 start_offset = uiop->uio_offset;
3252 error = XFS_DIR_GETDENTS(dp->i_mount, tp, dp, uiop, eofp); 3237 error = XFS_DIR_GETDENTS(dp->i_mount, tp, dp, uiop, eofp);
3253 if (start_offset != uiop->uio_offset) {
3254 xfs_ichgtime(dp, XFS_ICHGTIME_ACC);
3255 }
3256 xfs_iunlock_map_shared(dp, lock_mode); 3238 xfs_iunlock_map_shared(dp, lock_mode);
3257 return error; 3239 return error;
3258} 3240}
@@ -3635,9 +3617,9 @@ xfs_rwlock(
3635 if (locktype == VRWLOCK_WRITE) { 3617 if (locktype == VRWLOCK_WRITE) {
3636 xfs_ilock(ip, XFS_IOLOCK_EXCL); 3618 xfs_ilock(ip, XFS_IOLOCK_EXCL);
3637 } else if (locktype == VRWLOCK_TRY_READ) { 3619 } else if (locktype == VRWLOCK_TRY_READ) {
3638 return (xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED)); 3620 return xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED);
3639 } else if (locktype == VRWLOCK_TRY_WRITE) { 3621 } else if (locktype == VRWLOCK_TRY_WRITE) {
3640 return (xfs_ilock_nowait(ip, XFS_IOLOCK_EXCL)); 3622 return xfs_ilock_nowait(ip, XFS_IOLOCK_EXCL);
3641 } else { 3623 } else {
3642 ASSERT((locktype == VRWLOCK_READ) || 3624 ASSERT((locktype == VRWLOCK_READ) ||
3643 (locktype == VRWLOCK_WRITE_DIRECT)); 3625 (locktype == VRWLOCK_WRITE_DIRECT));
@@ -3829,7 +3811,12 @@ xfs_reclaim(
3829 vn_iowait(vp); 3811 vn_iowait(vp);
3830 3812
3831 ASSERT(XFS_FORCED_SHUTDOWN(ip->i_mount) || ip->i_delayed_blks == 0); 3813 ASSERT(XFS_FORCED_SHUTDOWN(ip->i_mount) || ip->i_delayed_blks == 0);
3832 ASSERT(VN_CACHED(vp) == 0); 3814
3815 /*
3816 * Make sure the atime in the XFS inode is correct before freeing the
3817 * Linux inode.
3818 */
3819 xfs_synchronize_atime(ip);
3833 3820
3834 /* If we have nothing to flush with this inode then complete the 3821 /* If we have nothing to flush with this inode then complete the
3835 * teardown now, otherwise break the link between the xfs inode 3822 * teardown now, otherwise break the link between the xfs inode
@@ -3880,7 +3867,7 @@ xfs_finish_reclaim(
3880 xfs_ifunlock(ip); 3867 xfs_ifunlock(ip);
3881 xfs_iunlock(ip, XFS_ILOCK_EXCL); 3868 xfs_iunlock(ip, XFS_ILOCK_EXCL);
3882 } 3869 }
3883 return(1); 3870 return 1;
3884 } 3871 }
3885 ip->i_flags |= XFS_IRECLAIM; 3872 ip->i_flags |= XFS_IRECLAIM;
3886 write_unlock(&ih->ih_lock); 3873 write_unlock(&ih->ih_lock);
@@ -3958,8 +3945,9 @@ xfs_finish_reclaim_all(xfs_mount_t *mp, int noblock)
3958 } 3945 }
3959 } 3946 }
3960 XFS_MOUNT_IUNLOCK(mp); 3947 XFS_MOUNT_IUNLOCK(mp);
3961 xfs_finish_reclaim(ip, noblock, 3948 if (xfs_finish_reclaim(ip, noblock,
3962 XFS_IFLUSH_DELWRI_ELSE_ASYNC); 3949 XFS_IFLUSH_DELWRI_ELSE_ASYNC))
3950 delay(1);
3963 purged = 1; 3951 purged = 1;
3964 break; 3952 break;
3965 } 3953 }
@@ -3998,42 +3986,36 @@ xfs_alloc_file_space(
3998 int alloc_type, 3986 int alloc_type,
3999 int attr_flags) 3987 int attr_flags)
4000{ 3988{
3989 xfs_mount_t *mp = ip->i_mount;
3990 xfs_off_t count;
4001 xfs_filblks_t allocated_fsb; 3991 xfs_filblks_t allocated_fsb;
4002 xfs_filblks_t allocatesize_fsb; 3992 xfs_filblks_t allocatesize_fsb;
4003 int committed; 3993 xfs_extlen_t extsz, temp;
4004 xfs_off_t count; 3994 xfs_fileoff_t startoffset_fsb;
4005 xfs_filblks_t datablocks;
4006 int error;
4007 xfs_fsblock_t firstfsb; 3995 xfs_fsblock_t firstfsb;
4008 xfs_bmap_free_t free_list; 3996 int nimaps;
4009 xfs_bmbt_irec_t *imapp; 3997 int bmapi_flag;
4010 xfs_bmbt_irec_t imaps[1]; 3998 int quota_flag;
4011 xfs_mount_t *mp;
4012 int numrtextents;
4013 int reccount;
4014 uint resblks;
4015 int rt; 3999 int rt;
4016 int rtextsize;
4017 xfs_fileoff_t startoffset_fsb;
4018 xfs_trans_t *tp; 4000 xfs_trans_t *tp;
4019 int xfs_bmapi_flags; 4001 xfs_bmbt_irec_t imaps[1], *imapp;
4002 xfs_bmap_free_t free_list;
4003 uint qblocks, resblks, resrtextents;
4004 int committed;
4005 int error;
4020 4006
4021 vn_trace_entry(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address); 4007 vn_trace_entry(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address);
4022 mp = ip->i_mount;
4023 4008
4024 if (XFS_FORCED_SHUTDOWN(mp)) 4009 if (XFS_FORCED_SHUTDOWN(mp))
4025 return XFS_ERROR(EIO); 4010 return XFS_ERROR(EIO);
4026 4011
4027 /* 4012 rt = XFS_IS_REALTIME_INODE(ip);
4028 * determine if this is a realtime file 4013 if (unlikely(rt)) {
4029 */ 4014 if (!(extsz = ip->i_d.di_extsize))
4030 if ((rt = XFS_IS_REALTIME_INODE(ip)) != 0) { 4015 extsz = mp->m_sb.sb_rextsize;
4031 if (ip->i_d.di_extsize) 4016 } else {
4032 rtextsize = ip->i_d.di_extsize; 4017 extsz = ip->i_d.di_extsize;
4033 else 4018 }
4034 rtextsize = mp->m_sb.sb_rextsize;
4035 } else
4036 rtextsize = 0;
4037 4019
4038 if ((error = XFS_QM_DQATTACH(mp, ip, 0))) 4020 if ((error = XFS_QM_DQATTACH(mp, ip, 0)))
4039 return error; 4021 return error;
@@ -4044,8 +4026,8 @@ xfs_alloc_file_space(
4044 count = len; 4026 count = len;
4045 error = 0; 4027 error = 0;
4046 imapp = &imaps[0]; 4028 imapp = &imaps[0];
4047 reccount = 1; 4029 nimaps = 1;
4048 xfs_bmapi_flags = XFS_BMAPI_WRITE | (alloc_type ? XFS_BMAPI_PREALLOC : 0); 4030 bmapi_flag = XFS_BMAPI_WRITE | (alloc_type ? XFS_BMAPI_PREALLOC : 0);
4049 startoffset_fsb = XFS_B_TO_FSBT(mp, offset); 4031 startoffset_fsb = XFS_B_TO_FSBT(mp, offset);
4050 allocatesize_fsb = XFS_B_TO_FSB(mp, count); 4032 allocatesize_fsb = XFS_B_TO_FSB(mp, count);
4051 4033
@@ -4062,47 +4044,55 @@ xfs_alloc_file_space(
4062 offset, end_dmi_offset - offset, 4044 offset, end_dmi_offset - offset,
4063 0, NULL); 4045 0, NULL);
4064 if (error) 4046 if (error)
4065 return(error); 4047 return error;
4066 } 4048 }
4067 4049
4068 /* 4050 /*
4069 * allocate file space until done or until there is an error 4051 * Allocate file space until done or until there is an error
4070 */ 4052 */
4071retry: 4053retry:
4072 while (allocatesize_fsb && !error) { 4054 while (allocatesize_fsb && !error) {
4055 xfs_fileoff_t s, e;
4056
4073 /* 4057 /*
4074 * determine if reserving space on 4058 * Determine space reservations for data/realtime.
4075 * the data or realtime partition.
4076 */ 4059 */
4077 if (rt) { 4060 if (unlikely(extsz)) {
4078 xfs_fileoff_t s, e;
4079
4080 s = startoffset_fsb; 4061 s = startoffset_fsb;
4081 do_div(s, rtextsize); 4062 do_div(s, extsz);
4082 s *= rtextsize; 4063 s *= extsz;
4083 e = roundup_64(startoffset_fsb + allocatesize_fsb, 4064 e = startoffset_fsb + allocatesize_fsb;
4084 rtextsize); 4065 if ((temp = do_mod(startoffset_fsb, extsz)))
4085 numrtextents = (int)(e - s) / mp->m_sb.sb_rextsize; 4066 e += temp;
4086 datablocks = 0; 4067 if ((temp = do_mod(e, extsz)))
4068 e += extsz - temp;
4087 } else { 4069 } else {
4088 datablocks = allocatesize_fsb; 4070 s = 0;
4089 numrtextents = 0; 4071 e = allocatesize_fsb;
4072 }
4073
4074 if (unlikely(rt)) {
4075 resrtextents = qblocks = (uint)(e - s);
4076 resrtextents /= mp->m_sb.sb_rextsize;
4077 resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
4078 quota_flag = XFS_QMOPT_RES_RTBLKS;
4079 } else {
4080 resrtextents = 0;
4081 resblks = qblocks = \
4082 XFS_DIOSTRAT_SPACE_RES(mp, (uint)(e - s));
4083 quota_flag = XFS_QMOPT_RES_REGBLKS;
4090 } 4084 }
4091 4085
4092 /* 4086 /*
4093 * allocate and setup the transaction 4087 * Allocate and setup the transaction.
4094 */ 4088 */
4095 tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT); 4089 tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT);
4096 resblks = XFS_DIOSTRAT_SPACE_RES(mp, datablocks); 4090 error = xfs_trans_reserve(tp, resblks,
4097 error = xfs_trans_reserve(tp, 4091 XFS_WRITE_LOG_RES(mp), resrtextents,
4098 resblks,
4099 XFS_WRITE_LOG_RES(mp),
4100 numrtextents,
4101 XFS_TRANS_PERM_LOG_RES, 4092 XFS_TRANS_PERM_LOG_RES,
4102 XFS_WRITE_LOG_COUNT); 4093 XFS_WRITE_LOG_COUNT);
4103
4104 /* 4094 /*
4105 * check for running out of space 4095 * Check for running out of space
4106 */ 4096 */
4107 if (error) { 4097 if (error) {
4108 /* 4098 /*
@@ -4113,8 +4103,8 @@ retry:
4113 break; 4103 break;
4114 } 4104 }
4115 xfs_ilock(ip, XFS_ILOCK_EXCL); 4105 xfs_ilock(ip, XFS_ILOCK_EXCL);
4116 error = XFS_TRANS_RESERVE_QUOTA(mp, tp, 4106 error = XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip,
4117 ip->i_udquot, ip->i_gdquot, resblks, 0, 0); 4107 qblocks, 0, quota_flag);
4118 if (error) 4108 if (error)
4119 goto error1; 4109 goto error1;
4120 4110
@@ -4122,19 +4112,19 @@ retry:
4122 xfs_trans_ihold(tp, ip); 4112 xfs_trans_ihold(tp, ip);
4123 4113
4124 /* 4114 /*
4125 * issue the bmapi() call to allocate the blocks 4115 * Issue the xfs_bmapi() call to allocate the blocks
4126 */ 4116 */
4127 XFS_BMAP_INIT(&free_list, &firstfsb); 4117 XFS_BMAP_INIT(&free_list, &firstfsb);
4128 error = xfs_bmapi(tp, ip, startoffset_fsb, 4118 error = xfs_bmapi(tp, ip, startoffset_fsb,
4129 allocatesize_fsb, xfs_bmapi_flags, 4119 allocatesize_fsb, bmapi_flag,
4130 &firstfsb, 0, imapp, &reccount, 4120 &firstfsb, 0, imapp, &nimaps,
4131 &free_list); 4121 &free_list);
4132 if (error) { 4122 if (error) {
4133 goto error0; 4123 goto error0;
4134 } 4124 }
4135 4125
4136 /* 4126 /*
4137 * complete the transaction 4127 * Complete the transaction
4138 */ 4128 */
4139 error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed); 4129 error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed);
4140 if (error) { 4130 if (error) {
@@ -4149,7 +4139,7 @@ retry:
4149 4139
4150 allocated_fsb = imapp->br_blockcount; 4140 allocated_fsb = imapp->br_blockcount;
4151 4141
4152 if (reccount == 0) { 4142 if (nimaps == 0) {
4153 error = XFS_ERROR(ENOSPC); 4143 error = XFS_ERROR(ENOSPC);
4154 break; 4144 break;
4155 } 4145 }
@@ -4172,9 +4162,11 @@ dmapi_enospc_check:
4172 4162
4173 return error; 4163 return error;
4174 4164
4175 error0: 4165error0: /* Cancel bmap, unlock inode, unreserve quota blocks, cancel trans */
4176 xfs_bmap_cancel(&free_list); 4166 xfs_bmap_cancel(&free_list);
4177 error1: 4167 XFS_TRANS_UNRESERVE_QUOTA_NBLKS(mp, tp, ip, qblocks, 0, quota_flag);
4168
4169error1: /* Just cancel transaction */
4178 xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); 4170 xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
4179 xfs_iunlock(ip, XFS_ILOCK_EXCL); 4171 xfs_iunlock(ip, XFS_ILOCK_EXCL);
4180 goto dmapi_enospc_check; 4172 goto dmapi_enospc_check;
@@ -4312,7 +4304,7 @@ xfs_free_file_space(
4312 offset, end_dmi_offset - offset, 4304 offset, end_dmi_offset - offset,
4313 AT_DELAY_FLAG(attr_flags), NULL); 4305 AT_DELAY_FLAG(attr_flags), NULL);
4314 if (error) 4306 if (error)
4315 return(error); 4307 return error;
4316 } 4308 }
4317 4309
4318 ASSERT(attr_flags & ATTR_NOLOCK ? attr_flags & ATTR_DMI : 1); 4310 ASSERT(attr_flags & ATTR_NOLOCK ? attr_flags & ATTR_DMI : 1);
@@ -4419,8 +4411,8 @@ xfs_free_file_space(
4419 } 4411 }
4420 xfs_ilock(ip, XFS_ILOCK_EXCL); 4412 xfs_ilock(ip, XFS_ILOCK_EXCL);
4421 error = XFS_TRANS_RESERVE_QUOTA(mp, tp, 4413 error = XFS_TRANS_RESERVE_QUOTA(mp, tp,
4422 ip->i_udquot, ip->i_gdquot, resblks, 0, rt ? 4414 ip->i_udquot, ip->i_gdquot, resblks, 0,
4423 XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS); 4415 XFS_QMOPT_RES_REGBLKS);
4424 if (error) 4416 if (error)
4425 goto error1; 4417 goto error1;
4426 4418