Commit 33044dc4 authored by Dave Chinner's avatar Dave Chinner

Merge branch 'xfs-misc-fixes-for-3.18-2' into for-next

parents f6d31f4b 2ebff7bb
...@@ -270,7 +270,6 @@ xfs_dir3_data_get_ftype( ...@@ -270,7 +270,6 @@ xfs_dir3_data_get_ftype(
{ {
__uint8_t ftype = dep->name[dep->namelen]; __uint8_t ftype = dep->name[dep->namelen];
ASSERT(ftype < XFS_DIR3_FT_MAX);
if (ftype >= XFS_DIR3_FT_MAX) if (ftype >= XFS_DIR3_FT_MAX)
return XFS_DIR3_FT_UNKNOWN; return XFS_DIR3_FT_UNKNOWN;
return ftype; return ftype;
......
...@@ -1646,7 +1646,7 @@ xfs_swap_extents_check_format( ...@@ -1646,7 +1646,7 @@ xfs_swap_extents_check_format(
return 0; return 0;
} }
int static int
xfs_swap_extent_flush( xfs_swap_extent_flush(
struct xfs_inode *ip) struct xfs_inode *ip)
{ {
......
...@@ -501,7 +501,7 @@ xfs_buf_item_unpin( ...@@ -501,7 +501,7 @@ xfs_buf_item_unpin(
* buffer being bad.. * buffer being bad..
*/ */
DEFINE_RATELIMIT_STATE(xfs_buf_write_fail_rl_state, 30 * HZ, 10); static DEFINE_RATELIMIT_STATE(xfs_buf_write_fail_rl_state, 30 * HZ, 10);
STATIC uint STATIC uint
xfs_buf_item_push( xfs_buf_item_push(
......
...@@ -33,7 +33,6 @@ ...@@ -33,7 +33,6 @@
#include "xfs_trace.h" #include "xfs_trace.h"
#include "xfs_icache.h" #include "xfs_icache.h"
#include "xfs_bmap_util.h" #include "xfs_bmap_util.h"
#include "xfs_quota.h"
#include "xfs_dquot_item.h" #include "xfs_dquot_item.h"
#include "xfs_dquot.h" #include "xfs_dquot.h"
......
...@@ -849,6 +849,36 @@ xfs_setattr_size( ...@@ -849,6 +849,36 @@ xfs_setattr_size(
return error; return error;
truncate_setsize(inode, newsize); truncate_setsize(inode, newsize);
/*
* The "we can't serialise against page faults" pain gets worse.
*
* If the file is mapped then we have to clean the page at the old EOF
* when extending the file. Extending the file can expose changes the
* underlying page mapping (e.g. from beyond EOF to a hole or
* unwritten), and so on the next attempt to write to that page we need
* to remap it for write. i.e. we need .page_mkwrite() to be called.
* Hence we need to clean the page to clean the pte and so a new write
* fault will be triggered appropriately.
*
* If we do it before we change the inode size, then we can race with a
* page fault that maps the page with exactly the same problem. If we do
* it after we change the file size, then a new page fault can come in
* and allocate space before we've run the rest of the truncate
* transaction. That's kinda grotesque, but it's better than have data
* over a hole, and so that's the lesser evil that has been chosen here.
*
* The real solution, however, is to have some mechanism for locking out
* page faults while a truncate is in progress.
*/
if (newsize > oldsize && mapping_mapped(VFS_I(ip)->i_mapping)) {
error = filemap_write_and_wait_range(
VFS_I(ip)->i_mapping,
round_down(oldsize, PAGE_CACHE_SIZE),
round_up(oldsize, PAGE_CACHE_SIZE) - 1);
if (error)
return error;
}
tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_SIZE); tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_SIZE);
error = xfs_trans_reserve(tp, &M_RES(mp)->tr_itruncate, 0, 0); error = xfs_trans_reserve(tp, &M_RES(mp)->tr_itruncate, 0, 0);
if (error) if (error)
......
...@@ -463,12 +463,40 @@ xlog_cil_push( ...@@ -463,12 +463,40 @@ xlog_cil_push(
spin_unlock(&cil->xc_push_lock); spin_unlock(&cil->xc_push_lock);
goto out_skip; goto out_skip;
} }
spin_unlock(&cil->xc_push_lock);
/* check for a previously pushed seqeunce */ /* check for a previously pushed seqeunce */
if (push_seq < cil->xc_ctx->sequence) if (push_seq < cil->xc_ctx->sequence) {
spin_unlock(&cil->xc_push_lock);
goto out_skip; goto out_skip;
}
/*
* We are now going to push this context, so add it to the committing
* list before we do anything else. This ensures that anyone waiting on
* this push can easily detect the difference between a "push in
* progress" and "CIL is empty, nothing to do".
*
* IOWs, a wait loop can now check for:
* the current sequence not being found on the committing list;
* an empty CIL; and
* an unchanged sequence number
* to detect a push that had nothing to do and therefore does not need
* waiting on. If the CIL is not empty, we get put on the committing
* list before emptying the CIL and bumping the sequence number. Hence
* an empty CIL and an unchanged sequence number means we jumped out
* above after doing nothing.
*
* Hence the waiter will either find the commit sequence on the
* committing list or the sequence number will be unchanged and the CIL
* still dirty. In that latter case, the push has not yet started, and
* so the waiter will have to continue trying to check the CIL
* committing list until it is found. In extreme cases of delay, the
* sequence may fully commit between the attempts the wait makes to wait
* on the commit sequence.
*/
list_add(&ctx->committing, &cil->xc_committing);
spin_unlock(&cil->xc_push_lock);
/* /*
* pull all the log vectors off the items in the CIL, and * pull all the log vectors off the items in the CIL, and
...@@ -532,7 +560,6 @@ xlog_cil_push( ...@@ -532,7 +560,6 @@ xlog_cil_push(
*/ */
spin_lock(&cil->xc_push_lock); spin_lock(&cil->xc_push_lock);
cil->xc_current_sequence = new_ctx->sequence; cil->xc_current_sequence = new_ctx->sequence;
list_add(&ctx->committing, &cil->xc_committing);
spin_unlock(&cil->xc_push_lock); spin_unlock(&cil->xc_push_lock);
up_write(&cil->xc_ctx_lock); up_write(&cil->xc_ctx_lock);
...@@ -855,13 +882,15 @@ xlog_cil_force_lsn( ...@@ -855,13 +882,15 @@ xlog_cil_force_lsn(
* Hence by the time we have got here it our sequence may not have been * Hence by the time we have got here it our sequence may not have been
* pushed yet. This is true if the current sequence still matches the * pushed yet. This is true if the current sequence still matches the
* push sequence after the above wait loop and the CIL still contains * push sequence after the above wait loop and the CIL still contains
* dirty objects. * dirty objects. This is guaranteed by the push code first adding the
* context to the committing list before emptying the CIL.
* *
* When the push occurs, it will empty the CIL and atomically increment * Hence if we don't find the context in the committing list and the
* the currect sequence past the push sequence and move it into the * current sequence number is unchanged then the CIL contents are
* committing list. Of course, if the CIL is clean at the time of the * significant. If the CIL is empty, if means there was nothing to push
* push, it won't have pushed the CIL at all, so in that case we should * and that means there is nothing to wait for. If the CIL is not empty,
* try the push for this sequence again from the start just in case. * it means we haven't yet started the push, because if it had started
* we would have found the context on the committing list.
*/ */
if (sequence == cil->xc_current_sequence && if (sequence == cil->xc_current_sequence &&
!list_empty(&cil->xc_cil)) { !list_empty(&cil->xc_cil)) {
......
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
* Keeps track of a current summary block, so we don't keep reading * Keeps track of a current summary block, so we don't keep reading
* it from the buffer cache. * it from the buffer cache.
*/ */
int static int
xfs_rtget_summary( xfs_rtget_summary(
xfs_mount_t *mp, /* file system mount structure */ xfs_mount_t *mp, /* file system mount structure */
xfs_trans_t *tp, /* transaction pointer */ xfs_trans_t *tp, /* transaction pointer */
......
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