diff options
Diffstat (limited to 'fs/xfs/xfs_vnodeops.c')
-rw-r--r-- | fs/xfs/xfs_vnodeops.c | 74 |
1 files changed, 22 insertions, 52 deletions
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index d8e6f8cd6f0c..37d8146ee15b 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c | |||
@@ -1189,9 +1189,8 @@ xfs_inactive( | |||
1189 | * inode might be lost for a long time or forever. | 1189 | * inode might be lost for a long time or forever. |
1190 | */ | 1190 | */ |
1191 | if (!XFS_FORCED_SHUTDOWN(mp)) { | 1191 | if (!XFS_FORCED_SHUTDOWN(mp)) { |
1192 | cmn_err(CE_NOTE, | 1192 | xfs_notice(mp, "%s: xfs_ifree returned error %d", |
1193 | "xfs_inactive: xfs_ifree() returned an error = %d on %s", | 1193 | __func__, error); |
1194 | error, mp->m_fsname); | ||
1195 | xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR); | 1194 | xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR); |
1196 | } | 1195 | } |
1197 | xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT); | 1196 | xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT); |
@@ -1208,12 +1207,12 @@ xfs_inactive( | |||
1208 | */ | 1207 | */ |
1209 | error = xfs_bmap_finish(&tp, &free_list, &committed); | 1208 | error = xfs_bmap_finish(&tp, &free_list, &committed); |
1210 | if (error) | 1209 | if (error) |
1211 | xfs_fs_cmn_err(CE_NOTE, mp, "xfs_inactive: " | 1210 | xfs_notice(mp, "%s: xfs_bmap_finish returned error %d", |
1212 | "xfs_bmap_finish() returned error %d", error); | 1211 | __func__, error); |
1213 | error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); | 1212 | error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); |
1214 | if (error) | 1213 | if (error) |
1215 | xfs_fs_cmn_err(CE_NOTE, mp, "xfs_inactive: " | 1214 | xfs_notice(mp, "%s: xfs_trans_commit returned error %d", |
1216 | "xfs_trans_commit() returned error %d", error); | 1215 | __func__, error); |
1217 | } | 1216 | } |
1218 | 1217 | ||
1219 | /* | 1218 | /* |
@@ -1310,7 +1309,7 @@ xfs_create( | |||
1310 | error = xfs_qm_vop_dqalloc(dp, current_fsuid(), current_fsgid(), prid, | 1309 | error = xfs_qm_vop_dqalloc(dp, current_fsuid(), current_fsgid(), prid, |
1311 | XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp); | 1310 | XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp); |
1312 | if (error) | 1311 | if (error) |
1313 | goto std_return; | 1312 | return error; |
1314 | 1313 | ||
1315 | if (is_dir) { | 1314 | if (is_dir) { |
1316 | rdev = 0; | 1315 | rdev = 0; |
@@ -1390,12 +1389,6 @@ xfs_create( | |||
1390 | } | 1389 | } |
1391 | 1390 | ||
1392 | /* | 1391 | /* |
1393 | * At this point, we've gotten a newly allocated inode. | ||
1394 | * It is locked (and joined to the transaction). | ||
1395 | */ | ||
1396 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); | ||
1397 | |||
1398 | /* | ||
1399 | * Now we join the directory inode to the transaction. We do not do it | 1392 | * Now we join the directory inode to the transaction. We do not do it |
1400 | * earlier because xfs_dir_ialloc might commit the previous transaction | 1393 | * earlier because xfs_dir_ialloc might commit the previous transaction |
1401 | * (and release all the locks). An error from here on will result in | 1394 | * (and release all the locks). An error from here on will result in |
@@ -1440,22 +1433,13 @@ xfs_create( | |||
1440 | */ | 1433 | */ |
1441 | xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp); | 1434 | xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp); |
1442 | 1435 | ||
1443 | /* | ||
1444 | * xfs_trans_commit normally decrements the vnode ref count | ||
1445 | * when it unlocks the inode. Since we want to return the | ||
1446 | * vnode to the caller, we bump the vnode ref count now. | ||
1447 | */ | ||
1448 | IHOLD(ip); | ||
1449 | |||
1450 | error = xfs_bmap_finish(&tp, &free_list, &committed); | 1436 | error = xfs_bmap_finish(&tp, &free_list, &committed); |
1451 | if (error) | 1437 | if (error) |
1452 | goto out_abort_rele; | 1438 | goto out_bmap_cancel; |
1453 | 1439 | ||
1454 | error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); | 1440 | error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); |
1455 | if (error) { | 1441 | if (error) |
1456 | IRELE(ip); | 1442 | goto out_release_inode; |
1457 | goto out_dqrele; | ||
1458 | } | ||
1459 | 1443 | ||
1460 | xfs_qm_dqrele(udqp); | 1444 | xfs_qm_dqrele(udqp); |
1461 | xfs_qm_dqrele(gdqp); | 1445 | xfs_qm_dqrele(gdqp); |
@@ -1469,27 +1453,21 @@ xfs_create( | |||
1469 | cancel_flags |= XFS_TRANS_ABORT; | 1453 | cancel_flags |= XFS_TRANS_ABORT; |
1470 | out_trans_cancel: | 1454 | out_trans_cancel: |
1471 | xfs_trans_cancel(tp, cancel_flags); | 1455 | xfs_trans_cancel(tp, cancel_flags); |
1472 | out_dqrele: | 1456 | out_release_inode: |
1457 | /* | ||
1458 | * Wait until after the current transaction is aborted to | ||
1459 | * release the inode. This prevents recursive transactions | ||
1460 | * and deadlocks from xfs_inactive. | ||
1461 | */ | ||
1462 | if (ip) | ||
1463 | IRELE(ip); | ||
1464 | |||
1473 | xfs_qm_dqrele(udqp); | 1465 | xfs_qm_dqrele(udqp); |
1474 | xfs_qm_dqrele(gdqp); | 1466 | xfs_qm_dqrele(gdqp); |
1475 | 1467 | ||
1476 | if (unlock_dp_on_error) | 1468 | if (unlock_dp_on_error) |
1477 | xfs_iunlock(dp, XFS_ILOCK_EXCL); | 1469 | xfs_iunlock(dp, XFS_ILOCK_EXCL); |
1478 | std_return: | ||
1479 | return error; | 1470 | return error; |
1480 | |||
1481 | out_abort_rele: | ||
1482 | /* | ||
1483 | * Wait until after the current transaction is aborted to | ||
1484 | * release the inode. This prevents recursive transactions | ||
1485 | * and deadlocks from xfs_inactive. | ||
1486 | */ | ||
1487 | xfs_bmap_cancel(&free_list); | ||
1488 | cancel_flags |= XFS_TRANS_ABORT; | ||
1489 | xfs_trans_cancel(tp, cancel_flags); | ||
1490 | IRELE(ip); | ||
1491 | unlock_dp_on_error = B_FALSE; | ||
1492 | goto out_dqrele; | ||
1493 | } | 1471 | } |
1494 | 1472 | ||
1495 | #ifdef DEBUG | 1473 | #ifdef DEBUG |
@@ -2114,9 +2092,8 @@ xfs_symlink( | |||
2114 | XFS_BMAPI_WRITE | XFS_BMAPI_METADATA, | 2092 | XFS_BMAPI_WRITE | XFS_BMAPI_METADATA, |
2115 | &first_block, resblks, mval, &nmaps, | 2093 | &first_block, resblks, mval, &nmaps, |
2116 | &free_list); | 2094 | &free_list); |
2117 | if (error) { | 2095 | if (error) |
2118 | goto error1; | 2096 | goto error2; |
2119 | } | ||
2120 | 2097 | ||
2121 | if (resblks) | 2098 | if (resblks) |
2122 | resblks -= fs_blocks; | 2099 | resblks -= fs_blocks; |
@@ -2148,7 +2125,7 @@ xfs_symlink( | |||
2148 | error = xfs_dir_createname(tp, dp, link_name, ip->i_ino, | 2125 | error = xfs_dir_createname(tp, dp, link_name, ip->i_ino, |
2149 | &first_block, &free_list, resblks); | 2126 | &first_block, &free_list, resblks); |
2150 | if (error) | 2127 | if (error) |
2151 | goto error1; | 2128 | goto error2; |
2152 | xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); | 2129 | xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); |
2153 | xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); | 2130 | xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); |
2154 | 2131 | ||
@@ -2161,13 +2138,6 @@ xfs_symlink( | |||
2161 | xfs_trans_set_sync(tp); | 2138 | xfs_trans_set_sync(tp); |
2162 | } | 2139 | } |
2163 | 2140 | ||
2164 | /* | ||
2165 | * xfs_trans_commit normally decrements the vnode ref count | ||
2166 | * when it unlocks the inode. Since we want to return the | ||
2167 | * vnode to the caller, we bump the vnode ref count now. | ||
2168 | */ | ||
2169 | IHOLD(ip); | ||
2170 | |||
2171 | error = xfs_bmap_finish(&tp, &free_list, &committed); | 2141 | error = xfs_bmap_finish(&tp, &free_list, &committed); |
2172 | if (error) { | 2142 | if (error) { |
2173 | goto error2; | 2143 | goto error2; |