Merge branch 'for-linus' of git://oss.sgi.com/xfs/xfs

* 'for-linus' of git://oss.sgi.com/xfs/xfs:
[XFS] XFS: Check for valid transaction headers in recovery
[XFS] handle memory allocation failures during log initialisation
[XFS] Account for allocated blocks when expanding directories
[XFS] Wait for all I/O on truncate to zero file size
[XFS] Fix use-after-free with log and quotas

+58 -7
+5
fs/xfs/xfs_da_btree.c
··· 1566 1566 int nmap, error, w, count, c, got, i, mapi; 1567 1567 xfs_trans_t *tp; 1568 1568 xfs_mount_t *mp; 1569 + xfs_drfsbno_t nblks; 1569 1570 1570 1571 dp = args->dp; 1571 1572 mp = dp->i_mount; 1572 1573 w = args->whichfork; 1573 1574 tp = args->trans; 1575 + nblks = dp->i_d.di_nblocks; 1576 + 1574 1577 /* 1575 1578 * For new directories adjust the file offset and block count. 1576 1579 */ ··· 1650 1647 } 1651 1648 if (mapp != &map) 1652 1649 kmem_free(mapp); 1650 + /* account for newly allocated blocks in reserved blocks total */ 1651 + args->total -= dp->i_d.di_nblocks - nblks; 1653 1652 *new_blkno = (xfs_dablk_t)bno; 1654 1653 return 0; 1655 1654 }
+6
fs/xfs/xfs_dir2.c
··· 525 525 xfs_mount_t *mp; 526 526 int nmap; /* number of bmap entries */ 527 527 xfs_trans_t *tp; 528 + xfs_drfsbno_t nblks; 528 529 529 530 xfs_dir2_trace_args_s("grow_inode", args, space); 530 531 dp = args->dp; 531 532 tp = args->trans; 532 533 mp = dp->i_mount; 534 + nblks = dp->i_d.di_nblocks; 533 535 /* 534 536 * Set lowest possible block in the space requested. 535 537 */ ··· 624 622 */ 625 623 if (mapp != &map) 626 624 kmem_free(mapp); 625 + 626 + /* account for newly allocated blocks in reserved blocks total */ 627 + args->total -= dp->i_d.di_nblocks - nblks; 627 628 *dbp = xfs_dir2_da_to_db(mp, (xfs_dablk_t)bno); 629 + 628 630 /* 629 631 * Update file's size if this is the data space and it grew. 630 632 */
+1 -1
fs/xfs/xfs_inode.c
··· 1414 1414 mp = ip->i_mount; 1415 1415 1416 1416 /* wait for the completion of any pending DIOs */ 1417 - if (new_size < ip->i_size) 1417 + if (new_size == 0 || new_size < ip->i_size) 1418 1418 vn_iowait(ip); 1419 1419 1420 1420 /*
+36 -3
fs/xfs/xfs_log.c
··· 563 563 } 564 564 565 565 mp->m_log = xlog_alloc_log(mp, log_target, blk_offset, num_bblks); 566 + if (!mp->m_log) { 567 + cmn_err(CE_WARN, "XFS: Log allocation failed: No memory!"); 568 + error = ENOMEM; 569 + goto out; 570 + } 566 571 567 572 /* 568 573 * Initialize the AIL now we have a log. ··· 606 601 return 0; 607 602 error: 608 603 xfs_log_unmount_dealloc(mp); 604 + out: 609 605 return error; 610 606 } /* xfs_log_mount */ 611 607 ··· 1223 1217 int i; 1224 1218 int iclogsize; 1225 1219 1226 - log = (xlog_t *)kmem_zalloc(sizeof(xlog_t), KM_SLEEP); 1220 + log = kmem_zalloc(sizeof(xlog_t), KM_MAYFAIL); 1221 + if (!log) 1222 + return NULL; 1227 1223 1228 1224 log->l_mp = mp; 1229 1225 log->l_targ = log_target; ··· 1257 1249 xlog_get_iclog_buffer_size(mp, log); 1258 1250 1259 1251 bp = xfs_buf_get_empty(log->l_iclog_size, mp->m_logdev_targp); 1252 + if (!bp) 1253 + goto out_free_log; 1260 1254 XFS_BUF_SET_IODONE_FUNC(bp, xlog_iodone); 1261 1255 XFS_BUF_SET_BDSTRAT_FUNC(bp, xlog_bdstrat_cb); 1262 1256 XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)1); ··· 1285 1275 iclogsize = log->l_iclog_size; 1286 1276 ASSERT(log->l_iclog_size >= 4096); 1287 1277 for (i=0; i < log->l_iclog_bufs; i++) { 1288 - *iclogp = (xlog_in_core_t *) 1289 - kmem_zalloc(sizeof(xlog_in_core_t), KM_SLEEP); 1278 + *iclogp = kmem_zalloc(sizeof(xlog_in_core_t), KM_MAYFAIL); 1279 + if (!*iclogp) 1280 + goto out_free_iclog; 1281 + 1290 1282 iclog = *iclogp; 1291 1283 iclog->ic_prev = prev_iclog; 1292 1284 prev_iclog = iclog; 1293 1285 1294 1286 bp = xfs_buf_get_noaddr(log->l_iclog_size, mp->m_logdev_targp); 1287 + if (!bp) 1288 + goto out_free_iclog; 1295 1289 if (!XFS_BUF_CPSEMA(bp)) 1296 1290 ASSERT(0); 1297 1291 XFS_BUF_SET_IODONE_FUNC(bp, xlog_iodone); ··· 1337 1323 log->l_iclog->ic_prev = prev_iclog; /* re-write 1st prev ptr */ 1338 1324 1339 1325 return log; 1326 + 1327 + out_free_iclog: 1328 + for (iclog = log->l_iclog; iclog; iclog = prev_iclog) { 1329 + prev_iclog = iclog->ic_next; 1330 + if (iclog->ic_bp) { 1331 + sv_destroy(&iclog->ic_force_wait); 1332 + sv_destroy(&iclog->ic_write_wait); 1333 + xfs_buf_free(iclog->ic_bp); 1334 + xlog_trace_iclog_dealloc(iclog); 1335 + } 1336 + kmem_free(iclog); 1337 + } 1338 + spinlock_destroy(&log->l_icloglock); 1339 + spinlock_destroy(&log->l_grant_lock); 1340 + xlog_trace_loggrant_dealloc(log); 1341 + xfs_buf_free(log->l_xbuf); 1342 + out_free_log: 1343 + kmem_free(log); 1344 + return NULL; 1340 1345 } /* xlog_alloc_log */ 1341 1346 1342 1347
+7 -1
fs/xfs/xfs_log_recover.c
··· 1419 1419 return 0; 1420 1420 item = trans->r_itemq; 1421 1421 if (item == NULL) { 1422 - ASSERT(*(uint *)dp == XFS_TRANS_HEADER_MAGIC); 1422 + /* we need to catch log corruptions here */ 1423 + if (*(uint *)dp != XFS_TRANS_HEADER_MAGIC) { 1424 + xlog_warn("XFS: xlog_recover_add_to_trans: " 1425 + "bad header magic number"); 1426 + ASSERT(0); 1427 + return XFS_ERROR(EIO); 1428 + } 1423 1429 if (len == sizeof(xfs_trans_header_t)) 1424 1430 xlog_recover_add_item(&trans->r_itemq); 1425 1431 memcpy(&trans->r_theader, dp, len); /* d, s, l */
+3 -2
fs/xfs/xfs_mount.c
··· 1245 1245 1246 1246 XFS_QM_DQPURGEALL(mp, XFS_QMOPT_QUOTALL | XFS_QMOPT_UMOUNTING); 1247 1247 1248 + if (mp->m_quotainfo) 1249 + XFS_QM_DONE(mp); 1250 + 1248 1251 /* 1249 1252 * Flush out the log synchronously so that we know for sure 1250 1253 * that nothing is pinned. This is important because bflush() ··· 1300 1297 xfs_errortag_clearall(mp, 0); 1301 1298 #endif 1302 1299 xfs_free_perag(mp); 1303 - if (mp->m_quotainfo) 1304 - XFS_QM_DONE(mp); 1305 1300 } 1306 1301 1307 1302 STATIC void