Commit 04ca2c17 authored by Linus Torvalds's avatar Linus Torvalds

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
parents ad1164b7 220ca310
...@@ -1566,11 +1566,14 @@ xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno) ...@@ -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; int nmap, error, w, count, c, got, i, mapi;
xfs_trans_t *tp; xfs_trans_t *tp;
xfs_mount_t *mp; xfs_mount_t *mp;
xfs_drfsbno_t nblks;
dp = args->dp; dp = args->dp;
mp = dp->i_mount; mp = dp->i_mount;
w = args->whichfork; w = args->whichfork;
tp = args->trans; tp = args->trans;
nblks = dp->i_d.di_nblocks;
/* /*
* For new directories adjust the file offset and block count. * 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) ...@@ -1647,6 +1650,8 @@ xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno)
} }
if (mapp != &map) if (mapp != &map)
kmem_free(mapp); 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; *new_blkno = (xfs_dablk_t)bno;
return 0; return 0;
} }
......
...@@ -525,11 +525,13 @@ xfs_dir2_grow_inode( ...@@ -525,11 +525,13 @@ xfs_dir2_grow_inode(
xfs_mount_t *mp; xfs_mount_t *mp;
int nmap; /* number of bmap entries */ int nmap; /* number of bmap entries */
xfs_trans_t *tp; xfs_trans_t *tp;
xfs_drfsbno_t nblks;
xfs_dir2_trace_args_s("grow_inode", args, space); xfs_dir2_trace_args_s("grow_inode", args, space);
dp = args->dp; dp = args->dp;
tp = args->trans; tp = args->trans;
mp = dp->i_mount; mp = dp->i_mount;
nblks = dp->i_d.di_nblocks;
/* /*
* Set lowest possible block in the space requested. * Set lowest possible block in the space requested.
*/ */
...@@ -622,7 +624,11 @@ xfs_dir2_grow_inode( ...@@ -622,7 +624,11 @@ xfs_dir2_grow_inode(
*/ */
if (mapp != &map) if (mapp != &map)
kmem_free(mapp); 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); *dbp = xfs_dir2_da_to_db(mp, (xfs_dablk_t)bno);
/* /*
* Update file's size if this is the data space and it grew. * Update file's size if this is the data space and it grew.
*/ */
......
...@@ -1414,7 +1414,7 @@ xfs_itruncate_start( ...@@ -1414,7 +1414,7 @@ xfs_itruncate_start(
mp = ip->i_mount; mp = ip->i_mount;
/* wait for the completion of any pending DIOs */ /* 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); vn_iowait(ip);
/* /*
......
...@@ -563,6 +563,11 @@ xfs_log_mount( ...@@ -563,6 +563,11 @@ xfs_log_mount(
} }
mp->m_log = xlog_alloc_log(mp, log_target, blk_offset, num_bblks); 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. * Initialize the AIL now we have a log.
...@@ -601,6 +606,7 @@ xfs_log_mount( ...@@ -601,6 +606,7 @@ xfs_log_mount(
return 0; return 0;
error: error:
xfs_log_unmount_dealloc(mp); xfs_log_unmount_dealloc(mp);
out:
return error; return error;
} /* xfs_log_mount */ } /* xfs_log_mount */
...@@ -1217,7 +1223,9 @@ xlog_alloc_log(xfs_mount_t *mp, ...@@ -1217,7 +1223,9 @@ xlog_alloc_log(xfs_mount_t *mp,
int i; int i;
int iclogsize; 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_mp = mp;
log->l_targ = log_target; log->l_targ = log_target;
...@@ -1249,6 +1257,8 @@ xlog_alloc_log(xfs_mount_t *mp, ...@@ -1249,6 +1257,8 @@ xlog_alloc_log(xfs_mount_t *mp,
xlog_get_iclog_buffer_size(mp, log); xlog_get_iclog_buffer_size(mp, log);
bp = xfs_buf_get_empty(log->l_iclog_size, mp->m_logdev_targp); 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_IODONE_FUNC(bp, xlog_iodone);
XFS_BUF_SET_BDSTRAT_FUNC(bp, xlog_bdstrat_cb); XFS_BUF_SET_BDSTRAT_FUNC(bp, xlog_bdstrat_cb);
XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)1); XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)1);
...@@ -1275,13 +1285,17 @@ xlog_alloc_log(xfs_mount_t *mp, ...@@ -1275,13 +1285,17 @@ xlog_alloc_log(xfs_mount_t *mp,
iclogsize = log->l_iclog_size; iclogsize = log->l_iclog_size;
ASSERT(log->l_iclog_size >= 4096); ASSERT(log->l_iclog_size >= 4096);
for (i=0; i < log->l_iclog_bufs; i++) { for (i=0; i < log->l_iclog_bufs; i++) {
*iclogp = (xlog_in_core_t *) *iclogp = kmem_zalloc(sizeof(xlog_in_core_t), KM_MAYFAIL);
kmem_zalloc(sizeof(xlog_in_core_t), KM_SLEEP); if (!*iclogp)
goto out_free_iclog;
iclog = *iclogp; iclog = *iclogp;
iclog->ic_prev = prev_iclog; iclog->ic_prev = prev_iclog;
prev_iclog = iclog; prev_iclog = iclog;
bp = xfs_buf_get_noaddr(log->l_iclog_size, mp->m_logdev_targp); bp = xfs_buf_get_noaddr(log->l_iclog_size, mp->m_logdev_targp);
if (!bp)
goto out_free_iclog;
if (!XFS_BUF_CPSEMA(bp)) if (!XFS_BUF_CPSEMA(bp))
ASSERT(0); ASSERT(0);
XFS_BUF_SET_IODONE_FUNC(bp, xlog_iodone); XFS_BUF_SET_IODONE_FUNC(bp, xlog_iodone);
...@@ -1323,6 +1337,25 @@ xlog_alloc_log(xfs_mount_t *mp, ...@@ -1323,6 +1337,25 @@ xlog_alloc_log(xfs_mount_t *mp,
log->l_iclog->ic_prev = prev_iclog; /* re-write 1st prev ptr */ log->l_iclog->ic_prev = prev_iclog; /* re-write 1st prev ptr */
return log; 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 */ } /* xlog_alloc_log */
......
...@@ -1419,7 +1419,13 @@ xlog_recover_add_to_trans( ...@@ -1419,7 +1419,13 @@ xlog_recover_add_to_trans(
return 0; return 0;
item = trans->r_itemq; item = trans->r_itemq;
if (item == NULL) { 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)) if (len == sizeof(xfs_trans_header_t))
xlog_recover_add_item(&trans->r_itemq); xlog_recover_add_item(&trans->r_itemq);
memcpy(&trans->r_theader, dp, len); /* d, s, l */ memcpy(&trans->r_theader, dp, len); /* d, s, l */
......
...@@ -1245,6 +1245,9 @@ xfs_unmountfs( ...@@ -1245,6 +1245,9 @@ xfs_unmountfs(
XFS_QM_DQPURGEALL(mp, XFS_QMOPT_QUOTALL | XFS_QMOPT_UMOUNTING); 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 * Flush out the log synchronously so that we know for sure
* that nothing is pinned. This is important because bflush() * that nothing is pinned. This is important because bflush()
...@@ -1297,8 +1300,6 @@ xfs_unmountfs( ...@@ -1297,8 +1300,6 @@ xfs_unmountfs(
xfs_errortag_clearall(mp, 0); xfs_errortag_clearall(mp, 0);
#endif #endif
xfs_free_perag(mp); xfs_free_perag(mp);
if (mp->m_quotainfo)
XFS_QM_DONE(mp);
} }
STATIC void STATIC void
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment