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
This commit is contained in:
commit
04ca2c17e3
@ -1566,11 +1566,14 @@ xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno)
|
||||
int nmap, error, w, count, c, got, i, mapi;
|
||||
xfs_trans_t *tp;
|
||||
xfs_mount_t *mp;
|
||||
xfs_drfsbno_t nblks;
|
||||
|
||||
dp = args->dp;
|
||||
mp = dp->i_mount;
|
||||
w = args->whichfork;
|
||||
tp = args->trans;
|
||||
nblks = dp->i_d.di_nblocks;
|
||||
|
||||
/*
|
||||
* For new directories adjust the file offset and block count.
|
||||
*/
|
||||
@ -1647,6 +1650,8 @@ xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno)
|
||||
}
|
||||
if (mapp != &map)
|
||||
kmem_free(mapp);
|
||||
/* account for newly allocated blocks in reserved blocks total */
|
||||
args->total -= dp->i_d.di_nblocks - nblks;
|
||||
*new_blkno = (xfs_dablk_t)bno;
|
||||
return 0;
|
||||
}
|
||||
|
@ -525,11 +525,13 @@ xfs_dir2_grow_inode(
|
||||
xfs_mount_t *mp;
|
||||
int nmap; /* number of bmap entries */
|
||||
xfs_trans_t *tp;
|
||||
xfs_drfsbno_t nblks;
|
||||
|
||||
xfs_dir2_trace_args_s("grow_inode", args, space);
|
||||
dp = args->dp;
|
||||
tp = args->trans;
|
||||
mp = dp->i_mount;
|
||||
nblks = dp->i_d.di_nblocks;
|
||||
/*
|
||||
* Set lowest possible block in the space requested.
|
||||
*/
|
||||
@ -622,7 +624,11 @@ xfs_dir2_grow_inode(
|
||||
*/
|
||||
if (mapp != &map)
|
||||
kmem_free(mapp);
|
||||
|
||||
/* account for newly allocated blocks in reserved blocks total */
|
||||
args->total -= dp->i_d.di_nblocks - nblks;
|
||||
*dbp = xfs_dir2_da_to_db(mp, (xfs_dablk_t)bno);
|
||||
|
||||
/*
|
||||
* Update file's size if this is the data space and it grew.
|
||||
*/
|
||||
|
@ -1414,7 +1414,7 @@ xfs_itruncate_start(
|
||||
mp = ip->i_mount;
|
||||
|
||||
/* wait for the completion of any pending DIOs */
|
||||
if (new_size < ip->i_size)
|
||||
if (new_size == 0 || new_size < ip->i_size)
|
||||
vn_iowait(ip);
|
||||
|
||||
/*
|
||||
|
@ -563,6 +563,11 @@ xfs_log_mount(
|
||||
}
|
||||
|
||||
mp->m_log = xlog_alloc_log(mp, log_target, blk_offset, num_bblks);
|
||||
if (!mp->m_log) {
|
||||
cmn_err(CE_WARN, "XFS: Log allocation failed: No memory!");
|
||||
error = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the AIL now we have a log.
|
||||
@ -601,6 +606,7 @@ xfs_log_mount(
|
||||
return 0;
|
||||
error:
|
||||
xfs_log_unmount_dealloc(mp);
|
||||
out:
|
||||
return error;
|
||||
} /* xfs_log_mount */
|
||||
|
||||
@ -1217,7 +1223,9 @@ xlog_alloc_log(xfs_mount_t *mp,
|
||||
int i;
|
||||
int iclogsize;
|
||||
|
||||
log = (xlog_t *)kmem_zalloc(sizeof(xlog_t), KM_SLEEP);
|
||||
log = kmem_zalloc(sizeof(xlog_t), KM_MAYFAIL);
|
||||
if (!log)
|
||||
return NULL;
|
||||
|
||||
log->l_mp = mp;
|
||||
log->l_targ = log_target;
|
||||
@ -1249,6 +1257,8 @@ xlog_alloc_log(xfs_mount_t *mp,
|
||||
xlog_get_iclog_buffer_size(mp, log);
|
||||
|
||||
bp = xfs_buf_get_empty(log->l_iclog_size, mp->m_logdev_targp);
|
||||
if (!bp)
|
||||
goto out_free_log;
|
||||
XFS_BUF_SET_IODONE_FUNC(bp, xlog_iodone);
|
||||
XFS_BUF_SET_BDSTRAT_FUNC(bp, xlog_bdstrat_cb);
|
||||
XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)1);
|
||||
@ -1275,13 +1285,17 @@ xlog_alloc_log(xfs_mount_t *mp,
|
||||
iclogsize = log->l_iclog_size;
|
||||
ASSERT(log->l_iclog_size >= 4096);
|
||||
for (i=0; i < log->l_iclog_bufs; i++) {
|
||||
*iclogp = (xlog_in_core_t *)
|
||||
kmem_zalloc(sizeof(xlog_in_core_t), KM_SLEEP);
|
||||
*iclogp = kmem_zalloc(sizeof(xlog_in_core_t), KM_MAYFAIL);
|
||||
if (!*iclogp)
|
||||
goto out_free_iclog;
|
||||
|
||||
iclog = *iclogp;
|
||||
iclog->ic_prev = prev_iclog;
|
||||
prev_iclog = iclog;
|
||||
|
||||
bp = xfs_buf_get_noaddr(log->l_iclog_size, mp->m_logdev_targp);
|
||||
if (!bp)
|
||||
goto out_free_iclog;
|
||||
if (!XFS_BUF_CPSEMA(bp))
|
||||
ASSERT(0);
|
||||
XFS_BUF_SET_IODONE_FUNC(bp, xlog_iodone);
|
||||
@ -1323,6 +1337,25 @@ xlog_alloc_log(xfs_mount_t *mp,
|
||||
log->l_iclog->ic_prev = prev_iclog; /* re-write 1st prev ptr */
|
||||
|
||||
return log;
|
||||
|
||||
out_free_iclog:
|
||||
for (iclog = log->l_iclog; iclog; iclog = prev_iclog) {
|
||||
prev_iclog = iclog->ic_next;
|
||||
if (iclog->ic_bp) {
|
||||
sv_destroy(&iclog->ic_force_wait);
|
||||
sv_destroy(&iclog->ic_write_wait);
|
||||
xfs_buf_free(iclog->ic_bp);
|
||||
xlog_trace_iclog_dealloc(iclog);
|
||||
}
|
||||
kmem_free(iclog);
|
||||
}
|
||||
spinlock_destroy(&log->l_icloglock);
|
||||
spinlock_destroy(&log->l_grant_lock);
|
||||
xlog_trace_loggrant_dealloc(log);
|
||||
xfs_buf_free(log->l_xbuf);
|
||||
out_free_log:
|
||||
kmem_free(log);
|
||||
return NULL;
|
||||
} /* xlog_alloc_log */
|
||||
|
||||
|
||||
|
@ -1419,7 +1419,13 @@ xlog_recover_add_to_trans(
|
||||
return 0;
|
||||
item = trans->r_itemq;
|
||||
if (item == NULL) {
|
||||
ASSERT(*(uint *)dp == XFS_TRANS_HEADER_MAGIC);
|
||||
/* we need to catch log corruptions here */
|
||||
if (*(uint *)dp != XFS_TRANS_HEADER_MAGIC) {
|
||||
xlog_warn("XFS: xlog_recover_add_to_trans: "
|
||||
"bad header magic number");
|
||||
ASSERT(0);
|
||||
return XFS_ERROR(EIO);
|
||||
}
|
||||
if (len == sizeof(xfs_trans_header_t))
|
||||
xlog_recover_add_item(&trans->r_itemq);
|
||||
memcpy(&trans->r_theader, dp, len); /* d, s, l */
|
||||
|
@ -1245,6 +1245,9 @@ xfs_unmountfs(
|
||||
|
||||
XFS_QM_DQPURGEALL(mp, XFS_QMOPT_QUOTALL | XFS_QMOPT_UMOUNTING);
|
||||
|
||||
if (mp->m_quotainfo)
|
||||
XFS_QM_DONE(mp);
|
||||
|
||||
/*
|
||||
* Flush out the log synchronously so that we know for sure
|
||||
* that nothing is pinned. This is important because bflush()
|
||||
@ -1297,8 +1300,6 @@ xfs_unmountfs(
|
||||
xfs_errortag_clearall(mp, 0);
|
||||
#endif
|
||||
xfs_free_perag(mp);
|
||||
if (mp->m_quotainfo)
|
||||
XFS_QM_DONE(mp);
|
||||
}
|
||||
|
||||
STATIC void
|
||||
|
Loading…
Reference in New Issue
Block a user