mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-30 23:54:04 +08:00
Merge branch 'for-linus' of git://oss.sgi.com/xfs/xfs
* 'for-linus' of git://oss.sgi.com/xfs/xfs: (69 commits) xfs: add AIL pushing tracepoints xfs: put in missed fix for merge problem xfs: do not flush data workqueues in xfs_flush_buftarg xfs: remove XFS_bflush xfs: remove xfs_buf_target_name xfs: use xfs_ioerror_alert in xfs_buf_iodone_callbacks xfs: clean up xfs_ioerror_alert xfs: clean up buffer allocation xfs: remove buffers from the delwri list in xfs_buf_stale xfs: remove XFS_BUF_STALE and XFS_BUF_SUPER_STALE xfs: remove XFS_BUF_SET_VTYPE and XFS_BUF_SET_VTYPE_REF xfs: remove XFS_BUF_FINISH_IOWAIT xfs: remove xfs_get_buftarg_list xfs: fix buffer flushing during unmount xfs: optimize fsync on directories xfs: reduce the number of log forces from tail pushing xfs: Don't allocate new buffers on every call to _xfs_buf_find xfs: simplify xfs_trans_ijoin* again xfs: unlock the inode before log force in xfs_change_file_space xfs: unlock the inode before log force in xfs_fs_nfs_commit_metadata ...
This commit is contained in:
commit
5619a69396
@ -452,7 +452,7 @@ xfs_alloc_read_agfl(
|
|||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
ASSERT(!xfs_buf_geterror(bp));
|
ASSERT(!xfs_buf_geterror(bp));
|
||||||
XFS_BUF_SET_VTYPE_REF(bp, B_FS_AGFL, XFS_AGFL_REF);
|
xfs_buf_set_ref(bp, XFS_AGFL_REF);
|
||||||
*bpp = bp;
|
*bpp = bp;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2139,7 +2139,7 @@ xfs_read_agf(
|
|||||||
xfs_trans_brelse(tp, *bpp);
|
xfs_trans_brelse(tp, *bpp);
|
||||||
return XFS_ERROR(EFSCORRUPTED);
|
return XFS_ERROR(EFSCORRUPTED);
|
||||||
}
|
}
|
||||||
XFS_BUF_SET_VTYPE_REF(*bpp, B_FS_AGF, XFS_AGF_REF);
|
xfs_buf_set_ref(*bpp, XFS_AGF_REF);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,40 +38,6 @@
|
|||||||
#include <linux/pagevec.h>
|
#include <linux/pagevec.h>
|
||||||
#include <linux/writeback.h>
|
#include <linux/writeback.h>
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Prime number of hash buckets since address is used as the key.
|
|
||||||
*/
|
|
||||||
#define NVSYNC 37
|
|
||||||
#define to_ioend_wq(v) (&xfs_ioend_wq[((unsigned long)v) % NVSYNC])
|
|
||||||
static wait_queue_head_t xfs_ioend_wq[NVSYNC];
|
|
||||||
|
|
||||||
void __init
|
|
||||||
xfs_ioend_init(void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < NVSYNC; i++)
|
|
||||||
init_waitqueue_head(&xfs_ioend_wq[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
xfs_ioend_wait(
|
|
||||||
xfs_inode_t *ip)
|
|
||||||
{
|
|
||||||
wait_queue_head_t *wq = to_ioend_wq(ip);
|
|
||||||
|
|
||||||
wait_event(*wq, (atomic_read(&ip->i_iocount) == 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
STATIC void
|
|
||||||
xfs_ioend_wake(
|
|
||||||
xfs_inode_t *ip)
|
|
||||||
{
|
|
||||||
if (atomic_dec_and_test(&ip->i_iocount))
|
|
||||||
wake_up(to_ioend_wq(ip));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
xfs_count_page_state(
|
xfs_count_page_state(
|
||||||
struct page *page,
|
struct page *page,
|
||||||
@ -115,25 +81,20 @@ xfs_destroy_ioend(
|
|||||||
xfs_ioend_t *ioend)
|
xfs_ioend_t *ioend)
|
||||||
{
|
{
|
||||||
struct buffer_head *bh, *next;
|
struct buffer_head *bh, *next;
|
||||||
struct xfs_inode *ip = XFS_I(ioend->io_inode);
|
|
||||||
|
|
||||||
for (bh = ioend->io_buffer_head; bh; bh = next) {
|
for (bh = ioend->io_buffer_head; bh; bh = next) {
|
||||||
next = bh->b_private;
|
next = bh->b_private;
|
||||||
bh->b_end_io(bh, !ioend->io_error);
|
bh->b_end_io(bh, !ioend->io_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
if (ioend->io_iocb) {
|
||||||
* Volume managers supporting multiple paths can send back ENODEV
|
if (ioend->io_isasync) {
|
||||||
* when the final path disappears. In this case continuing to fill
|
aio_complete(ioend->io_iocb, ioend->io_error ?
|
||||||
* the page cache with dirty data which cannot be written out is
|
ioend->io_error : ioend->io_result, 0);
|
||||||
* evil, so prevent that.
|
}
|
||||||
*/
|
inode_dio_done(ioend->io_inode);
|
||||||
if (unlikely(ioend->io_error == -ENODEV)) {
|
|
||||||
xfs_do_force_shutdown(ip->i_mount, SHUTDOWN_DEVICE_REQ,
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
xfs_ioend_wake(ip);
|
|
||||||
mempool_free(ioend, xfs_ioend_pool);
|
mempool_free(ioend, xfs_ioend_pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,6 +116,15 @@ xfs_ioend_new_eof(
|
|||||||
return isize > ip->i_d.di_size ? isize : 0;
|
return isize > ip->i_d.di_size ? isize : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fast and loose check if this write could update the on-disk inode size.
|
||||||
|
*/
|
||||||
|
static inline bool xfs_ioend_is_append(struct xfs_ioend *ioend)
|
||||||
|
{
|
||||||
|
return ioend->io_offset + ioend->io_size >
|
||||||
|
XFS_I(ioend->io_inode)->i_d.di_size;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Update on-disk file size now that data has been written to disk. The
|
* Update on-disk file size now that data has been written to disk. The
|
||||||
* current in-memory file size is i_size. If a write is beyond eof i_new_size
|
* current in-memory file size is i_size. If a write is beyond eof i_new_size
|
||||||
@ -173,9 +143,6 @@ xfs_setfilesize(
|
|||||||
xfs_inode_t *ip = XFS_I(ioend->io_inode);
|
xfs_inode_t *ip = XFS_I(ioend->io_inode);
|
||||||
xfs_fsize_t isize;
|
xfs_fsize_t isize;
|
||||||
|
|
||||||
if (unlikely(ioend->io_error))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (!xfs_ilock_nowait(ip, XFS_ILOCK_EXCL))
|
if (!xfs_ilock_nowait(ip, XFS_ILOCK_EXCL))
|
||||||
return EAGAIN;
|
return EAGAIN;
|
||||||
|
|
||||||
@ -192,6 +159,9 @@ xfs_setfilesize(
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Schedule IO completion handling on the final put of an ioend.
|
* Schedule IO completion handling on the final put of an ioend.
|
||||||
|
*
|
||||||
|
* If there is no work to do we might as well call it a day and free the
|
||||||
|
* ioend right now.
|
||||||
*/
|
*/
|
||||||
STATIC void
|
STATIC void
|
||||||
xfs_finish_ioend(
|
xfs_finish_ioend(
|
||||||
@ -200,8 +170,10 @@ xfs_finish_ioend(
|
|||||||
if (atomic_dec_and_test(&ioend->io_remaining)) {
|
if (atomic_dec_and_test(&ioend->io_remaining)) {
|
||||||
if (ioend->io_type == IO_UNWRITTEN)
|
if (ioend->io_type == IO_UNWRITTEN)
|
||||||
queue_work(xfsconvertd_workqueue, &ioend->io_work);
|
queue_work(xfsconvertd_workqueue, &ioend->io_work);
|
||||||
else
|
else if (xfs_ioend_is_append(ioend))
|
||||||
queue_work(xfsdatad_workqueue, &ioend->io_work);
|
queue_work(xfsdatad_workqueue, &ioend->io_work);
|
||||||
|
else
|
||||||
|
xfs_destroy_ioend(ioend);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -216,17 +188,24 @@ xfs_end_io(
|
|||||||
struct xfs_inode *ip = XFS_I(ioend->io_inode);
|
struct xfs_inode *ip = XFS_I(ioend->io_inode);
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
|
if (XFS_FORCED_SHUTDOWN(ip->i_mount)) {
|
||||||
|
error = -EIO;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (ioend->io_error)
|
||||||
|
goto done;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For unwritten extents we need to issue transactions to convert a
|
* For unwritten extents we need to issue transactions to convert a
|
||||||
* range to normal written extens after the data I/O has finished.
|
* range to normal written extens after the data I/O has finished.
|
||||||
*/
|
*/
|
||||||
if (ioend->io_type == IO_UNWRITTEN &&
|
if (ioend->io_type == IO_UNWRITTEN) {
|
||||||
likely(!ioend->io_error && !XFS_FORCED_SHUTDOWN(ip->i_mount))) {
|
|
||||||
|
|
||||||
error = xfs_iomap_write_unwritten(ip, ioend->io_offset,
|
error = xfs_iomap_write_unwritten(ip, ioend->io_offset,
|
||||||
ioend->io_size);
|
ioend->io_size);
|
||||||
if (error)
|
if (error) {
|
||||||
ioend->io_error = error;
|
ioend->io_error = -error;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -236,6 +215,7 @@ xfs_end_io(
|
|||||||
error = xfs_setfilesize(ioend);
|
error = xfs_setfilesize(ioend);
|
||||||
ASSERT(!error || error == EAGAIN);
|
ASSERT(!error || error == EAGAIN);
|
||||||
|
|
||||||
|
done:
|
||||||
/*
|
/*
|
||||||
* If we didn't complete processing of the ioend, requeue it to the
|
* If we didn't complete processing of the ioend, requeue it to the
|
||||||
* tail of the workqueue for another attempt later. Otherwise destroy
|
* tail of the workqueue for another attempt later. Otherwise destroy
|
||||||
@ -247,8 +227,6 @@ xfs_end_io(
|
|||||||
/* ensure we don't spin on blocked ioends */
|
/* ensure we don't spin on blocked ioends */
|
||||||
delay(1);
|
delay(1);
|
||||||
} else {
|
} else {
|
||||||
if (ioend->io_iocb)
|
|
||||||
aio_complete(ioend->io_iocb, ioend->io_result, 0);
|
|
||||||
xfs_destroy_ioend(ioend);
|
xfs_destroy_ioend(ioend);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -285,13 +263,13 @@ xfs_alloc_ioend(
|
|||||||
* all the I/O from calling the completion routine too early.
|
* all the I/O from calling the completion routine too early.
|
||||||
*/
|
*/
|
||||||
atomic_set(&ioend->io_remaining, 1);
|
atomic_set(&ioend->io_remaining, 1);
|
||||||
|
ioend->io_isasync = 0;
|
||||||
ioend->io_error = 0;
|
ioend->io_error = 0;
|
||||||
ioend->io_list = NULL;
|
ioend->io_list = NULL;
|
||||||
ioend->io_type = type;
|
ioend->io_type = type;
|
||||||
ioend->io_inode = inode;
|
ioend->io_inode = inode;
|
||||||
ioend->io_buffer_head = NULL;
|
ioend->io_buffer_head = NULL;
|
||||||
ioend->io_buffer_tail = NULL;
|
ioend->io_buffer_tail = NULL;
|
||||||
atomic_inc(&XFS_I(ioend->io_inode)->i_iocount);
|
|
||||||
ioend->io_offset = 0;
|
ioend->io_offset = 0;
|
||||||
ioend->io_size = 0;
|
ioend->io_size = 0;
|
||||||
ioend->io_iocb = NULL;
|
ioend->io_iocb = NULL;
|
||||||
@ -337,8 +315,8 @@ xfs_map_blocks(
|
|||||||
count = mp->m_maxioffset - offset;
|
count = mp->m_maxioffset - offset;
|
||||||
end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count);
|
end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count);
|
||||||
offset_fsb = XFS_B_TO_FSBT(mp, offset);
|
offset_fsb = XFS_B_TO_FSBT(mp, offset);
|
||||||
error = xfs_bmapi(NULL, ip, offset_fsb, end_fsb - offset_fsb,
|
error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb,
|
||||||
bmapi_flags, NULL, 0, imap, &nimaps, NULL);
|
imap, &nimaps, bmapi_flags);
|
||||||
xfs_iunlock(ip, XFS_ILOCK_SHARED);
|
xfs_iunlock(ip, XFS_ILOCK_SHARED);
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
@ -551,7 +529,6 @@ xfs_cancel_ioend(
|
|||||||
unlock_buffer(bh);
|
unlock_buffer(bh);
|
||||||
} while ((bh = next_bh) != NULL);
|
} while ((bh = next_bh) != NULL);
|
||||||
|
|
||||||
xfs_ioend_wake(XFS_I(ioend->io_inode));
|
|
||||||
mempool_free(ioend, xfs_ioend_pool);
|
mempool_free(ioend, xfs_ioend_pool);
|
||||||
} while ((ioend = next) != NULL);
|
} while ((ioend = next) != NULL);
|
||||||
}
|
}
|
||||||
@ -1161,8 +1138,8 @@ __xfs_get_blocks(
|
|||||||
end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + size);
|
end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + size);
|
||||||
offset_fsb = XFS_B_TO_FSBT(mp, offset);
|
offset_fsb = XFS_B_TO_FSBT(mp, offset);
|
||||||
|
|
||||||
error = xfs_bmapi(NULL, ip, offset_fsb, end_fsb - offset_fsb,
|
error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb,
|
||||||
XFS_BMAPI_ENTIRE, NULL, 0, &imap, &nimaps, NULL);
|
&imap, &nimaps, XFS_BMAPI_ENTIRE);
|
||||||
if (error)
|
if (error)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
|
||||||
@ -1300,7 +1277,6 @@ xfs_end_io_direct_write(
|
|||||||
bool is_async)
|
bool is_async)
|
||||||
{
|
{
|
||||||
struct xfs_ioend *ioend = iocb->private;
|
struct xfs_ioend *ioend = iocb->private;
|
||||||
struct inode *inode = ioend->io_inode;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* blockdev_direct_IO can return an error even after the I/O
|
* blockdev_direct_IO can return an error even after the I/O
|
||||||
@ -1311,28 +1287,17 @@ xfs_end_io_direct_write(
|
|||||||
|
|
||||||
ioend->io_offset = offset;
|
ioend->io_offset = offset;
|
||||||
ioend->io_size = size;
|
ioend->io_size = size;
|
||||||
|
ioend->io_iocb = iocb;
|
||||||
|
ioend->io_result = ret;
|
||||||
if (private && size > 0)
|
if (private && size > 0)
|
||||||
ioend->io_type = IO_UNWRITTEN;
|
ioend->io_type = IO_UNWRITTEN;
|
||||||
|
|
||||||
if (is_async) {
|
if (is_async) {
|
||||||
/*
|
ioend->io_isasync = 1;
|
||||||
* If we are converting an unwritten extent we need to delay
|
|
||||||
* the AIO completion until after the unwrittent extent
|
|
||||||
* conversion has completed, otherwise do it ASAP.
|
|
||||||
*/
|
|
||||||
if (ioend->io_type == IO_UNWRITTEN) {
|
|
||||||
ioend->io_iocb = iocb;
|
|
||||||
ioend->io_result = ret;
|
|
||||||
} else {
|
|
||||||
aio_complete(iocb, ret, 0);
|
|
||||||
}
|
|
||||||
xfs_finish_ioend(ioend);
|
xfs_finish_ioend(ioend);
|
||||||
} else {
|
} else {
|
||||||
xfs_finish_ioend_sync(ioend);
|
xfs_finish_ioend_sync(ioend);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX: probably should move into the real I/O completion handler */
|
|
||||||
inode_dio_done(inode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC ssize_t
|
STATIC ssize_t
|
||||||
|
@ -47,6 +47,7 @@ typedef struct xfs_ioend {
|
|||||||
unsigned int io_type; /* delalloc / unwritten */
|
unsigned int io_type; /* delalloc / unwritten */
|
||||||
int io_error; /* I/O error code */
|
int io_error; /* I/O error code */
|
||||||
atomic_t io_remaining; /* hold count */
|
atomic_t io_remaining; /* hold count */
|
||||||
|
unsigned int io_isasync : 1; /* needs aio_complete */
|
||||||
struct inode *io_inode; /* file being written to */
|
struct inode *io_inode; /* file being written to */
|
||||||
struct buffer_head *io_buffer_head;/* buffer linked list head */
|
struct buffer_head *io_buffer_head;/* buffer linked list head */
|
||||||
struct buffer_head *io_buffer_tail;/* buffer linked list tail */
|
struct buffer_head *io_buffer_tail;/* buffer linked list tail */
|
||||||
@ -60,9 +61,6 @@ typedef struct xfs_ioend {
|
|||||||
extern const struct address_space_operations xfs_address_space_operations;
|
extern const struct address_space_operations xfs_address_space_operations;
|
||||||
extern int xfs_get_blocks(struct inode *, sector_t, struct buffer_head *, int);
|
extern int xfs_get_blocks(struct inode *, sector_t, struct buffer_head *, int);
|
||||||
|
|
||||||
extern void xfs_ioend_init(void);
|
|
||||||
extern void xfs_ioend_wait(struct xfs_inode *);
|
|
||||||
|
|
||||||
extern void xfs_count_page_state(struct page *, int *, int *);
|
extern void xfs_count_page_state(struct page *, int *, int *);
|
||||||
|
|
||||||
#endif /* __XFS_AOPS_H__ */
|
#endif /* __XFS_AOPS_H__ */
|
||||||
|
@ -319,7 +319,7 @@ xfs_attr_set_int(
|
|||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
xfs_trans_ijoin(args.trans, dp);
|
xfs_trans_ijoin(args.trans, dp, 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the attribute list is non-existent or a shortform list,
|
* If the attribute list is non-existent or a shortform list,
|
||||||
@ -389,7 +389,7 @@ xfs_attr_set_int(
|
|||||||
* a new one. We need the inode to be in all transactions.
|
* a new one. We need the inode to be in all transactions.
|
||||||
*/
|
*/
|
||||||
if (committed)
|
if (committed)
|
||||||
xfs_trans_ijoin(args.trans, dp);
|
xfs_trans_ijoin(args.trans, dp, 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Commit the leaf transformation. We'll need another (linked)
|
* Commit the leaf transformation. We'll need another (linked)
|
||||||
@ -537,7 +537,7 @@ xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags)
|
|||||||
* No need to make quota reservations here. We expect to release some
|
* No need to make quota reservations here. We expect to release some
|
||||||
* blocks not allocate in the common case.
|
* blocks not allocate in the common case.
|
||||||
*/
|
*/
|
||||||
xfs_trans_ijoin(args.trans, dp);
|
xfs_trans_ijoin(args.trans, dp, 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Decide on what work routines to call based on the inode size.
|
* Decide on what work routines to call based on the inode size.
|
||||||
@ -809,7 +809,7 @@ xfs_attr_inactive(xfs_inode_t *dp)
|
|||||||
* No need to make quota reservations here. We expect to release some
|
* No need to make quota reservations here. We expect to release some
|
||||||
* blocks, not allocate, in the common case.
|
* blocks, not allocate, in the common case.
|
||||||
*/
|
*/
|
||||||
xfs_trans_ijoin(trans, dp);
|
xfs_trans_ijoin(trans, dp, 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Decide on what work routines to call based on the inode size.
|
* Decide on what work routines to call based on the inode size.
|
||||||
@ -823,18 +823,6 @@ xfs_attr_inactive(xfs_inode_t *dp)
|
|||||||
if (error)
|
if (error)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/*
|
|
||||||
* Signal synchronous inactive transactions unless this is a
|
|
||||||
* synchronous mount filesystem in which case we know that we're here
|
|
||||||
* because we've been called out of xfs_inactive which means that the
|
|
||||||
* last reference is gone and the unlink transaction has already hit
|
|
||||||
* the disk so async inactive transactions are safe.
|
|
||||||
*/
|
|
||||||
if (!(mp->m_flags & XFS_MOUNT_WSYNC)) {
|
|
||||||
if (dp->i_d.di_anextents > 0)
|
|
||||||
xfs_trans_set_sync(trans);
|
|
||||||
}
|
|
||||||
|
|
||||||
error = xfs_itruncate_extents(&trans, dp, XFS_ATTR_FORK, 0);
|
error = xfs_itruncate_extents(&trans, dp, XFS_ATTR_FORK, 0);
|
||||||
if (error)
|
if (error)
|
||||||
goto out;
|
goto out;
|
||||||
@ -973,7 +961,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
|
|||||||
* a new one. We need the inode to be in all transactions.
|
* a new one. We need the inode to be in all transactions.
|
||||||
*/
|
*/
|
||||||
if (committed)
|
if (committed)
|
||||||
xfs_trans_ijoin(args->trans, dp);
|
xfs_trans_ijoin(args->trans, dp, 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Commit the current trans (including the inode) and start
|
* Commit the current trans (including the inode) and start
|
||||||
@ -1075,7 +1063,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
|
|||||||
* in all transactions.
|
* in all transactions.
|
||||||
*/
|
*/
|
||||||
if (committed)
|
if (committed)
|
||||||
xfs_trans_ijoin(args->trans, dp);
|
xfs_trans_ijoin(args->trans, dp, 0);
|
||||||
} else
|
} else
|
||||||
xfs_da_buf_done(bp);
|
xfs_da_buf_done(bp);
|
||||||
|
|
||||||
@ -1149,7 +1137,7 @@ xfs_attr_leaf_removename(xfs_da_args_t *args)
|
|||||||
* a new one. We need the inode to be in all transactions.
|
* a new one. We need the inode to be in all transactions.
|
||||||
*/
|
*/
|
||||||
if (committed)
|
if (committed)
|
||||||
xfs_trans_ijoin(args->trans, dp);
|
xfs_trans_ijoin(args->trans, dp, 0);
|
||||||
} else
|
} else
|
||||||
xfs_da_buf_done(bp);
|
xfs_da_buf_done(bp);
|
||||||
return(0);
|
return(0);
|
||||||
@ -1303,7 +1291,7 @@ restart:
|
|||||||
* in all transactions.
|
* in all transactions.
|
||||||
*/
|
*/
|
||||||
if (committed)
|
if (committed)
|
||||||
xfs_trans_ijoin(args->trans, dp);
|
xfs_trans_ijoin(args->trans, dp, 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Commit the node conversion and start the next
|
* Commit the node conversion and start the next
|
||||||
@ -1340,7 +1328,7 @@ restart:
|
|||||||
* a new one. We need the inode to be in all transactions.
|
* a new one. We need the inode to be in all transactions.
|
||||||
*/
|
*/
|
||||||
if (committed)
|
if (committed)
|
||||||
xfs_trans_ijoin(args->trans, dp);
|
xfs_trans_ijoin(args->trans, dp, 0);
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* Addition succeeded, update Btree hashvals.
|
* Addition succeeded, update Btree hashvals.
|
||||||
@ -1452,7 +1440,7 @@ restart:
|
|||||||
* in all transactions.
|
* in all transactions.
|
||||||
*/
|
*/
|
||||||
if (committed)
|
if (committed)
|
||||||
xfs_trans_ijoin(args->trans, dp);
|
xfs_trans_ijoin(args->trans, dp, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1584,7 +1572,7 @@ xfs_attr_node_removename(xfs_da_args_t *args)
|
|||||||
* a new one. We need the inode to be in all transactions.
|
* a new one. We need the inode to be in all transactions.
|
||||||
*/
|
*/
|
||||||
if (committed)
|
if (committed)
|
||||||
xfs_trans_ijoin(args->trans, dp);
|
xfs_trans_ijoin(args->trans, dp, 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Commit the Btree join operation and start a new trans.
|
* Commit the Btree join operation and start a new trans.
|
||||||
@ -1635,7 +1623,7 @@ xfs_attr_node_removename(xfs_da_args_t *args)
|
|||||||
* in all transactions.
|
* in all transactions.
|
||||||
*/
|
*/
|
||||||
if (committed)
|
if (committed)
|
||||||
xfs_trans_ijoin(args->trans, dp);
|
xfs_trans_ijoin(args->trans, dp, 0);
|
||||||
} else
|
} else
|
||||||
xfs_da_brelse(args->trans, bp);
|
xfs_da_brelse(args->trans, bp);
|
||||||
}
|
}
|
||||||
@ -1975,10 +1963,9 @@ xfs_attr_rmtval_get(xfs_da_args_t *args)
|
|||||||
lblkno = args->rmtblkno;
|
lblkno = args->rmtblkno;
|
||||||
while (valuelen > 0) {
|
while (valuelen > 0) {
|
||||||
nmap = ATTR_RMTVALUE_MAPSIZE;
|
nmap = ATTR_RMTVALUE_MAPSIZE;
|
||||||
error = xfs_bmapi(args->trans, args->dp, (xfs_fileoff_t)lblkno,
|
error = xfs_bmapi_read(args->dp, (xfs_fileoff_t)lblkno,
|
||||||
args->rmtblkcnt,
|
args->rmtblkcnt, map, &nmap,
|
||||||
XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA,
|
XFS_BMAPI_ATTRFORK);
|
||||||
NULL, 0, map, &nmap, NULL);
|
|
||||||
if (error)
|
if (error)
|
||||||
return(error);
|
return(error);
|
||||||
ASSERT(nmap >= 1);
|
ASSERT(nmap >= 1);
|
||||||
@ -2052,10 +2039,9 @@ xfs_attr_rmtval_set(xfs_da_args_t *args)
|
|||||||
*/
|
*/
|
||||||
xfs_bmap_init(args->flist, args->firstblock);
|
xfs_bmap_init(args->flist, args->firstblock);
|
||||||
nmap = 1;
|
nmap = 1;
|
||||||
error = xfs_bmapi(args->trans, dp, (xfs_fileoff_t)lblkno,
|
error = xfs_bmapi_write(args->trans, dp, (xfs_fileoff_t)lblkno,
|
||||||
blkcnt,
|
blkcnt,
|
||||||
XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA |
|
XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA,
|
||||||
XFS_BMAPI_WRITE,
|
|
||||||
args->firstblock, args->total, &map, &nmap,
|
args->firstblock, args->total, &map, &nmap,
|
||||||
args->flist);
|
args->flist);
|
||||||
if (!error) {
|
if (!error) {
|
||||||
@ -2074,7 +2060,7 @@ xfs_attr_rmtval_set(xfs_da_args_t *args)
|
|||||||
* a new one. We need the inode to be in all transactions.
|
* a new one. We need the inode to be in all transactions.
|
||||||
*/
|
*/
|
||||||
if (committed)
|
if (committed)
|
||||||
xfs_trans_ijoin(args->trans, dp);
|
xfs_trans_ijoin(args->trans, dp, 0);
|
||||||
|
|
||||||
ASSERT(nmap == 1);
|
ASSERT(nmap == 1);
|
||||||
ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
|
ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
|
||||||
@ -2104,14 +2090,11 @@ xfs_attr_rmtval_set(xfs_da_args_t *args)
|
|||||||
*/
|
*/
|
||||||
xfs_bmap_init(args->flist, args->firstblock);
|
xfs_bmap_init(args->flist, args->firstblock);
|
||||||
nmap = 1;
|
nmap = 1;
|
||||||
error = xfs_bmapi(NULL, dp, (xfs_fileoff_t)lblkno,
|
error = xfs_bmapi_read(dp, (xfs_fileoff_t)lblkno,
|
||||||
args->rmtblkcnt,
|
args->rmtblkcnt, &map, &nmap,
|
||||||
XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA,
|
XFS_BMAPI_ATTRFORK);
|
||||||
args->firstblock, 0, &map, &nmap,
|
if (error)
|
||||||
NULL);
|
|
||||||
if (error) {
|
|
||||||
return(error);
|
return(error);
|
||||||
}
|
|
||||||
ASSERT(nmap == 1);
|
ASSERT(nmap == 1);
|
||||||
ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
|
ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
|
||||||
(map.br_startblock != HOLESTARTBLOCK));
|
(map.br_startblock != HOLESTARTBLOCK));
|
||||||
@ -2121,16 +2104,17 @@ xfs_attr_rmtval_set(xfs_da_args_t *args)
|
|||||||
|
|
||||||
bp = xfs_buf_get(mp->m_ddev_targp, dblkno, blkcnt,
|
bp = xfs_buf_get(mp->m_ddev_targp, dblkno, blkcnt,
|
||||||
XBF_LOCK | XBF_DONT_BLOCK);
|
XBF_LOCK | XBF_DONT_BLOCK);
|
||||||
ASSERT(!xfs_buf_geterror(bp));
|
if (!bp)
|
||||||
|
return ENOMEM;
|
||||||
tmp = (valuelen < XFS_BUF_SIZE(bp)) ? valuelen :
|
tmp = (valuelen < XFS_BUF_SIZE(bp)) ? valuelen :
|
||||||
XFS_BUF_SIZE(bp);
|
XFS_BUF_SIZE(bp);
|
||||||
xfs_buf_iomove(bp, 0, tmp, src, XBRW_WRITE);
|
xfs_buf_iomove(bp, 0, tmp, src, XBRW_WRITE);
|
||||||
if (tmp < XFS_BUF_SIZE(bp))
|
if (tmp < XFS_BUF_SIZE(bp))
|
||||||
xfs_buf_zero(bp, tmp, XFS_BUF_SIZE(bp) - tmp);
|
xfs_buf_zero(bp, tmp, XFS_BUF_SIZE(bp) - tmp);
|
||||||
if ((error = xfs_bwrite(mp, bp))) {/* GROT: NOTE: synchronous write */
|
error = xfs_bwrite(bp); /* GROT: NOTE: synchronous write */
|
||||||
return (error);
|
xfs_buf_relse(bp);
|
||||||
}
|
if (error)
|
||||||
|
return error;
|
||||||
src += tmp;
|
src += tmp;
|
||||||
valuelen -= tmp;
|
valuelen -= tmp;
|
||||||
|
|
||||||
@ -2166,16 +2150,12 @@ xfs_attr_rmtval_remove(xfs_da_args_t *args)
|
|||||||
/*
|
/*
|
||||||
* Try to remember where we decided to put the value.
|
* Try to remember where we decided to put the value.
|
||||||
*/
|
*/
|
||||||
xfs_bmap_init(args->flist, args->firstblock);
|
|
||||||
nmap = 1;
|
nmap = 1;
|
||||||
error = xfs_bmapi(NULL, args->dp, (xfs_fileoff_t)lblkno,
|
error = xfs_bmapi_read(args->dp, (xfs_fileoff_t)lblkno,
|
||||||
args->rmtblkcnt,
|
args->rmtblkcnt, &map, &nmap,
|
||||||
XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA,
|
XFS_BMAPI_ATTRFORK);
|
||||||
args->firstblock, 0, &map, &nmap,
|
if (error)
|
||||||
args->flist);
|
|
||||||
if (error) {
|
|
||||||
return(error);
|
return(error);
|
||||||
}
|
|
||||||
ASSERT(nmap == 1);
|
ASSERT(nmap == 1);
|
||||||
ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
|
ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
|
||||||
(map.br_startblock != HOLESTARTBLOCK));
|
(map.br_startblock != HOLESTARTBLOCK));
|
||||||
@ -2188,8 +2168,7 @@ xfs_attr_rmtval_remove(xfs_da_args_t *args)
|
|||||||
*/
|
*/
|
||||||
bp = xfs_incore(mp->m_ddev_targp, dblkno, blkcnt, XBF_TRYLOCK);
|
bp = xfs_incore(mp->m_ddev_targp, dblkno, blkcnt, XBF_TRYLOCK);
|
||||||
if (bp) {
|
if (bp) {
|
||||||
XFS_BUF_STALE(bp);
|
xfs_buf_stale(bp);
|
||||||
XFS_BUF_UNDELAYWRITE(bp);
|
|
||||||
xfs_buf_relse(bp);
|
xfs_buf_relse(bp);
|
||||||
bp = NULL;
|
bp = NULL;
|
||||||
}
|
}
|
||||||
@ -2227,7 +2206,7 @@ xfs_attr_rmtval_remove(xfs_da_args_t *args)
|
|||||||
* a new one. We need the inode to be in all transactions.
|
* a new one. We need the inode to be in all transactions.
|
||||||
*/
|
*/
|
||||||
if (committed)
|
if (committed)
|
||||||
xfs_trans_ijoin(args->trans, args->dp);
|
xfs_trans_ijoin(args->trans, args->dp, 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Close out trans and start the next one in the chain.
|
* Close out trans and start the next one in the chain.
|
||||||
|
@ -2926,9 +2926,8 @@ xfs_attr_leaf_freextent(xfs_trans_t **trans, xfs_inode_t *dp,
|
|||||||
* Try to remember where we decided to put the value.
|
* Try to remember where we decided to put the value.
|
||||||
*/
|
*/
|
||||||
nmap = 1;
|
nmap = 1;
|
||||||
error = xfs_bmapi(*trans, dp, (xfs_fileoff_t)tblkno, tblkcnt,
|
error = xfs_bmapi_read(dp, (xfs_fileoff_t)tblkno, tblkcnt,
|
||||||
XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA,
|
&map, &nmap, XFS_BMAPI_ATTRFORK);
|
||||||
NULL, 0, &map, &nmap, NULL);
|
|
||||||
if (error) {
|
if (error) {
|
||||||
return(error);
|
return(error);
|
||||||
}
|
}
|
||||||
@ -2948,6 +2947,8 @@ xfs_attr_leaf_freextent(xfs_trans_t **trans, xfs_inode_t *dp,
|
|||||||
bp = xfs_trans_get_buf(*trans,
|
bp = xfs_trans_get_buf(*trans,
|
||||||
dp->i_mount->m_ddev_targp,
|
dp->i_mount->m_ddev_targp,
|
||||||
dblkno, dblkcnt, XBF_LOCK);
|
dblkno, dblkcnt, XBF_LOCK);
|
||||||
|
if (!bp)
|
||||||
|
return ENOMEM;
|
||||||
xfs_trans_binval(*trans, bp);
|
xfs_trans_binval(*trans, bp);
|
||||||
/*
|
/*
|
||||||
* Roll to next transaction.
|
* Roll to next transaction.
|
||||||
|
2549
fs/xfs/xfs_bmap.c
2549
fs/xfs/xfs_bmap.c
File diff suppressed because it is too large
Load Diff
@ -62,27 +62,23 @@ typedef struct xfs_bmap_free
|
|||||||
#define XFS_BMAP_MAX_NMAP 4
|
#define XFS_BMAP_MAX_NMAP 4
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Flags for xfs_bmapi
|
* Flags for xfs_bmapi_*
|
||||||
*/
|
*/
|
||||||
#define XFS_BMAPI_WRITE 0x001 /* write operation: allocate space */
|
#define XFS_BMAPI_ENTIRE 0x001 /* return entire extent, not trimmed */
|
||||||
#define XFS_BMAPI_DELAY 0x002 /* delayed write operation */
|
#define XFS_BMAPI_METADATA 0x002 /* mapping metadata not user data */
|
||||||
#define XFS_BMAPI_ENTIRE 0x004 /* return entire extent, not trimmed */
|
#define XFS_BMAPI_ATTRFORK 0x004 /* use attribute fork not data */
|
||||||
#define XFS_BMAPI_METADATA 0x008 /* mapping metadata not user data */
|
#define XFS_BMAPI_PREALLOC 0x008 /* preallocation op: unwritten space */
|
||||||
#define XFS_BMAPI_ATTRFORK 0x010 /* use attribute fork not data */
|
#define XFS_BMAPI_IGSTATE 0x010 /* Ignore state - */
|
||||||
#define XFS_BMAPI_PREALLOC 0x040 /* preallocation op: unwritten space */
|
|
||||||
#define XFS_BMAPI_IGSTATE 0x080 /* Ignore state - */
|
|
||||||
/* combine contig. space */
|
/* combine contig. space */
|
||||||
#define XFS_BMAPI_CONTIG 0x100 /* must allocate only one extent */
|
#define XFS_BMAPI_CONTIG 0x020 /* must allocate only one extent */
|
||||||
/*
|
/*
|
||||||
* unwritten extent conversion - this needs write cache flushing and no additional
|
* unwritten extent conversion - this needs write cache flushing and no additional
|
||||||
* allocation alignments. When specified with XFS_BMAPI_PREALLOC it converts
|
* allocation alignments. When specified with XFS_BMAPI_PREALLOC it converts
|
||||||
* from written to unwritten, otherwise convert from unwritten to written.
|
* from written to unwritten, otherwise convert from unwritten to written.
|
||||||
*/
|
*/
|
||||||
#define XFS_BMAPI_CONVERT 0x200
|
#define XFS_BMAPI_CONVERT 0x040
|
||||||
|
|
||||||
#define XFS_BMAPI_FLAGS \
|
#define XFS_BMAPI_FLAGS \
|
||||||
{ XFS_BMAPI_WRITE, "WRITE" }, \
|
|
||||||
{ XFS_BMAPI_DELAY, "DELAY" }, \
|
|
||||||
{ XFS_BMAPI_ENTIRE, "ENTIRE" }, \
|
{ XFS_BMAPI_ENTIRE, "ENTIRE" }, \
|
||||||
{ XFS_BMAPI_METADATA, "METADATA" }, \
|
{ XFS_BMAPI_METADATA, "METADATA" }, \
|
||||||
{ XFS_BMAPI_ATTRFORK, "ATTRFORK" }, \
|
{ XFS_BMAPI_ATTRFORK, "ATTRFORK" }, \
|
||||||
@ -113,21 +109,28 @@ static inline void xfs_bmap_init(xfs_bmap_free_t *flp, xfs_fsblock_t *fbp)
|
|||||||
* Argument structure for xfs_bmap_alloc.
|
* Argument structure for xfs_bmap_alloc.
|
||||||
*/
|
*/
|
||||||
typedef struct xfs_bmalloca {
|
typedef struct xfs_bmalloca {
|
||||||
xfs_fsblock_t firstblock; /* i/o first block allocated */
|
xfs_fsblock_t *firstblock; /* i/o first block allocated */
|
||||||
xfs_fsblock_t rval; /* starting block of new extent */
|
struct xfs_bmap_free *flist; /* bmap freelist */
|
||||||
xfs_fileoff_t off; /* offset in file filling in */
|
|
||||||
struct xfs_trans *tp; /* transaction pointer */
|
struct xfs_trans *tp; /* transaction pointer */
|
||||||
struct xfs_inode *ip; /* incore inode pointer */
|
struct xfs_inode *ip; /* incore inode pointer */
|
||||||
struct xfs_bmbt_irec *prevp; /* extent before the new one */
|
struct xfs_bmbt_irec prev; /* extent before the new one */
|
||||||
struct xfs_bmbt_irec *gotp; /* extent after, or delayed */
|
struct xfs_bmbt_irec got; /* extent after, or delayed */
|
||||||
xfs_extlen_t alen; /* i/o length asked/allocated */
|
|
||||||
|
xfs_fileoff_t offset; /* offset in file filling in */
|
||||||
|
xfs_extlen_t length; /* i/o length asked/allocated */
|
||||||
|
xfs_fsblock_t blkno; /* starting block of new extent */
|
||||||
|
|
||||||
|
struct xfs_btree_cur *cur; /* btree cursor */
|
||||||
|
xfs_extnum_t idx; /* current extent index */
|
||||||
|
int nallocs;/* number of extents alloc'd */
|
||||||
|
int logflags;/* flags for transaction logging */
|
||||||
|
|
||||||
xfs_extlen_t total; /* total blocks needed for xaction */
|
xfs_extlen_t total; /* total blocks needed for xaction */
|
||||||
xfs_extlen_t minlen; /* minimum allocation size (blocks) */
|
xfs_extlen_t minlen; /* minimum allocation size (blocks) */
|
||||||
xfs_extlen_t minleft; /* amount must be left after alloc */
|
xfs_extlen_t minleft; /* amount must be left after alloc */
|
||||||
char eof; /* set if allocating past last extent */
|
char eof; /* set if allocating past last extent */
|
||||||
char wasdel; /* replacing a delayed allocation */
|
char wasdel; /* replacing a delayed allocation */
|
||||||
char userdata;/* set if is user data */
|
char userdata;/* set if is user data */
|
||||||
char low; /* low on space, using seq'l ags */
|
|
||||||
char aeof; /* allocated space at eof */
|
char aeof; /* allocated space at eof */
|
||||||
char conv; /* overwriting unwritten extents */
|
char conv; /* overwriting unwritten extents */
|
||||||
} xfs_bmalloca_t;
|
} xfs_bmalloca_t;
|
||||||
@ -152,251 +155,62 @@ typedef struct xfs_bmalloca {
|
|||||||
{ BMAP_RIGHT_FILLING, "RF" }, \
|
{ BMAP_RIGHT_FILLING, "RF" }, \
|
||||||
{ BMAP_ATTRFORK, "ATTR" }
|
{ BMAP_ATTRFORK, "ATTR" }
|
||||||
|
|
||||||
/*
|
|
||||||
* Add bmap trace insert entries for all the contents of the extent list.
|
|
||||||
*
|
|
||||||
* Quite excessive tracing. Only do this for debug builds.
|
|
||||||
*/
|
|
||||||
#if defined(__KERNEL) && defined(DEBUG)
|
#if defined(__KERNEL) && defined(DEBUG)
|
||||||
void
|
void xfs_bmap_trace_exlist(struct xfs_inode *ip, xfs_extnum_t cnt,
|
||||||
xfs_bmap_trace_exlist(
|
int whichfork, unsigned long caller_ip);
|
||||||
struct xfs_inode *ip, /* incore inode pointer */
|
|
||||||
xfs_extnum_t cnt, /* count of entries in list */
|
|
||||||
int whichfork,
|
|
||||||
unsigned long caller_ip); /* data or attr fork */
|
|
||||||
#define XFS_BMAP_TRACE_EXLIST(ip,c,w) \
|
#define XFS_BMAP_TRACE_EXLIST(ip,c,w) \
|
||||||
xfs_bmap_trace_exlist(ip,c,w, _THIS_IP_)
|
xfs_bmap_trace_exlist(ip,c,w, _THIS_IP_)
|
||||||
#else
|
#else
|
||||||
#define XFS_BMAP_TRACE_EXLIST(ip,c,w)
|
#define XFS_BMAP_TRACE_EXLIST(ip,c,w)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
int xfs_bmap_add_attrfork(struct xfs_inode *ip, int size, int rsvd);
|
||||||
* Convert inode from non-attributed to attributed.
|
void xfs_bmap_add_free(xfs_fsblock_t bno, xfs_filblks_t len,
|
||||||
* Must not be in a transaction, ip must not be locked.
|
struct xfs_bmap_free *flist, struct xfs_mount *mp);
|
||||||
*/
|
void xfs_bmap_cancel(struct xfs_bmap_free *flist);
|
||||||
int /* error code */
|
void xfs_bmap_compute_maxlevels(struct xfs_mount *mp, int whichfork);
|
||||||
xfs_bmap_add_attrfork(
|
int xfs_bmap_first_unused(struct xfs_trans *tp, struct xfs_inode *ip,
|
||||||
struct xfs_inode *ip, /* incore inode pointer */
|
xfs_extlen_t len, xfs_fileoff_t *unused, int whichfork);
|
||||||
int size, /* space needed for new attribute */
|
int xfs_bmap_last_before(struct xfs_trans *tp, struct xfs_inode *ip,
|
||||||
int rsvd); /* flag for reserved block allocation */
|
xfs_fileoff_t *last_block, int whichfork);
|
||||||
|
int xfs_bmap_last_offset(struct xfs_trans *tp, struct xfs_inode *ip,
|
||||||
/*
|
xfs_fileoff_t *unused, int whichfork);
|
||||||
* Add the extent to the list of extents to be free at transaction end.
|
int xfs_bmap_one_block(struct xfs_inode *ip, int whichfork);
|
||||||
* The list is maintained sorted (by block number).
|
int xfs_bmap_read_extents(struct xfs_trans *tp, struct xfs_inode *ip,
|
||||||
*/
|
int whichfork);
|
||||||
void
|
int xfs_bmapi_read(struct xfs_inode *ip, xfs_fileoff_t bno,
|
||||||
xfs_bmap_add_free(
|
xfs_filblks_t len, struct xfs_bmbt_irec *mval,
|
||||||
xfs_fsblock_t bno, /* fs block number of extent */
|
int *nmap, int flags);
|
||||||
xfs_filblks_t len, /* length of extent */
|
int xfs_bmapi_delay(struct xfs_inode *ip, xfs_fileoff_t bno,
|
||||||
xfs_bmap_free_t *flist, /* list of extents */
|
xfs_filblks_t len, struct xfs_bmbt_irec *mval,
|
||||||
struct xfs_mount *mp); /* mount point structure */
|
int *nmap, int flags);
|
||||||
|
int xfs_bmapi_write(struct xfs_trans *tp, struct xfs_inode *ip,
|
||||||
/*
|
xfs_fileoff_t bno, xfs_filblks_t len, int flags,
|
||||||
* Routine to clean up the free list data structure when
|
xfs_fsblock_t *firstblock, xfs_extlen_t total,
|
||||||
* an error occurs during a transaction.
|
struct xfs_bmbt_irec *mval, int *nmap,
|
||||||
*/
|
struct xfs_bmap_free *flist);
|
||||||
void
|
int xfs_bunmapi(struct xfs_trans *tp, struct xfs_inode *ip,
|
||||||
xfs_bmap_cancel(
|
xfs_fileoff_t bno, xfs_filblks_t len, int flags,
|
||||||
xfs_bmap_free_t *flist); /* free list to clean up */
|
xfs_extnum_t nexts, xfs_fsblock_t *firstblock,
|
||||||
|
struct xfs_bmap_free *flist, int *done);
|
||||||
/*
|
int xfs_check_nostate_extents(struct xfs_ifork *ifp, xfs_extnum_t idx,
|
||||||
* Compute and fill in the value of the maximum depth of a bmap btree
|
xfs_extnum_t num);
|
||||||
* in this filesystem. Done once, during mount.
|
uint xfs_default_attroffset(struct xfs_inode *ip);
|
||||||
*/
|
|
||||||
void
|
|
||||||
xfs_bmap_compute_maxlevels(
|
|
||||||
struct xfs_mount *mp, /* file system mount structure */
|
|
||||||
int whichfork); /* data or attr fork */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Returns the file-relative block number of the first unused block in the file.
|
|
||||||
* This is the lowest-address hole if the file has holes, else the first block
|
|
||||||
* past the end of file.
|
|
||||||
*/
|
|
||||||
int /* error */
|
|
||||||
xfs_bmap_first_unused(
|
|
||||||
struct xfs_trans *tp, /* transaction pointer */
|
|
||||||
struct xfs_inode *ip, /* incore inode */
|
|
||||||
xfs_extlen_t len, /* size of hole to find */
|
|
||||||
xfs_fileoff_t *unused, /* unused block num */
|
|
||||||
int whichfork); /* data or attr fork */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Returns the file-relative block number of the last block + 1 before
|
|
||||||
* last_block (input value) in the file.
|
|
||||||
* This is not based on i_size, it is based on the extent list.
|
|
||||||
* Returns 0 for local files, as they do not have an extent list.
|
|
||||||
*/
|
|
||||||
int /* error */
|
|
||||||
xfs_bmap_last_before(
|
|
||||||
struct xfs_trans *tp, /* transaction pointer */
|
|
||||||
struct xfs_inode *ip, /* incore inode */
|
|
||||||
xfs_fileoff_t *last_block, /* last block */
|
|
||||||
int whichfork); /* data or attr fork */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Returns the file-relative block number of the first block past eof in
|
|
||||||
* the file. This is not based on i_size, it is based on the extent list.
|
|
||||||
* Returns 0 for local files, as they do not have an extent list.
|
|
||||||
*/
|
|
||||||
int /* error */
|
|
||||||
xfs_bmap_last_offset(
|
|
||||||
struct xfs_trans *tp, /* transaction pointer */
|
|
||||||
struct xfs_inode *ip, /* incore inode */
|
|
||||||
xfs_fileoff_t *unused, /* last block num */
|
|
||||||
int whichfork); /* data or attr fork */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Returns whether the selected fork of the inode has exactly one
|
|
||||||
* block or not. For the data fork we check this matches di_size,
|
|
||||||
* implying the file's range is 0..bsize-1.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
xfs_bmap_one_block(
|
|
||||||
struct xfs_inode *ip, /* incore inode */
|
|
||||||
int whichfork); /* data or attr fork */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Read in the extents to iu_extents.
|
|
||||||
* All inode fields are set up by caller, we just traverse the btree
|
|
||||||
* and copy the records in.
|
|
||||||
*/
|
|
||||||
int /* error */
|
|
||||||
xfs_bmap_read_extents(
|
|
||||||
struct xfs_trans *tp, /* transaction pointer */
|
|
||||||
struct xfs_inode *ip, /* incore inode */
|
|
||||||
int whichfork); /* data or attr fork */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Map file blocks to filesystem blocks.
|
|
||||||
* File range is given by the bno/len pair.
|
|
||||||
* Adds blocks to file if a write ("flags & XFS_BMAPI_WRITE" set)
|
|
||||||
* into a hole or past eof.
|
|
||||||
* Only allocates blocks from a single allocation group,
|
|
||||||
* to avoid locking problems.
|
|
||||||
* The returned value in "firstblock" from the first call in a transaction
|
|
||||||
* must be remembered and presented to subsequent calls in "firstblock".
|
|
||||||
* An upper bound for the number of blocks to be allocated is supplied to
|
|
||||||
* the first call in "total"; if no allocation group has that many free
|
|
||||||
* blocks then the call will fail (return NULLFSBLOCK in "firstblock").
|
|
||||||
*/
|
|
||||||
int /* error */
|
|
||||||
xfs_bmapi(
|
|
||||||
struct xfs_trans *tp, /* transaction pointer */
|
|
||||||
struct xfs_inode *ip, /* incore inode */
|
|
||||||
xfs_fileoff_t bno, /* starting file offs. mapped */
|
|
||||||
xfs_filblks_t len, /* length to map in file */
|
|
||||||
int flags, /* XFS_BMAPI_... */
|
|
||||||
xfs_fsblock_t *firstblock, /* first allocated block
|
|
||||||
controls a.g. for allocs */
|
|
||||||
xfs_extlen_t total, /* total blocks needed */
|
|
||||||
struct xfs_bmbt_irec *mval, /* output: map values */
|
|
||||||
int *nmap, /* i/o: mval size/count */
|
|
||||||
xfs_bmap_free_t *flist); /* i/o: list extents to free */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Map file blocks to filesystem blocks, simple version.
|
|
||||||
* One block only, read-only.
|
|
||||||
* For flags, only the XFS_BMAPI_ATTRFORK flag is examined.
|
|
||||||
* For the other flag values, the effect is as if XFS_BMAPI_METADATA
|
|
||||||
* was set and all the others were clear.
|
|
||||||
*/
|
|
||||||
int /* error */
|
|
||||||
xfs_bmapi_single(
|
|
||||||
struct xfs_trans *tp, /* transaction pointer */
|
|
||||||
struct xfs_inode *ip, /* incore inode */
|
|
||||||
int whichfork, /* data or attr fork */
|
|
||||||
xfs_fsblock_t *fsb, /* output: mapped block */
|
|
||||||
xfs_fileoff_t bno); /* starting file offs. mapped */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Unmap (remove) blocks from a file.
|
|
||||||
* If nexts is nonzero then the number of extents to remove is limited to
|
|
||||||
* that value. If not all extents in the block range can be removed then
|
|
||||||
* *done is set.
|
|
||||||
*/
|
|
||||||
int /* error */
|
|
||||||
xfs_bunmapi(
|
|
||||||
struct xfs_trans *tp, /* transaction pointer */
|
|
||||||
struct xfs_inode *ip, /* incore inode */
|
|
||||||
xfs_fileoff_t bno, /* starting offset to unmap */
|
|
||||||
xfs_filblks_t len, /* length to unmap in file */
|
|
||||||
int flags, /* XFS_BMAPI_... */
|
|
||||||
xfs_extnum_t nexts, /* number of extents max */
|
|
||||||
xfs_fsblock_t *firstblock, /* first allocated block
|
|
||||||
controls a.g. for allocs */
|
|
||||||
xfs_bmap_free_t *flist, /* i/o: list extents to free */
|
|
||||||
int *done); /* set if not done yet */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check an extent list, which has just been read, for
|
|
||||||
* any bit in the extent flag field.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
xfs_check_nostate_extents(
|
|
||||||
struct xfs_ifork *ifp,
|
|
||||||
xfs_extnum_t idx,
|
|
||||||
xfs_extnum_t num);
|
|
||||||
|
|
||||||
uint
|
|
||||||
xfs_default_attroffset(
|
|
||||||
struct xfs_inode *ip);
|
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
|
|
||||||
/*
|
|
||||||
* Routine to be called at transaction's end by xfs_bmapi, xfs_bunmapi
|
|
||||||
* caller. Frees all the extents that need freeing, which must be done
|
|
||||||
* last due to locking considerations.
|
|
||||||
*
|
|
||||||
* Return 1 if the given transaction was committed and a new one allocated,
|
|
||||||
* and 0 otherwise.
|
|
||||||
*/
|
|
||||||
int /* error */
|
|
||||||
xfs_bmap_finish(
|
|
||||||
struct xfs_trans **tp, /* transaction pointer addr */
|
|
||||||
xfs_bmap_free_t *flist, /* i/o: list extents to free */
|
|
||||||
int *committed); /* xact committed or not */
|
|
||||||
|
|
||||||
/* bmap to userspace formatter - copy to user & advance pointer */
|
/* bmap to userspace formatter - copy to user & advance pointer */
|
||||||
typedef int (*xfs_bmap_format_t)(void **, struct getbmapx *, int *);
|
typedef int (*xfs_bmap_format_t)(void **, struct getbmapx *, int *);
|
||||||
|
|
||||||
/*
|
int xfs_bmap_finish(struct xfs_trans **tp, struct xfs_bmap_free *flist,
|
||||||
* Get inode's extents as described in bmv, and format for output.
|
int *committed);
|
||||||
*/
|
int xfs_getbmap(struct xfs_inode *ip, struct getbmapx *bmv,
|
||||||
int /* error code */
|
xfs_bmap_format_t formatter, void *arg);
|
||||||
xfs_getbmap(
|
int xfs_bmap_eof(struct xfs_inode *ip, xfs_fileoff_t endoff,
|
||||||
xfs_inode_t *ip,
|
int whichfork, int *eof);
|
||||||
struct getbmapx *bmv, /* user bmap structure */
|
int xfs_bmap_count_blocks(struct xfs_trans *tp, struct xfs_inode *ip,
|
||||||
xfs_bmap_format_t formatter, /* format to user */
|
int whichfork, int *count);
|
||||||
void *arg); /* formatter arg */
|
int xfs_bmap_punch_delalloc_range(struct xfs_inode *ip,
|
||||||
|
xfs_fileoff_t start_fsb, xfs_fileoff_t length);
|
||||||
/*
|
|
||||||
* Check if the endoff is outside the last extent. If so the caller will grow
|
|
||||||
* the allocation to a stripe unit boundary
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
xfs_bmap_eof(
|
|
||||||
struct xfs_inode *ip,
|
|
||||||
xfs_fileoff_t endoff,
|
|
||||||
int whichfork,
|
|
||||||
int *eof);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Count fsblocks of the given fork.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
xfs_bmap_count_blocks(
|
|
||||||
xfs_trans_t *tp,
|
|
||||||
struct xfs_inode *ip,
|
|
||||||
int whichfork,
|
|
||||||
int *count);
|
|
||||||
|
|
||||||
int
|
|
||||||
xfs_bmap_punch_delalloc_range(
|
|
||||||
struct xfs_inode *ip,
|
|
||||||
xfs_fileoff_t start_fsb,
|
|
||||||
xfs_fileoff_t length);
|
|
||||||
#endif /* __KERNEL__ */
|
#endif /* __KERNEL__ */
|
||||||
|
|
||||||
#endif /* __XFS_BMAP_H__ */
|
#endif /* __XFS_BMAP_H__ */
|
||||||
|
@ -631,7 +631,7 @@ xfs_btree_read_bufl(
|
|||||||
}
|
}
|
||||||
ASSERT(!xfs_buf_geterror(bp));
|
ASSERT(!xfs_buf_geterror(bp));
|
||||||
if (bp)
|
if (bp)
|
||||||
XFS_BUF_SET_VTYPE_REF(bp, B_FS_MAP, refval);
|
xfs_buf_set_ref(bp, refval);
|
||||||
*bpp = bp;
|
*bpp = bp;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -939,13 +939,13 @@ xfs_btree_set_refs(
|
|||||||
switch (cur->bc_btnum) {
|
switch (cur->bc_btnum) {
|
||||||
case XFS_BTNUM_BNO:
|
case XFS_BTNUM_BNO:
|
||||||
case XFS_BTNUM_CNT:
|
case XFS_BTNUM_CNT:
|
||||||
XFS_BUF_SET_VTYPE_REF(bp, B_FS_MAP, XFS_ALLOC_BTREE_REF);
|
xfs_buf_set_ref(bp, XFS_ALLOC_BTREE_REF);
|
||||||
break;
|
break;
|
||||||
case XFS_BTNUM_INO:
|
case XFS_BTNUM_INO:
|
||||||
XFS_BUF_SET_VTYPE_REF(bp, B_FS_INOMAP, XFS_INO_BTREE_REF);
|
xfs_buf_set_ref(bp, XFS_INO_BTREE_REF);
|
||||||
break;
|
break;
|
||||||
case XFS_BTNUM_BMAP:
|
case XFS_BTNUM_BMAP:
|
||||||
XFS_BUF_SET_VTYPE_REF(bp, B_FS_MAP, XFS_BMAP_BTREE_REF);
|
xfs_buf_set_ref(bp, XFS_BMAP_BTREE_REF);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ASSERT(0);
|
ASSERT(0);
|
||||||
@ -970,7 +970,8 @@ xfs_btree_get_buf_block(
|
|||||||
*bpp = xfs_trans_get_buf(cur->bc_tp, mp->m_ddev_targp, d,
|
*bpp = xfs_trans_get_buf(cur->bc_tp, mp->m_ddev_targp, d,
|
||||||
mp->m_bsize, flags);
|
mp->m_bsize, flags);
|
||||||
|
|
||||||
ASSERT(!xfs_buf_geterror(*bpp));
|
if (!*bpp)
|
||||||
|
return ENOMEM;
|
||||||
|
|
||||||
*block = XFS_BUF_TO_BLOCK(*bpp);
|
*block = XFS_BUF_TO_BLOCK(*bpp);
|
||||||
return 0;
|
return 0;
|
||||||
|
244
fs/xfs/xfs_buf.c
244
fs/xfs/xfs_buf.c
@ -43,7 +43,6 @@
|
|||||||
|
|
||||||
static kmem_zone_t *xfs_buf_zone;
|
static kmem_zone_t *xfs_buf_zone;
|
||||||
STATIC int xfsbufd(void *);
|
STATIC int xfsbufd(void *);
|
||||||
STATIC void xfs_buf_delwri_queue(xfs_buf_t *, int);
|
|
||||||
|
|
||||||
static struct workqueue_struct *xfslogd_workqueue;
|
static struct workqueue_struct *xfslogd_workqueue;
|
||||||
struct workqueue_struct *xfsdatad_workqueue;
|
struct workqueue_struct *xfsdatad_workqueue;
|
||||||
@ -66,10 +65,6 @@ struct workqueue_struct *xfsconvertd_workqueue;
|
|||||||
#define xb_to_km(flags) \
|
#define xb_to_km(flags) \
|
||||||
(((flags) & XBF_DONT_BLOCK) ? KM_NOFS : KM_SLEEP)
|
(((flags) & XBF_DONT_BLOCK) ? KM_NOFS : KM_SLEEP)
|
||||||
|
|
||||||
#define xfs_buf_allocate(flags) \
|
|
||||||
kmem_zone_alloc(xfs_buf_zone, xb_to_km(flags))
|
|
||||||
#define xfs_buf_deallocate(bp) \
|
|
||||||
kmem_zone_free(xfs_buf_zone, (bp));
|
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
xfs_buf_is_vmapped(
|
xfs_buf_is_vmapped(
|
||||||
@ -152,6 +147,7 @@ xfs_buf_stale(
|
|||||||
struct xfs_buf *bp)
|
struct xfs_buf *bp)
|
||||||
{
|
{
|
||||||
bp->b_flags |= XBF_STALE;
|
bp->b_flags |= XBF_STALE;
|
||||||
|
xfs_buf_delwri_dequeue(bp);
|
||||||
atomic_set(&(bp)->b_lru_ref, 0);
|
atomic_set(&(bp)->b_lru_ref, 0);
|
||||||
if (!list_empty(&bp->b_lru)) {
|
if (!list_empty(&bp->b_lru)) {
|
||||||
struct xfs_buftarg *btp = bp->b_target;
|
struct xfs_buftarg *btp = bp->b_target;
|
||||||
@ -167,14 +163,19 @@ xfs_buf_stale(
|
|||||||
ASSERT(atomic_read(&bp->b_hold) >= 1);
|
ASSERT(atomic_read(&bp->b_hold) >= 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC void
|
struct xfs_buf *
|
||||||
_xfs_buf_initialize(
|
xfs_buf_alloc(
|
||||||
xfs_buf_t *bp,
|
struct xfs_buftarg *target,
|
||||||
xfs_buftarg_t *target,
|
|
||||||
xfs_off_t range_base,
|
xfs_off_t range_base,
|
||||||
size_t range_length,
|
size_t range_length,
|
||||||
xfs_buf_flags_t flags)
|
xfs_buf_flags_t flags)
|
||||||
{
|
{
|
||||||
|
struct xfs_buf *bp;
|
||||||
|
|
||||||
|
bp = kmem_zone_alloc(xfs_buf_zone, xb_to_km(flags));
|
||||||
|
if (unlikely(!bp))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We don't want certain flags to appear in b_flags.
|
* We don't want certain flags to appear in b_flags.
|
||||||
*/
|
*/
|
||||||
@ -203,8 +204,9 @@ _xfs_buf_initialize(
|
|||||||
init_waitqueue_head(&bp->b_waiters);
|
init_waitqueue_head(&bp->b_waiters);
|
||||||
|
|
||||||
XFS_STATS_INC(xb_create);
|
XFS_STATS_INC(xb_create);
|
||||||
|
|
||||||
trace_xfs_buf_init(bp, _RET_IP_);
|
trace_xfs_buf_init(bp, _RET_IP_);
|
||||||
|
|
||||||
|
return bp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -277,7 +279,7 @@ xfs_buf_free(
|
|||||||
} else if (bp->b_flags & _XBF_KMEM)
|
} else if (bp->b_flags & _XBF_KMEM)
|
||||||
kmem_free(bp->b_addr);
|
kmem_free(bp->b_addr);
|
||||||
_xfs_buf_free_pages(bp);
|
_xfs_buf_free_pages(bp);
|
||||||
xfs_buf_deallocate(bp);
|
kmem_zone_free(xfs_buf_zone, bp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -416,10 +418,7 @@ _xfs_buf_map_pages(
|
|||||||
/*
|
/*
|
||||||
* Look up, and creates if absent, a lockable buffer for
|
* Look up, and creates if absent, a lockable buffer for
|
||||||
* a given range of an inode. The buffer is returned
|
* a given range of an inode. The buffer is returned
|
||||||
* locked. If other overlapping buffers exist, they are
|
* locked. No I/O is implied by this call.
|
||||||
* released before the new buffer is created and locked,
|
|
||||||
* which may imply that this call will block until those buffers
|
|
||||||
* are unlocked. No I/O is implied by this call.
|
|
||||||
*/
|
*/
|
||||||
xfs_buf_t *
|
xfs_buf_t *
|
||||||
_xfs_buf_find(
|
_xfs_buf_find(
|
||||||
@ -481,8 +480,6 @@ _xfs_buf_find(
|
|||||||
|
|
||||||
/* No match found */
|
/* No match found */
|
||||||
if (new_bp) {
|
if (new_bp) {
|
||||||
_xfs_buf_initialize(new_bp, btp, range_base,
|
|
||||||
range_length, flags);
|
|
||||||
rb_link_node(&new_bp->b_rbnode, parent, rbp);
|
rb_link_node(&new_bp->b_rbnode, parent, rbp);
|
||||||
rb_insert_color(&new_bp->b_rbnode, &pag->pag_buf_tree);
|
rb_insert_color(&new_bp->b_rbnode, &pag->pag_buf_tree);
|
||||||
/* the buffer keeps the perag reference until it is freed */
|
/* the buffer keeps the perag reference until it is freed */
|
||||||
@ -525,35 +522,51 @@ found:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Assembles a buffer covering the specified range.
|
* Assembles a buffer covering the specified range. The code is optimised for
|
||||||
* Storage in memory for all portions of the buffer will be allocated,
|
* cache hits, as metadata intensive workloads will see 3 orders of magnitude
|
||||||
* although backing storage may not be.
|
* more hits than misses.
|
||||||
*/
|
*/
|
||||||
xfs_buf_t *
|
struct xfs_buf *
|
||||||
xfs_buf_get(
|
xfs_buf_get(
|
||||||
xfs_buftarg_t *target,/* target for buffer */
|
xfs_buftarg_t *target,/* target for buffer */
|
||||||
xfs_off_t ioff, /* starting offset of range */
|
xfs_off_t ioff, /* starting offset of range */
|
||||||
size_t isize, /* length of range */
|
size_t isize, /* length of range */
|
||||||
xfs_buf_flags_t flags)
|
xfs_buf_flags_t flags)
|
||||||
{
|
{
|
||||||
xfs_buf_t *bp, *new_bp;
|
struct xfs_buf *bp;
|
||||||
|
struct xfs_buf *new_bp;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
new_bp = xfs_buf_allocate(flags);
|
bp = _xfs_buf_find(target, ioff, isize, flags, NULL);
|
||||||
|
if (likely(bp))
|
||||||
|
goto found;
|
||||||
|
|
||||||
|
new_bp = xfs_buf_alloc(target, ioff << BBSHIFT, isize << BBSHIFT,
|
||||||
|
flags);
|
||||||
if (unlikely(!new_bp))
|
if (unlikely(!new_bp))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
bp = _xfs_buf_find(target, ioff, isize, flags, new_bp);
|
bp = _xfs_buf_find(target, ioff, isize, flags, new_bp);
|
||||||
|
if (!bp) {
|
||||||
|
kmem_zone_free(xfs_buf_zone, new_bp);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (bp == new_bp) {
|
if (bp == new_bp) {
|
||||||
error = xfs_buf_allocate_memory(bp, flags);
|
error = xfs_buf_allocate_memory(bp, flags);
|
||||||
if (error)
|
if (error)
|
||||||
goto no_buffer;
|
goto no_buffer;
|
||||||
} else {
|
} else
|
||||||
xfs_buf_deallocate(new_bp);
|
kmem_zone_free(xfs_buf_zone, new_bp);
|
||||||
if (unlikely(bp == NULL))
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now we have a workable buffer, fill in the block number so
|
||||||
|
* that we can do IO on it.
|
||||||
|
*/
|
||||||
|
bp->b_bn = ioff;
|
||||||
|
bp->b_count_desired = bp->b_buffer_length;
|
||||||
|
|
||||||
|
found:
|
||||||
if (!(bp->b_flags & XBF_MAPPED)) {
|
if (!(bp->b_flags & XBF_MAPPED)) {
|
||||||
error = _xfs_buf_map_pages(bp, flags);
|
error = _xfs_buf_map_pages(bp, flags);
|
||||||
if (unlikely(error)) {
|
if (unlikely(error)) {
|
||||||
@ -564,18 +577,10 @@ xfs_buf_get(
|
|||||||
}
|
}
|
||||||
|
|
||||||
XFS_STATS_INC(xb_get);
|
XFS_STATS_INC(xb_get);
|
||||||
|
|
||||||
/*
|
|
||||||
* Always fill in the block number now, the mapped cases can do
|
|
||||||
* their own overlay of this later.
|
|
||||||
*/
|
|
||||||
bp->b_bn = ioff;
|
|
||||||
bp->b_count_desired = bp->b_buffer_length;
|
|
||||||
|
|
||||||
trace_xfs_buf_get(bp, flags, _RET_IP_);
|
trace_xfs_buf_get(bp, flags, _RET_IP_);
|
||||||
return bp;
|
return bp;
|
||||||
|
|
||||||
no_buffer:
|
no_buffer:
|
||||||
if (flags & (XBF_LOCK | XBF_TRYLOCK))
|
if (flags & (XBF_LOCK | XBF_TRYLOCK))
|
||||||
xfs_buf_unlock(bp);
|
xfs_buf_unlock(bp);
|
||||||
xfs_buf_rele(bp);
|
xfs_buf_rele(bp);
|
||||||
@ -689,19 +694,6 @@ xfs_buf_read_uncached(
|
|||||||
return bp;
|
return bp;
|
||||||
}
|
}
|
||||||
|
|
||||||
xfs_buf_t *
|
|
||||||
xfs_buf_get_empty(
|
|
||||||
size_t len,
|
|
||||||
xfs_buftarg_t *target)
|
|
||||||
{
|
|
||||||
xfs_buf_t *bp;
|
|
||||||
|
|
||||||
bp = xfs_buf_allocate(0);
|
|
||||||
if (bp)
|
|
||||||
_xfs_buf_initialize(bp, target, 0, len, 0);
|
|
||||||
return bp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return a buffer allocated as an empty buffer and associated to external
|
* Return a buffer allocated as an empty buffer and associated to external
|
||||||
* memory via xfs_buf_associate_memory() back to it's empty state.
|
* memory via xfs_buf_associate_memory() back to it's empty state.
|
||||||
@ -787,10 +779,9 @@ xfs_buf_get_uncached(
|
|||||||
int error, i;
|
int error, i;
|
||||||
xfs_buf_t *bp;
|
xfs_buf_t *bp;
|
||||||
|
|
||||||
bp = xfs_buf_allocate(0);
|
bp = xfs_buf_alloc(target, 0, len, 0);
|
||||||
if (unlikely(bp == NULL))
|
if (unlikely(bp == NULL))
|
||||||
goto fail;
|
goto fail;
|
||||||
_xfs_buf_initialize(bp, target, 0, len, 0);
|
|
||||||
|
|
||||||
error = _xfs_buf_get_pages(bp, page_count, 0);
|
error = _xfs_buf_get_pages(bp, page_count, 0);
|
||||||
if (error)
|
if (error)
|
||||||
@ -818,7 +809,7 @@ xfs_buf_get_uncached(
|
|||||||
__free_page(bp->b_pages[i]);
|
__free_page(bp->b_pages[i]);
|
||||||
_xfs_buf_free_pages(bp);
|
_xfs_buf_free_pages(bp);
|
||||||
fail_free_buf:
|
fail_free_buf:
|
||||||
xfs_buf_deallocate(bp);
|
kmem_zone_free(xfs_buf_zone, bp);
|
||||||
fail:
|
fail:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -937,12 +928,6 @@ void
|
|||||||
xfs_buf_unlock(
|
xfs_buf_unlock(
|
||||||
struct xfs_buf *bp)
|
struct xfs_buf *bp)
|
||||||
{
|
{
|
||||||
if ((bp->b_flags & (XBF_DELWRI|_XBF_DELWRI_Q)) == XBF_DELWRI) {
|
|
||||||
atomic_inc(&bp->b_hold);
|
|
||||||
bp->b_flags |= XBF_ASYNC;
|
|
||||||
xfs_buf_delwri_queue(bp, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
XB_CLEAR_OWNER(bp);
|
XB_CLEAR_OWNER(bp);
|
||||||
up(&bp->b_sema);
|
up(&bp->b_sema);
|
||||||
|
|
||||||
@ -1019,9 +1004,19 @@ xfs_buf_ioerror(
|
|||||||
trace_xfs_buf_ioerror(bp, error, _RET_IP_);
|
trace_xfs_buf_ioerror(bp, error, _RET_IP_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xfs_buf_ioerror_alert(
|
||||||
|
struct xfs_buf *bp,
|
||||||
|
const char *func)
|
||||||
|
{
|
||||||
|
xfs_alert(bp->b_target->bt_mount,
|
||||||
|
"metadata I/O error: block 0x%llx (\"%s\") error %d buf count %zd",
|
||||||
|
(__uint64_t)XFS_BUF_ADDR(bp), func,
|
||||||
|
bp->b_error, XFS_BUF_COUNT(bp));
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
xfs_bwrite(
|
xfs_bwrite(
|
||||||
struct xfs_mount *mp,
|
|
||||||
struct xfs_buf *bp)
|
struct xfs_buf *bp)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
@ -1033,25 +1028,13 @@ xfs_bwrite(
|
|||||||
xfs_bdstrat_cb(bp);
|
xfs_bdstrat_cb(bp);
|
||||||
|
|
||||||
error = xfs_buf_iowait(bp);
|
error = xfs_buf_iowait(bp);
|
||||||
if (error)
|
if (error) {
|
||||||
xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR);
|
xfs_force_shutdown(bp->b_target->bt_mount,
|
||||||
xfs_buf_relse(bp);
|
SHUTDOWN_META_IO_ERROR);
|
||||||
|
}
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
xfs_bdwrite(
|
|
||||||
void *mp,
|
|
||||||
struct xfs_buf *bp)
|
|
||||||
{
|
|
||||||
trace_xfs_buf_bdwrite(bp, _RET_IP_);
|
|
||||||
|
|
||||||
bp->b_flags &= ~XBF_READ;
|
|
||||||
bp->b_flags |= (XBF_DELWRI | XBF_ASYNC);
|
|
||||||
|
|
||||||
xfs_buf_delwri_queue(bp, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called when we want to stop a buffer from getting written or read.
|
* Called when we want to stop a buffer from getting written or read.
|
||||||
* We attach the EIO error, muck with its flags, and call xfs_buf_ioend
|
* We attach the EIO error, muck with its flags, and call xfs_buf_ioend
|
||||||
@ -1074,9 +1057,8 @@ xfs_bioerror(
|
|||||||
* We're calling xfs_buf_ioend, so delete XBF_DONE flag.
|
* We're calling xfs_buf_ioend, so delete XBF_DONE flag.
|
||||||
*/
|
*/
|
||||||
XFS_BUF_UNREAD(bp);
|
XFS_BUF_UNREAD(bp);
|
||||||
XFS_BUF_UNDELAYWRITE(bp);
|
|
||||||
XFS_BUF_UNDONE(bp);
|
XFS_BUF_UNDONE(bp);
|
||||||
XFS_BUF_STALE(bp);
|
xfs_buf_stale(bp);
|
||||||
|
|
||||||
xfs_buf_ioend(bp, 0);
|
xfs_buf_ioend(bp, 0);
|
||||||
|
|
||||||
@ -1103,9 +1085,8 @@ xfs_bioerror_relse(
|
|||||||
* change that interface.
|
* change that interface.
|
||||||
*/
|
*/
|
||||||
XFS_BUF_UNREAD(bp);
|
XFS_BUF_UNREAD(bp);
|
||||||
XFS_BUF_UNDELAYWRITE(bp);
|
|
||||||
XFS_BUF_DONE(bp);
|
XFS_BUF_DONE(bp);
|
||||||
XFS_BUF_STALE(bp);
|
xfs_buf_stale(bp);
|
||||||
bp->b_iodone = NULL;
|
bp->b_iodone = NULL;
|
||||||
if (!(fl & XBF_ASYNC)) {
|
if (!(fl & XBF_ASYNC)) {
|
||||||
/*
|
/*
|
||||||
@ -1115,7 +1096,7 @@ xfs_bioerror_relse(
|
|||||||
* ASYNC buffers.
|
* ASYNC buffers.
|
||||||
*/
|
*/
|
||||||
xfs_buf_ioerror(bp, EIO);
|
xfs_buf_ioerror(bp, EIO);
|
||||||
XFS_BUF_FINISH_IOWAIT(bp);
|
complete(&bp->b_iowait);
|
||||||
} else {
|
} else {
|
||||||
xfs_buf_relse(bp);
|
xfs_buf_relse(bp);
|
||||||
}
|
}
|
||||||
@ -1275,15 +1256,10 @@ xfs_buf_iorequest(
|
|||||||
{
|
{
|
||||||
trace_xfs_buf_iorequest(bp, _RET_IP_);
|
trace_xfs_buf_iorequest(bp, _RET_IP_);
|
||||||
|
|
||||||
if (bp->b_flags & XBF_DELWRI) {
|
ASSERT(!(bp->b_flags & XBF_DELWRI));
|
||||||
xfs_buf_delwri_queue(bp, 1);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bp->b_flags & XBF_WRITE) {
|
if (bp->b_flags & XBF_WRITE)
|
||||||
xfs_buf_wait_unpin(bp);
|
xfs_buf_wait_unpin(bp);
|
||||||
}
|
|
||||||
|
|
||||||
xfs_buf_hold(bp);
|
xfs_buf_hold(bp);
|
||||||
|
|
||||||
/* Set the count to 1 initially, this will stop an I/O
|
/* Set the count to 1 initially, this will stop an I/O
|
||||||
@ -1481,9 +1457,13 @@ xfs_setsize_buftarg_flags(
|
|||||||
btp->bt_smask = sectorsize - 1;
|
btp->bt_smask = sectorsize - 1;
|
||||||
|
|
||||||
if (set_blocksize(btp->bt_bdev, sectorsize)) {
|
if (set_blocksize(btp->bt_bdev, sectorsize)) {
|
||||||
|
char name[BDEVNAME_SIZE];
|
||||||
|
|
||||||
|
bdevname(btp->bt_bdev, name);
|
||||||
|
|
||||||
xfs_warn(btp->bt_mount,
|
xfs_warn(btp->bt_mount,
|
||||||
"Cannot set_blocksize to %u on device %s\n",
|
"Cannot set_blocksize to %u on device %s\n",
|
||||||
sectorsize, xfs_buf_target_name(btp));
|
sectorsize, name);
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1514,12 +1494,12 @@ xfs_setsize_buftarg(
|
|||||||
}
|
}
|
||||||
|
|
||||||
STATIC int
|
STATIC int
|
||||||
xfs_alloc_delwrite_queue(
|
xfs_alloc_delwri_queue(
|
||||||
xfs_buftarg_t *btp,
|
xfs_buftarg_t *btp,
|
||||||
const char *fsname)
|
const char *fsname)
|
||||||
{
|
{
|
||||||
INIT_LIST_HEAD(&btp->bt_delwrite_queue);
|
INIT_LIST_HEAD(&btp->bt_delwri_queue);
|
||||||
spin_lock_init(&btp->bt_delwrite_lock);
|
spin_lock_init(&btp->bt_delwri_lock);
|
||||||
btp->bt_flags = 0;
|
btp->bt_flags = 0;
|
||||||
btp->bt_task = kthread_run(xfsbufd, btp, "xfsbufd/%s", fsname);
|
btp->bt_task = kthread_run(xfsbufd, btp, "xfsbufd/%s", fsname);
|
||||||
if (IS_ERR(btp->bt_task))
|
if (IS_ERR(btp->bt_task))
|
||||||
@ -1549,7 +1529,7 @@ xfs_alloc_buftarg(
|
|||||||
spin_lock_init(&btp->bt_lru_lock);
|
spin_lock_init(&btp->bt_lru_lock);
|
||||||
if (xfs_setsize_buftarg_early(btp, bdev))
|
if (xfs_setsize_buftarg_early(btp, bdev))
|
||||||
goto error;
|
goto error;
|
||||||
if (xfs_alloc_delwrite_queue(btp, fsname))
|
if (xfs_alloc_delwri_queue(btp, fsname))
|
||||||
goto error;
|
goto error;
|
||||||
btp->bt_shrinker.shrink = xfs_buftarg_shrink;
|
btp->bt_shrinker.shrink = xfs_buftarg_shrink;
|
||||||
btp->bt_shrinker.seeks = DEFAULT_SEEKS;
|
btp->bt_shrinker.seeks = DEFAULT_SEEKS;
|
||||||
@ -1565,56 +1545,48 @@ error:
|
|||||||
/*
|
/*
|
||||||
* Delayed write buffer handling
|
* Delayed write buffer handling
|
||||||
*/
|
*/
|
||||||
STATIC void
|
void
|
||||||
xfs_buf_delwri_queue(
|
xfs_buf_delwri_queue(
|
||||||
xfs_buf_t *bp,
|
xfs_buf_t *bp)
|
||||||
int unlock)
|
|
||||||
{
|
{
|
||||||
struct list_head *dwq = &bp->b_target->bt_delwrite_queue;
|
struct xfs_buftarg *btp = bp->b_target;
|
||||||
spinlock_t *dwlk = &bp->b_target->bt_delwrite_lock;
|
|
||||||
|
|
||||||
trace_xfs_buf_delwri_queue(bp, _RET_IP_);
|
trace_xfs_buf_delwri_queue(bp, _RET_IP_);
|
||||||
|
|
||||||
ASSERT((bp->b_flags&(XBF_DELWRI|XBF_ASYNC)) == (XBF_DELWRI|XBF_ASYNC));
|
ASSERT(!(bp->b_flags & XBF_READ));
|
||||||
|
|
||||||
spin_lock(dwlk);
|
spin_lock(&btp->bt_delwri_lock);
|
||||||
/* If already in the queue, dequeue and place at tail */
|
|
||||||
if (!list_empty(&bp->b_list)) {
|
if (!list_empty(&bp->b_list)) {
|
||||||
|
/* if already in the queue, move it to the tail */
|
||||||
ASSERT(bp->b_flags & _XBF_DELWRI_Q);
|
ASSERT(bp->b_flags & _XBF_DELWRI_Q);
|
||||||
if (unlock)
|
list_move_tail(&bp->b_list, &btp->bt_delwri_queue);
|
||||||
atomic_dec(&bp->b_hold);
|
} else {
|
||||||
list_del(&bp->b_list);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (list_empty(dwq)) {
|
|
||||||
/* start xfsbufd as it is about to have something to do */
|
/* start xfsbufd as it is about to have something to do */
|
||||||
wake_up_process(bp->b_target->bt_task);
|
if (list_empty(&btp->bt_delwri_queue))
|
||||||
|
wake_up_process(bp->b_target->bt_task);
|
||||||
|
|
||||||
|
atomic_inc(&bp->b_hold);
|
||||||
|
bp->b_flags |= XBF_DELWRI | _XBF_DELWRI_Q | XBF_ASYNC;
|
||||||
|
list_add_tail(&bp->b_list, &btp->bt_delwri_queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
bp->b_flags |= _XBF_DELWRI_Q;
|
|
||||||
list_add_tail(&bp->b_list, dwq);
|
|
||||||
bp->b_queuetime = jiffies;
|
bp->b_queuetime = jiffies;
|
||||||
spin_unlock(dwlk);
|
spin_unlock(&btp->bt_delwri_lock);
|
||||||
|
|
||||||
if (unlock)
|
|
||||||
xfs_buf_unlock(bp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
xfs_buf_delwri_dequeue(
|
xfs_buf_delwri_dequeue(
|
||||||
xfs_buf_t *bp)
|
xfs_buf_t *bp)
|
||||||
{
|
{
|
||||||
spinlock_t *dwlk = &bp->b_target->bt_delwrite_lock;
|
|
||||||
int dequeued = 0;
|
int dequeued = 0;
|
||||||
|
|
||||||
spin_lock(dwlk);
|
spin_lock(&bp->b_target->bt_delwri_lock);
|
||||||
if ((bp->b_flags & XBF_DELWRI) && !list_empty(&bp->b_list)) {
|
if ((bp->b_flags & XBF_DELWRI) && !list_empty(&bp->b_list)) {
|
||||||
ASSERT(bp->b_flags & _XBF_DELWRI_Q);
|
ASSERT(bp->b_flags & _XBF_DELWRI_Q);
|
||||||
list_del_init(&bp->b_list);
|
list_del_init(&bp->b_list);
|
||||||
dequeued = 1;
|
dequeued = 1;
|
||||||
}
|
}
|
||||||
bp->b_flags &= ~(XBF_DELWRI|_XBF_DELWRI_Q);
|
bp->b_flags &= ~(XBF_DELWRI|_XBF_DELWRI_Q);
|
||||||
spin_unlock(dwlk);
|
spin_unlock(&bp->b_target->bt_delwri_lock);
|
||||||
|
|
||||||
if (dequeued)
|
if (dequeued)
|
||||||
xfs_buf_rele(bp);
|
xfs_buf_rele(bp);
|
||||||
@ -1646,16 +1618,9 @@ xfs_buf_delwri_promote(
|
|||||||
if (bp->b_queuetime < jiffies - age)
|
if (bp->b_queuetime < jiffies - age)
|
||||||
return;
|
return;
|
||||||
bp->b_queuetime = jiffies - age;
|
bp->b_queuetime = jiffies - age;
|
||||||
spin_lock(&btp->bt_delwrite_lock);
|
spin_lock(&btp->bt_delwri_lock);
|
||||||
list_move(&bp->b_list, &btp->bt_delwrite_queue);
|
list_move(&bp->b_list, &btp->bt_delwri_queue);
|
||||||
spin_unlock(&btp->bt_delwrite_lock);
|
spin_unlock(&btp->bt_delwri_lock);
|
||||||
}
|
|
||||||
|
|
||||||
STATIC void
|
|
||||||
xfs_buf_runall_queues(
|
|
||||||
struct workqueue_struct *queue)
|
|
||||||
{
|
|
||||||
flush_workqueue(queue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1669,15 +1634,13 @@ xfs_buf_delwri_split(
|
|||||||
unsigned long age)
|
unsigned long age)
|
||||||
{
|
{
|
||||||
xfs_buf_t *bp, *n;
|
xfs_buf_t *bp, *n;
|
||||||
struct list_head *dwq = &target->bt_delwrite_queue;
|
|
||||||
spinlock_t *dwlk = &target->bt_delwrite_lock;
|
|
||||||
int skipped = 0;
|
int skipped = 0;
|
||||||
int force;
|
int force;
|
||||||
|
|
||||||
force = test_and_clear_bit(XBT_FORCE_FLUSH, &target->bt_flags);
|
force = test_and_clear_bit(XBT_FORCE_FLUSH, &target->bt_flags);
|
||||||
INIT_LIST_HEAD(list);
|
INIT_LIST_HEAD(list);
|
||||||
spin_lock(dwlk);
|
spin_lock(&target->bt_delwri_lock);
|
||||||
list_for_each_entry_safe(bp, n, dwq, b_list) {
|
list_for_each_entry_safe(bp, n, &target->bt_delwri_queue, b_list) {
|
||||||
ASSERT(bp->b_flags & XBF_DELWRI);
|
ASSERT(bp->b_flags & XBF_DELWRI);
|
||||||
|
|
||||||
if (!xfs_buf_ispinned(bp) && xfs_buf_trylock(bp)) {
|
if (!xfs_buf_ispinned(bp) && xfs_buf_trylock(bp)) {
|
||||||
@ -1694,10 +1657,9 @@ xfs_buf_delwri_split(
|
|||||||
} else
|
} else
|
||||||
skipped++;
|
skipped++;
|
||||||
}
|
}
|
||||||
spin_unlock(dwlk);
|
|
||||||
|
|
||||||
|
spin_unlock(&target->bt_delwri_lock);
|
||||||
return skipped;
|
return skipped;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1747,7 +1709,7 @@ xfsbufd(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* sleep for a long time if there is nothing to do. */
|
/* sleep for a long time if there is nothing to do. */
|
||||||
if (list_empty(&target->bt_delwrite_queue))
|
if (list_empty(&target->bt_delwri_queue))
|
||||||
tout = MAX_SCHEDULE_TIMEOUT;
|
tout = MAX_SCHEDULE_TIMEOUT;
|
||||||
schedule_timeout_interruptible(tout);
|
schedule_timeout_interruptible(tout);
|
||||||
|
|
||||||
@ -1783,9 +1745,7 @@ xfs_flush_buftarg(
|
|||||||
LIST_HEAD(wait_list);
|
LIST_HEAD(wait_list);
|
||||||
struct blk_plug plug;
|
struct blk_plug plug;
|
||||||
|
|
||||||
xfs_buf_runall_queues(xfsconvertd_workqueue);
|
flush_workqueue(xfslogd_workqueue);
|
||||||
xfs_buf_runall_queues(xfsdatad_workqueue);
|
|
||||||
xfs_buf_runall_queues(xfslogd_workqueue);
|
|
||||||
|
|
||||||
set_bit(XBT_FORCE_FLUSH, &target->bt_flags);
|
set_bit(XBT_FORCE_FLUSH, &target->bt_flags);
|
||||||
pincount = xfs_buf_delwri_split(target, &tmp_list, 0);
|
pincount = xfs_buf_delwri_split(target, &tmp_list, 0);
|
||||||
@ -1866,11 +1826,3 @@ xfs_buf_terminate(void)
|
|||||||
destroy_workqueue(xfslogd_workqueue);
|
destroy_workqueue(xfslogd_workqueue);
|
||||||
kmem_zone_destroy(xfs_buf_zone);
|
kmem_zone_destroy(xfs_buf_zone);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_KDB_MODULES
|
|
||||||
struct list_head *
|
|
||||||
xfs_get_buftarg_list(void)
|
|
||||||
{
|
|
||||||
return &xfs_buftarg_list;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
@ -105,8 +105,8 @@ typedef struct xfs_buftarg {
|
|||||||
|
|
||||||
/* per device delwri queue */
|
/* per device delwri queue */
|
||||||
struct task_struct *bt_task;
|
struct task_struct *bt_task;
|
||||||
struct list_head bt_delwrite_queue;
|
struct list_head bt_delwri_queue;
|
||||||
spinlock_t bt_delwrite_lock;
|
spinlock_t bt_delwri_lock;
|
||||||
unsigned long bt_flags;
|
unsigned long bt_flags;
|
||||||
|
|
||||||
/* LRU control structures */
|
/* LRU control structures */
|
||||||
@ -175,7 +175,8 @@ extern xfs_buf_t *xfs_buf_get(xfs_buftarg_t *, xfs_off_t, size_t,
|
|||||||
extern xfs_buf_t *xfs_buf_read(xfs_buftarg_t *, xfs_off_t, size_t,
|
extern xfs_buf_t *xfs_buf_read(xfs_buftarg_t *, xfs_off_t, size_t,
|
||||||
xfs_buf_flags_t);
|
xfs_buf_flags_t);
|
||||||
|
|
||||||
extern xfs_buf_t *xfs_buf_get_empty(size_t, xfs_buftarg_t *);
|
struct xfs_buf *xfs_buf_alloc(struct xfs_buftarg *, xfs_off_t, size_t,
|
||||||
|
xfs_buf_flags_t);
|
||||||
extern void xfs_buf_set_empty(struct xfs_buf *bp, size_t len);
|
extern void xfs_buf_set_empty(struct xfs_buf *bp, size_t len);
|
||||||
extern xfs_buf_t *xfs_buf_get_uncached(struct xfs_buftarg *, size_t, int);
|
extern xfs_buf_t *xfs_buf_get_uncached(struct xfs_buftarg *, size_t, int);
|
||||||
extern int xfs_buf_associate_memory(xfs_buf_t *, void *, size_t);
|
extern int xfs_buf_associate_memory(xfs_buf_t *, void *, size_t);
|
||||||
@ -197,14 +198,14 @@ extern void xfs_buf_unlock(xfs_buf_t *);
|
|||||||
((bp)->b_sema.count <= 0)
|
((bp)->b_sema.count <= 0)
|
||||||
|
|
||||||
/* Buffer Read and Write Routines */
|
/* Buffer Read and Write Routines */
|
||||||
extern int xfs_bwrite(struct xfs_mount *mp, struct xfs_buf *bp);
|
extern int xfs_bwrite(struct xfs_buf *bp);
|
||||||
extern void xfs_bdwrite(void *mp, xfs_buf_t *bp);
|
|
||||||
|
|
||||||
extern void xfsbdstrat(struct xfs_mount *, struct xfs_buf *);
|
extern void xfsbdstrat(struct xfs_mount *, struct xfs_buf *);
|
||||||
extern int xfs_bdstrat_cb(struct xfs_buf *);
|
extern int xfs_bdstrat_cb(struct xfs_buf *);
|
||||||
|
|
||||||
extern void xfs_buf_ioend(xfs_buf_t *, int);
|
extern void xfs_buf_ioend(xfs_buf_t *, int);
|
||||||
extern void xfs_buf_ioerror(xfs_buf_t *, int);
|
extern void xfs_buf_ioerror(xfs_buf_t *, int);
|
||||||
|
extern void xfs_buf_ioerror_alert(struct xfs_buf *, const char *func);
|
||||||
extern int xfs_buf_iorequest(xfs_buf_t *);
|
extern int xfs_buf_iorequest(xfs_buf_t *);
|
||||||
extern int xfs_buf_iowait(xfs_buf_t *);
|
extern int xfs_buf_iowait(xfs_buf_t *);
|
||||||
extern void xfs_buf_iomove(xfs_buf_t *, size_t, size_t, void *,
|
extern void xfs_buf_iomove(xfs_buf_t *, size_t, size_t, void *,
|
||||||
@ -221,38 +222,22 @@ static inline int xfs_buf_geterror(xfs_buf_t *bp)
|
|||||||
extern xfs_caddr_t xfs_buf_offset(xfs_buf_t *, size_t);
|
extern xfs_caddr_t xfs_buf_offset(xfs_buf_t *, size_t);
|
||||||
|
|
||||||
/* Delayed Write Buffer Routines */
|
/* Delayed Write Buffer Routines */
|
||||||
extern void xfs_buf_delwri_dequeue(xfs_buf_t *);
|
extern void xfs_buf_delwri_queue(struct xfs_buf *);
|
||||||
extern void xfs_buf_delwri_promote(xfs_buf_t *);
|
extern void xfs_buf_delwri_dequeue(struct xfs_buf *);
|
||||||
|
extern void xfs_buf_delwri_promote(struct xfs_buf *);
|
||||||
|
|
||||||
/* Buffer Daemon Setup Routines */
|
/* Buffer Daemon Setup Routines */
|
||||||
extern int xfs_buf_init(void);
|
extern int xfs_buf_init(void);
|
||||||
extern void xfs_buf_terminate(void);
|
extern void xfs_buf_terminate(void);
|
||||||
|
|
||||||
static inline const char *
|
|
||||||
xfs_buf_target_name(struct xfs_buftarg *target)
|
|
||||||
{
|
|
||||||
static char __b[BDEVNAME_SIZE];
|
|
||||||
|
|
||||||
return bdevname(target->bt_bdev, __b);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define XFS_BUF_ZEROFLAGS(bp) \
|
#define XFS_BUF_ZEROFLAGS(bp) \
|
||||||
((bp)->b_flags &= ~(XBF_READ|XBF_WRITE|XBF_ASYNC|XBF_DELWRI| \
|
((bp)->b_flags &= ~(XBF_READ|XBF_WRITE|XBF_ASYNC|XBF_DELWRI| \
|
||||||
XBF_SYNCIO|XBF_FUA|XBF_FLUSH))
|
XBF_SYNCIO|XBF_FUA|XBF_FLUSH))
|
||||||
|
|
||||||
void xfs_buf_stale(struct xfs_buf *bp);
|
void xfs_buf_stale(struct xfs_buf *bp);
|
||||||
#define XFS_BUF_STALE(bp) xfs_buf_stale(bp);
|
|
||||||
#define XFS_BUF_UNSTALE(bp) ((bp)->b_flags &= ~XBF_STALE)
|
#define XFS_BUF_UNSTALE(bp) ((bp)->b_flags &= ~XBF_STALE)
|
||||||
#define XFS_BUF_ISSTALE(bp) ((bp)->b_flags & XBF_STALE)
|
#define XFS_BUF_ISSTALE(bp) ((bp)->b_flags & XBF_STALE)
|
||||||
#define XFS_BUF_SUPER_STALE(bp) do { \
|
|
||||||
XFS_BUF_STALE(bp); \
|
|
||||||
xfs_buf_delwri_dequeue(bp); \
|
|
||||||
XFS_BUF_DONE(bp); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define XFS_BUF_DELAYWRITE(bp) ((bp)->b_flags |= XBF_DELWRI)
|
|
||||||
#define XFS_BUF_UNDELAYWRITE(bp) xfs_buf_delwri_dequeue(bp)
|
|
||||||
#define XFS_BUF_ISDELAYWRITE(bp) ((bp)->b_flags & XBF_DELWRI)
|
#define XFS_BUF_ISDELAYWRITE(bp) ((bp)->b_flags & XBF_DELWRI)
|
||||||
|
|
||||||
#define XFS_BUF_DONE(bp) ((bp)->b_flags |= XBF_DONE)
|
#define XFS_BUF_DONE(bp) ((bp)->b_flags |= XBF_DONE)
|
||||||
@ -280,23 +265,16 @@ void xfs_buf_stale(struct xfs_buf *bp);
|
|||||||
#define XFS_BUF_SIZE(bp) ((bp)->b_buffer_length)
|
#define XFS_BUF_SIZE(bp) ((bp)->b_buffer_length)
|
||||||
#define XFS_BUF_SET_SIZE(bp, cnt) ((bp)->b_buffer_length = (cnt))
|
#define XFS_BUF_SET_SIZE(bp, cnt) ((bp)->b_buffer_length = (cnt))
|
||||||
|
|
||||||
static inline void
|
static inline void xfs_buf_set_ref(struct xfs_buf *bp, int lru_ref)
|
||||||
xfs_buf_set_ref(
|
|
||||||
struct xfs_buf *bp,
|
|
||||||
int lru_ref)
|
|
||||||
{
|
{
|
||||||
atomic_set(&bp->b_lru_ref, lru_ref);
|
atomic_set(&bp->b_lru_ref, lru_ref);
|
||||||
}
|
}
|
||||||
#define XFS_BUF_SET_VTYPE_REF(bp, type, ref) xfs_buf_set_ref(bp, ref)
|
|
||||||
#define XFS_BUF_SET_VTYPE(bp, type) do { } while (0)
|
|
||||||
|
|
||||||
static inline int xfs_buf_ispinned(struct xfs_buf *bp)
|
static inline int xfs_buf_ispinned(struct xfs_buf *bp)
|
||||||
{
|
{
|
||||||
return atomic_read(&bp->b_pin_count);
|
return atomic_read(&bp->b_pin_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define XFS_BUF_FINISH_IOWAIT(bp) complete(&bp->b_iowait);
|
|
||||||
|
|
||||||
static inline void xfs_buf_relse(xfs_buf_t *bp)
|
static inline void xfs_buf_relse(xfs_buf_t *bp)
|
||||||
{
|
{
|
||||||
xfs_buf_unlock(bp);
|
xfs_buf_unlock(bp);
|
||||||
@ -313,14 +291,7 @@ extern void xfs_wait_buftarg(xfs_buftarg_t *);
|
|||||||
extern int xfs_setsize_buftarg(xfs_buftarg_t *, unsigned int, unsigned int);
|
extern int xfs_setsize_buftarg(xfs_buftarg_t *, unsigned int, unsigned int);
|
||||||
extern int xfs_flush_buftarg(xfs_buftarg_t *, int);
|
extern int xfs_flush_buftarg(xfs_buftarg_t *, int);
|
||||||
|
|
||||||
#ifdef CONFIG_KDB_MODULES
|
|
||||||
extern struct list_head *xfs_get_buftarg_list(void);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define xfs_getsize_buftarg(buftarg) block_size((buftarg)->bt_bdev)
|
#define xfs_getsize_buftarg(buftarg) block_size((buftarg)->bt_bdev)
|
||||||
#define xfs_readonly_buftarg(buftarg) bdev_read_only((buftarg)->bt_bdev)
|
#define xfs_readonly_buftarg(buftarg) bdev_read_only((buftarg)->bt_bdev)
|
||||||
|
|
||||||
#define xfs_binval(buftarg) xfs_flush_buftarg(buftarg, 1)
|
|
||||||
#define XFS_bflush(buftarg) xfs_flush_buftarg(buftarg, 1)
|
|
||||||
|
|
||||||
#endif /* __XFS_BUF_H__ */
|
#endif /* __XFS_BUF_H__ */
|
||||||
|
@ -967,7 +967,8 @@ xfs_buf_iodone_callbacks(
|
|||||||
* I/O errors, there's no point in giving this a retry.
|
* I/O errors, there's no point in giving this a retry.
|
||||||
*/
|
*/
|
||||||
if (XFS_FORCED_SHUTDOWN(mp)) {
|
if (XFS_FORCED_SHUTDOWN(mp)) {
|
||||||
XFS_BUF_SUPER_STALE(bp);
|
xfs_buf_stale(bp);
|
||||||
|
XFS_BUF_DONE(bp);
|
||||||
trace_xfs_buf_item_iodone(bp, _RET_IP_);
|
trace_xfs_buf_item_iodone(bp, _RET_IP_);
|
||||||
goto do_callbacks;
|
goto do_callbacks;
|
||||||
}
|
}
|
||||||
@ -975,9 +976,7 @@ xfs_buf_iodone_callbacks(
|
|||||||
if (bp->b_target != lasttarg ||
|
if (bp->b_target != lasttarg ||
|
||||||
time_after(jiffies, (lasttime + 5*HZ))) {
|
time_after(jiffies, (lasttime + 5*HZ))) {
|
||||||
lasttime = jiffies;
|
lasttime = jiffies;
|
||||||
xfs_alert(mp, "Device %s: metadata write error block 0x%llx",
|
xfs_buf_ioerror_alert(bp, __func__);
|
||||||
xfs_buf_target_name(bp->b_target),
|
|
||||||
(__uint64_t)XFS_BUF_ADDR(bp));
|
|
||||||
}
|
}
|
||||||
lasttarg = bp->b_target;
|
lasttarg = bp->b_target;
|
||||||
|
|
||||||
@ -993,7 +992,7 @@ xfs_buf_iodone_callbacks(
|
|||||||
xfs_buf_ioerror(bp, 0); /* errno of 0 unsets the flag */
|
xfs_buf_ioerror(bp, 0); /* errno of 0 unsets the flag */
|
||||||
|
|
||||||
if (!XFS_BUF_ISSTALE(bp)) {
|
if (!XFS_BUF_ISSTALE(bp)) {
|
||||||
XFS_BUF_DELAYWRITE(bp);
|
xfs_buf_delwri_queue(bp);
|
||||||
XFS_BUF_DONE(bp);
|
XFS_BUF_DONE(bp);
|
||||||
}
|
}
|
||||||
ASSERT(bp->b_iodone != NULL);
|
ASSERT(bp->b_iodone != NULL);
|
||||||
@ -1006,9 +1005,8 @@ xfs_buf_iodone_callbacks(
|
|||||||
* If the write of the buffer was synchronous, we want to make
|
* If the write of the buffer was synchronous, we want to make
|
||||||
* sure to return the error to the caller of xfs_bwrite().
|
* sure to return the error to the caller of xfs_bwrite().
|
||||||
*/
|
*/
|
||||||
XFS_BUF_STALE(bp);
|
xfs_buf_stale(bp);
|
||||||
XFS_BUF_DONE(bp);
|
XFS_BUF_DONE(bp);
|
||||||
XFS_BUF_UNDELAYWRITE(bp);
|
|
||||||
|
|
||||||
trace_xfs_buf_error_relse(bp, _RET_IP_);
|
trace_xfs_buf_error_relse(bp, _RET_IP_);
|
||||||
|
|
||||||
|
@ -1578,9 +1578,8 @@ xfs_da_grow_inode_int(
|
|||||||
*/
|
*/
|
||||||
nmap = 1;
|
nmap = 1;
|
||||||
ASSERT(args->firstblock != NULL);
|
ASSERT(args->firstblock != NULL);
|
||||||
error = xfs_bmapi(tp, dp, *bno, count,
|
error = xfs_bmapi_write(tp, dp, *bno, count,
|
||||||
xfs_bmapi_aflag(w)|XFS_BMAPI_WRITE|XFS_BMAPI_METADATA|
|
xfs_bmapi_aflag(w)|XFS_BMAPI_METADATA|XFS_BMAPI_CONTIG,
|
||||||
XFS_BMAPI_CONTIG,
|
|
||||||
args->firstblock, args->total, &map, &nmap,
|
args->firstblock, args->total, &map, &nmap,
|
||||||
args->flist);
|
args->flist);
|
||||||
if (error)
|
if (error)
|
||||||
@ -1602,9 +1601,8 @@ xfs_da_grow_inode_int(
|
|||||||
for (b = *bno, mapi = 0; b < *bno + count; ) {
|
for (b = *bno, mapi = 0; b < *bno + count; ) {
|
||||||
nmap = MIN(XFS_BMAP_MAX_NMAP, count);
|
nmap = MIN(XFS_BMAP_MAX_NMAP, count);
|
||||||
c = (int)(*bno + count - b);
|
c = (int)(*bno + count - b);
|
||||||
error = xfs_bmapi(tp, dp, b, c,
|
error = xfs_bmapi_write(tp, dp, b, c,
|
||||||
xfs_bmapi_aflag(w)|XFS_BMAPI_WRITE|
|
xfs_bmapi_aflag(w)|XFS_BMAPI_METADATA,
|
||||||
XFS_BMAPI_METADATA,
|
|
||||||
args->firstblock, args->total,
|
args->firstblock, args->total,
|
||||||
&mapp[mapi], &nmap, args->flist);
|
&mapp[mapi], &nmap, args->flist);
|
||||||
if (error)
|
if (error)
|
||||||
@ -1975,33 +1973,16 @@ xfs_da_do_buf(
|
|||||||
/*
|
/*
|
||||||
* Optimize the one-block case.
|
* Optimize the one-block case.
|
||||||
*/
|
*/
|
||||||
if (nfsb == 1) {
|
if (nfsb == 1)
|
||||||
xfs_fsblock_t fsb;
|
|
||||||
|
|
||||||
if ((error =
|
|
||||||
xfs_bmapi_single(trans, dp, whichfork, &fsb,
|
|
||||||
(xfs_fileoff_t)bno))) {
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
mapp = ↦
|
mapp = ↦
|
||||||
if (fsb == NULLFSBLOCK) {
|
else
|
||||||
nmap = 0;
|
|
||||||
} else {
|
|
||||||
map.br_startblock = fsb;
|
|
||||||
map.br_startoff = (xfs_fileoff_t)bno;
|
|
||||||
map.br_blockcount = 1;
|
|
||||||
nmap = 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mapp = kmem_alloc(sizeof(*mapp) * nfsb, KM_SLEEP);
|
mapp = kmem_alloc(sizeof(*mapp) * nfsb, KM_SLEEP);
|
||||||
nmap = nfsb;
|
|
||||||
if ((error = xfs_bmapi(trans, dp, (xfs_fileoff_t)bno,
|
nmap = nfsb;
|
||||||
nfsb,
|
error = xfs_bmapi_read(dp, (xfs_fileoff_t)bno, nfsb, mapp,
|
||||||
XFS_BMAPI_METADATA |
|
&nmap, xfs_bmapi_aflag(whichfork));
|
||||||
xfs_bmapi_aflag(whichfork),
|
if (error)
|
||||||
NULL, 0, mapp, &nmap, NULL)))
|
goto exit0;
|
||||||
goto exit0;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
map.br_startblock = XFS_DADDR_TO_FSB(mp, mappedbno);
|
map.br_startblock = XFS_DADDR_TO_FSB(mp, mappedbno);
|
||||||
map.br_startoff = (xfs_fileoff_t)bno;
|
map.br_startoff = (xfs_fileoff_t)bno;
|
||||||
@ -2072,13 +2053,10 @@ xfs_da_do_buf(
|
|||||||
if (!bp)
|
if (!bp)
|
||||||
continue;
|
continue;
|
||||||
if (caller == 1) {
|
if (caller == 1) {
|
||||||
if (whichfork == XFS_ATTR_FORK) {
|
if (whichfork == XFS_ATTR_FORK)
|
||||||
XFS_BUF_SET_VTYPE_REF(bp, B_FS_ATTR_BTREE,
|
xfs_buf_set_ref(bp, XFS_ATTR_BTREE_REF);
|
||||||
XFS_ATTR_BTREE_REF);
|
else
|
||||||
} else {
|
xfs_buf_set_ref(bp, XFS_DIR_BTREE_REF);
|
||||||
XFS_BUF_SET_VTYPE_REF(bp, B_FS_DIR_BTREE,
|
|
||||||
XFS_DIR_BTREE_REF);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (bplist) {
|
if (bplist) {
|
||||||
bplist[nbplist++] = bp;
|
bplist[nbplist++] = bp;
|
||||||
|
@ -425,8 +425,8 @@ xfs_swap_extents(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
xfs_trans_ijoin_ref(tp, ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
|
xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
|
||||||
xfs_trans_ijoin_ref(tp, tip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
|
xfs_trans_ijoin(tp, tip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
|
||||||
|
|
||||||
xfs_trans_log_inode(tp, ip, ilf_fields);
|
xfs_trans_log_inode(tp, ip, ilf_fields);
|
||||||
xfs_trans_log_inode(tp, tip, tilf_fields);
|
xfs_trans_log_inode(tp, tip, tilf_fields);
|
||||||
@ -438,7 +438,7 @@ xfs_swap_extents(
|
|||||||
if (mp->m_flags & XFS_MOUNT_WSYNC)
|
if (mp->m_flags & XFS_MOUNT_WSYNC)
|
||||||
xfs_trans_set_sync(tp);
|
xfs_trans_set_sync(tp);
|
||||||
|
|
||||||
error = xfs_trans_commit(tp, XFS_TRANS_SWAPEXT);
|
error = xfs_trans_commit(tp, 0);
|
||||||
|
|
||||||
trace_xfs_swap_extent_after(ip, 0);
|
trace_xfs_swap_extent_after(ip, 0);
|
||||||
trace_xfs_swap_extent_after(tip, 1);
|
trace_xfs_swap_extent_after(tip, 1);
|
||||||
|
@ -888,12 +888,10 @@ xfs_dir2_leaf_getdents(
|
|||||||
* we already have in the table.
|
* we already have in the table.
|
||||||
*/
|
*/
|
||||||
nmap = map_size - map_valid;
|
nmap = map_size - map_valid;
|
||||||
error = xfs_bmapi(NULL, dp,
|
error = xfs_bmapi_read(dp, map_off,
|
||||||
map_off,
|
|
||||||
xfs_dir2_byte_to_da(mp,
|
xfs_dir2_byte_to_da(mp,
|
||||||
XFS_DIR2_LEAF_OFFSET) - map_off,
|
XFS_DIR2_LEAF_OFFSET) - map_off,
|
||||||
XFS_BMAPI_METADATA, NULL, 0,
|
&map[map_valid], &nmap, 0);
|
||||||
&map[map_valid], &nmap, NULL);
|
|
||||||
/*
|
/*
|
||||||
* Don't know if we should ignore this or
|
* Don't know if we should ignore this or
|
||||||
* try to return an error.
|
* try to return an error.
|
||||||
|
@ -38,7 +38,7 @@ xfs_trim_extents(
|
|||||||
struct xfs_mount *mp,
|
struct xfs_mount *mp,
|
||||||
xfs_agnumber_t agno,
|
xfs_agnumber_t agno,
|
||||||
xfs_fsblock_t start,
|
xfs_fsblock_t start,
|
||||||
xfs_fsblock_t len,
|
xfs_fsblock_t end,
|
||||||
xfs_fsblock_t minlen,
|
xfs_fsblock_t minlen,
|
||||||
__uint64_t *blocks_trimmed)
|
__uint64_t *blocks_trimmed)
|
||||||
{
|
{
|
||||||
@ -100,7 +100,7 @@ xfs_trim_extents(
|
|||||||
* down partially overlapping ranges for now.
|
* down partially overlapping ranges for now.
|
||||||
*/
|
*/
|
||||||
if (XFS_AGB_TO_FSB(mp, agno, fbno) + flen < start ||
|
if (XFS_AGB_TO_FSB(mp, agno, fbno) + flen < start ||
|
||||||
XFS_AGB_TO_FSB(mp, agno, fbno) >= start + len) {
|
XFS_AGB_TO_FSB(mp, agno, fbno) > end) {
|
||||||
trace_xfs_discard_exclude(mp, agno, fbno, flen);
|
trace_xfs_discard_exclude(mp, agno, fbno, flen);
|
||||||
goto next_extent;
|
goto next_extent;
|
||||||
}
|
}
|
||||||
@ -145,7 +145,7 @@ xfs_ioc_trim(
|
|||||||
struct request_queue *q = mp->m_ddev_targp->bt_bdev->bd_disk->queue;
|
struct request_queue *q = mp->m_ddev_targp->bt_bdev->bd_disk->queue;
|
||||||
unsigned int granularity = q->limits.discard_granularity;
|
unsigned int granularity = q->limits.discard_granularity;
|
||||||
struct fstrim_range range;
|
struct fstrim_range range;
|
||||||
xfs_fsblock_t start, len, minlen;
|
xfs_fsblock_t start, end, minlen;
|
||||||
xfs_agnumber_t start_agno, end_agno, agno;
|
xfs_agnumber_t start_agno, end_agno, agno;
|
||||||
__uint64_t blocks_trimmed = 0;
|
__uint64_t blocks_trimmed = 0;
|
||||||
int error, last_error = 0;
|
int error, last_error = 0;
|
||||||
@ -165,19 +165,19 @@ xfs_ioc_trim(
|
|||||||
* matter as trimming blocks is an advisory interface.
|
* matter as trimming blocks is an advisory interface.
|
||||||
*/
|
*/
|
||||||
start = XFS_B_TO_FSBT(mp, range.start);
|
start = XFS_B_TO_FSBT(mp, range.start);
|
||||||
len = XFS_B_TO_FSBT(mp, range.len);
|
end = start + XFS_B_TO_FSBT(mp, range.len) - 1;
|
||||||
minlen = XFS_B_TO_FSB(mp, max_t(u64, granularity, range.minlen));
|
minlen = XFS_B_TO_FSB(mp, max_t(u64, granularity, range.minlen));
|
||||||
|
|
||||||
start_agno = XFS_FSB_TO_AGNO(mp, start);
|
if (start >= mp->m_sb.sb_dblocks)
|
||||||
if (start_agno >= mp->m_sb.sb_agcount)
|
|
||||||
return -XFS_ERROR(EINVAL);
|
return -XFS_ERROR(EINVAL);
|
||||||
|
if (end > mp->m_sb.sb_dblocks - 1)
|
||||||
|
end = mp->m_sb.sb_dblocks - 1;
|
||||||
|
|
||||||
end_agno = XFS_FSB_TO_AGNO(mp, start + len);
|
start_agno = XFS_FSB_TO_AGNO(mp, start);
|
||||||
if (end_agno >= mp->m_sb.sb_agcount)
|
end_agno = XFS_FSB_TO_AGNO(mp, end);
|
||||||
end_agno = mp->m_sb.sb_agcount - 1;
|
|
||||||
|
|
||||||
for (agno = start_agno; agno <= end_agno; agno++) {
|
for (agno = start_agno; agno <= end_agno; agno++) {
|
||||||
error = -xfs_trim_extents(mp, agno, start, len, minlen,
|
error = -xfs_trim_extents(mp, agno, start, end, minlen,
|
||||||
&blocks_trimmed);
|
&blocks_trimmed);
|
||||||
if (error)
|
if (error)
|
||||||
last_error = error;
|
last_error = error;
|
||||||
|
@ -377,16 +377,14 @@ xfs_qm_dqalloc(
|
|||||||
return (ESRCH);
|
return (ESRCH);
|
||||||
}
|
}
|
||||||
|
|
||||||
xfs_trans_ijoin_ref(tp, quotip, XFS_ILOCK_EXCL);
|
xfs_trans_ijoin(tp, quotip, XFS_ILOCK_EXCL);
|
||||||
nmaps = 1;
|
nmaps = 1;
|
||||||
if ((error = xfs_bmapi(tp, quotip,
|
error = xfs_bmapi_write(tp, quotip, offset_fsb,
|
||||||
offset_fsb, XFS_DQUOT_CLUSTER_SIZE_FSB,
|
XFS_DQUOT_CLUSTER_SIZE_FSB, XFS_BMAPI_METADATA,
|
||||||
XFS_BMAPI_METADATA | XFS_BMAPI_WRITE,
|
&firstblock, XFS_QM_DQALLOC_SPACE_RES(mp),
|
||||||
&firstblock,
|
&map, &nmaps, &flist);
|
||||||
XFS_QM_DQALLOC_SPACE_RES(mp),
|
if (error)
|
||||||
&map, &nmaps, &flist))) {
|
|
||||||
goto error0;
|
goto error0;
|
||||||
}
|
|
||||||
ASSERT(map.br_blockcount == XFS_DQUOT_CLUSTER_SIZE_FSB);
|
ASSERT(map.br_blockcount == XFS_DQUOT_CLUSTER_SIZE_FSB);
|
||||||
ASSERT(nmaps == 1);
|
ASSERT(nmaps == 1);
|
||||||
ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
|
ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
|
||||||
@ -402,8 +400,11 @@ xfs_qm_dqalloc(
|
|||||||
dqp->q_blkno,
|
dqp->q_blkno,
|
||||||
mp->m_quotainfo->qi_dqchunklen,
|
mp->m_quotainfo->qi_dqchunklen,
|
||||||
0);
|
0);
|
||||||
if (!bp || (error = xfs_buf_geterror(bp)))
|
|
||||||
|
error = xfs_buf_geterror(bp);
|
||||||
|
if (error)
|
||||||
goto error1;
|
goto error1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make a chunk of dquots out of this buffer and log
|
* Make a chunk of dquots out of this buffer and log
|
||||||
* the entire thing.
|
* the entire thing.
|
||||||
@ -485,9 +486,8 @@ xfs_qm_dqtobp(
|
|||||||
/*
|
/*
|
||||||
* Find the block map; no allocations yet
|
* Find the block map; no allocations yet
|
||||||
*/
|
*/
|
||||||
error = xfs_bmapi(NULL, quotip, dqp->q_fileoffset,
|
error = xfs_bmapi_read(quotip, dqp->q_fileoffset,
|
||||||
XFS_DQUOT_CLUSTER_SIZE_FSB, XFS_BMAPI_METADATA,
|
XFS_DQUOT_CLUSTER_SIZE_FSB, &map, &nmaps, 0);
|
||||||
NULL, 0, &map, &nmaps, NULL);
|
|
||||||
|
|
||||||
xfs_iunlock(quotip, XFS_ILOCK_SHARED);
|
xfs_iunlock(quotip, XFS_ILOCK_SHARED);
|
||||||
if (error)
|
if (error)
|
||||||
@ -605,7 +605,7 @@ xfs_qm_dqread(
|
|||||||
dqp->q_res_rtbcount = be64_to_cpu(ddqp->d_rtbcount);
|
dqp->q_res_rtbcount = be64_to_cpu(ddqp->d_rtbcount);
|
||||||
|
|
||||||
/* Mark the buf so that this will stay incore a little longer */
|
/* Mark the buf so that this will stay incore a little longer */
|
||||||
XFS_BUF_SET_VTYPE_REF(bp, B_FS_DQUOT, XFS_DQUOT_REF);
|
xfs_buf_set_ref(bp, XFS_DQUOT_REF);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We got the buffer with a xfs_trans_read_buf() (in dqtobp())
|
* We got the buffer with a xfs_trans_read_buf() (in dqtobp())
|
||||||
@ -1242,9 +1242,11 @@ xfs_qm_dqflush(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (flags & SYNC_WAIT)
|
if (flags & SYNC_WAIT)
|
||||||
error = xfs_bwrite(mp, bp);
|
error = xfs_bwrite(bp);
|
||||||
else
|
else
|
||||||
xfs_bdwrite(mp, bp);
|
xfs_buf_delwri_queue(bp);
|
||||||
|
|
||||||
|
xfs_buf_relse(bp);
|
||||||
|
|
||||||
trace_xfs_dqflush_done(dqp);
|
trace_xfs_dqflush_done(dqp);
|
||||||
|
|
||||||
|
@ -229,16 +229,16 @@ xfs_fs_nfs_commit_metadata(
|
|||||||
{
|
{
|
||||||
struct xfs_inode *ip = XFS_I(inode);
|
struct xfs_inode *ip = XFS_I(inode);
|
||||||
struct xfs_mount *mp = ip->i_mount;
|
struct xfs_mount *mp = ip->i_mount;
|
||||||
int error = 0;
|
xfs_lsn_t lsn = 0;
|
||||||
|
|
||||||
xfs_ilock(ip, XFS_ILOCK_SHARED);
|
xfs_ilock(ip, XFS_ILOCK_SHARED);
|
||||||
if (xfs_ipincount(ip)) {
|
if (xfs_ipincount(ip))
|
||||||
error = _xfs_log_force_lsn(mp, ip->i_itemp->ili_last_lsn,
|
lsn = ip->i_itemp->ili_last_lsn;
|
||||||
XFS_LOG_SYNC, NULL);
|
|
||||||
}
|
|
||||||
xfs_iunlock(ip, XFS_ILOCK_SHARED);
|
xfs_iunlock(ip, XFS_ILOCK_SHARED);
|
||||||
|
|
||||||
return error;
|
if (!lsn)
|
||||||
|
return 0;
|
||||||
|
return _xfs_log_force_lsn(mp, lsn, XFS_LOG_SYNC, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct export_operations xfs_export_operations = {
|
const struct export_operations xfs_export_operations = {
|
||||||
|
@ -124,6 +124,35 @@ xfs_iozero(
|
|||||||
return (-status);
|
return (-status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fsync operations on directories are much simpler than on regular files,
|
||||||
|
* as there is no file data to flush, and thus also no need for explicit
|
||||||
|
* cache flush operations, and there are no non-transaction metadata updates
|
||||||
|
* on directories either.
|
||||||
|
*/
|
||||||
|
STATIC int
|
||||||
|
xfs_dir_fsync(
|
||||||
|
struct file *file,
|
||||||
|
loff_t start,
|
||||||
|
loff_t end,
|
||||||
|
int datasync)
|
||||||
|
{
|
||||||
|
struct xfs_inode *ip = XFS_I(file->f_mapping->host);
|
||||||
|
struct xfs_mount *mp = ip->i_mount;
|
||||||
|
xfs_lsn_t lsn = 0;
|
||||||
|
|
||||||
|
trace_xfs_dir_fsync(ip);
|
||||||
|
|
||||||
|
xfs_ilock(ip, XFS_ILOCK_SHARED);
|
||||||
|
if (xfs_ipincount(ip))
|
||||||
|
lsn = ip->i_itemp->ili_last_lsn;
|
||||||
|
xfs_iunlock(ip, XFS_ILOCK_SHARED);
|
||||||
|
|
||||||
|
if (!lsn)
|
||||||
|
return 0;
|
||||||
|
return _xfs_log_force_lsn(mp, lsn, XFS_LOG_SYNC, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
STATIC int
|
STATIC int
|
||||||
xfs_file_fsync(
|
xfs_file_fsync(
|
||||||
struct file *file,
|
struct file *file,
|
||||||
@ -137,6 +166,7 @@ xfs_file_fsync(
|
|||||||
struct xfs_trans *tp;
|
struct xfs_trans *tp;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
int log_flushed = 0;
|
int log_flushed = 0;
|
||||||
|
xfs_lsn_t lsn = 0;
|
||||||
|
|
||||||
trace_xfs_file_fsync(ip);
|
trace_xfs_file_fsync(ip);
|
||||||
|
|
||||||
@ -149,10 +179,6 @@ xfs_file_fsync(
|
|||||||
|
|
||||||
xfs_iflags_clear(ip, XFS_ITRUNCATED);
|
xfs_iflags_clear(ip, XFS_ITRUNCATED);
|
||||||
|
|
||||||
xfs_ilock(ip, XFS_IOLOCK_SHARED);
|
|
||||||
xfs_ioend_wait(ip);
|
|
||||||
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
|
|
||||||
|
|
||||||
if (mp->m_flags & XFS_MOUNT_BARRIER) {
|
if (mp->m_flags & XFS_MOUNT_BARRIER) {
|
||||||
/*
|
/*
|
||||||
* If we have an RT and/or log subvolume we need to make sure
|
* If we have an RT and/or log subvolume we need to make sure
|
||||||
@ -216,11 +242,11 @@ xfs_file_fsync(
|
|||||||
* transaction. So we play it safe and fire off the
|
* transaction. So we play it safe and fire off the
|
||||||
* transaction anyway.
|
* transaction anyway.
|
||||||
*/
|
*/
|
||||||
xfs_trans_ijoin(tp, ip);
|
xfs_trans_ijoin(tp, ip, 0);
|
||||||
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
|
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
|
||||||
xfs_trans_set_sync(tp);
|
error = xfs_trans_commit(tp, 0);
|
||||||
error = _xfs_trans_commit(tp, 0, &log_flushed);
|
|
||||||
|
|
||||||
|
lsn = ip->i_itemp->ili_last_lsn;
|
||||||
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
@ -231,14 +257,14 @@ xfs_file_fsync(
|
|||||||
* disk yet, the inode will be still be pinned. If it is,
|
* disk yet, the inode will be still be pinned. If it is,
|
||||||
* force the log.
|
* force the log.
|
||||||
*/
|
*/
|
||||||
if (xfs_ipincount(ip)) {
|
if (xfs_ipincount(ip))
|
||||||
error = _xfs_log_force_lsn(mp,
|
lsn = ip->i_itemp->ili_last_lsn;
|
||||||
ip->i_itemp->ili_last_lsn,
|
|
||||||
XFS_LOG_SYNC, &log_flushed);
|
|
||||||
}
|
|
||||||
xfs_iunlock(ip, XFS_ILOCK_SHARED);
|
xfs_iunlock(ip, XFS_ILOCK_SHARED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!error && lsn)
|
||||||
|
error = _xfs_log_force_lsn(mp, lsn, XFS_LOG_SYNC, &log_flushed);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we only have a single device, and the log force about was
|
* If we only have a single device, and the log force about was
|
||||||
* a no-op we might have to flush the data device cache here.
|
* a no-op we might have to flush the data device cache here.
|
||||||
@ -317,7 +343,19 @@ xfs_file_aio_read(
|
|||||||
if (XFS_FORCED_SHUTDOWN(mp))
|
if (XFS_FORCED_SHUTDOWN(mp))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
if (unlikely(ioflags & IO_ISDIRECT)) {
|
/*
|
||||||
|
* Locking is a bit tricky here. If we take an exclusive lock
|
||||||
|
* for direct IO, we effectively serialise all new concurrent
|
||||||
|
* read IO to this file and block it behind IO that is currently in
|
||||||
|
* progress because IO in progress holds the IO lock shared. We only
|
||||||
|
* need to hold the lock exclusive to blow away the page cache, so
|
||||||
|
* only take lock exclusively if the page cache needs invalidation.
|
||||||
|
* This allows the normal direct IO case of no page cache pages to
|
||||||
|
* proceeed concurrently without serialisation.
|
||||||
|
*/
|
||||||
|
xfs_rw_ilock(ip, XFS_IOLOCK_SHARED);
|
||||||
|
if ((ioflags & IO_ISDIRECT) && inode->i_mapping->nrpages) {
|
||||||
|
xfs_rw_iunlock(ip, XFS_IOLOCK_SHARED);
|
||||||
xfs_rw_ilock(ip, XFS_IOLOCK_EXCL);
|
xfs_rw_ilock(ip, XFS_IOLOCK_EXCL);
|
||||||
|
|
||||||
if (inode->i_mapping->nrpages) {
|
if (inode->i_mapping->nrpages) {
|
||||||
@ -330,8 +368,7 @@ xfs_file_aio_read(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
xfs_rw_ilock_demote(ip, XFS_IOLOCK_EXCL);
|
xfs_rw_ilock_demote(ip, XFS_IOLOCK_EXCL);
|
||||||
} else
|
}
|
||||||
xfs_rw_ilock(ip, XFS_IOLOCK_SHARED);
|
|
||||||
|
|
||||||
trace_xfs_file_read(ip, size, iocb->ki_pos, ioflags);
|
trace_xfs_file_read(ip, size, iocb->ki_pos, ioflags);
|
||||||
|
|
||||||
@ -407,11 +444,13 @@ xfs_aio_write_isize_update(
|
|||||||
*/
|
*/
|
||||||
STATIC void
|
STATIC void
|
||||||
xfs_aio_write_newsize_update(
|
xfs_aio_write_newsize_update(
|
||||||
struct xfs_inode *ip)
|
struct xfs_inode *ip,
|
||||||
|
xfs_fsize_t new_size)
|
||||||
{
|
{
|
||||||
if (ip->i_new_size) {
|
if (new_size == ip->i_new_size) {
|
||||||
xfs_rw_ilock(ip, XFS_ILOCK_EXCL);
|
xfs_rw_ilock(ip, XFS_ILOCK_EXCL);
|
||||||
ip->i_new_size = 0;
|
if (new_size == ip->i_new_size)
|
||||||
|
ip->i_new_size = 0;
|
||||||
if (ip->i_d.di_size > ip->i_size)
|
if (ip->i_d.di_size > ip->i_size)
|
||||||
ip->i_d.di_size = ip->i_size;
|
ip->i_d.di_size = ip->i_size;
|
||||||
xfs_rw_iunlock(ip, XFS_ILOCK_EXCL);
|
xfs_rw_iunlock(ip, XFS_ILOCK_EXCL);
|
||||||
@ -462,7 +501,7 @@ xfs_file_splice_write(
|
|||||||
ret = generic_file_splice_write(pipe, outfilp, ppos, count, flags);
|
ret = generic_file_splice_write(pipe, outfilp, ppos, count, flags);
|
||||||
|
|
||||||
xfs_aio_write_isize_update(inode, ppos, ret);
|
xfs_aio_write_isize_update(inode, ppos, ret);
|
||||||
xfs_aio_write_newsize_update(ip);
|
xfs_aio_write_newsize_update(ip, new_size);
|
||||||
xfs_iunlock(ip, XFS_IOLOCK_EXCL);
|
xfs_iunlock(ip, XFS_IOLOCK_EXCL);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -500,11 +539,9 @@ xfs_zero_last_block(
|
|||||||
|
|
||||||
last_fsb = XFS_B_TO_FSBT(mp, isize);
|
last_fsb = XFS_B_TO_FSBT(mp, isize);
|
||||||
nimaps = 1;
|
nimaps = 1;
|
||||||
error = xfs_bmapi(NULL, ip, last_fsb, 1, 0, NULL, 0, &imap,
|
error = xfs_bmapi_read(ip, last_fsb, 1, &imap, &nimaps, 0);
|
||||||
&nimaps, NULL);
|
if (error)
|
||||||
if (error) {
|
|
||||||
return error;
|
return error;
|
||||||
}
|
|
||||||
ASSERT(nimaps > 0);
|
ASSERT(nimaps > 0);
|
||||||
/*
|
/*
|
||||||
* If the block underlying isize is just a hole, then there
|
* If the block underlying isize is just a hole, then there
|
||||||
@ -595,8 +632,8 @@ xfs_zero_eof(
|
|||||||
while (start_zero_fsb <= end_zero_fsb) {
|
while (start_zero_fsb <= end_zero_fsb) {
|
||||||
nimaps = 1;
|
nimaps = 1;
|
||||||
zero_count_fsb = end_zero_fsb - start_zero_fsb + 1;
|
zero_count_fsb = end_zero_fsb - start_zero_fsb + 1;
|
||||||
error = xfs_bmapi(NULL, ip, start_zero_fsb, zero_count_fsb,
|
error = xfs_bmapi_read(ip, start_zero_fsb, zero_count_fsb,
|
||||||
0, NULL, 0, &imap, &nimaps, NULL);
|
&imap, &nimaps, 0);
|
||||||
if (error) {
|
if (error) {
|
||||||
ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_IOLOCK_EXCL));
|
ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_IOLOCK_EXCL));
|
||||||
return error;
|
return error;
|
||||||
@ -659,6 +696,7 @@ xfs_file_aio_write_checks(
|
|||||||
struct file *file,
|
struct file *file,
|
||||||
loff_t *pos,
|
loff_t *pos,
|
||||||
size_t *count,
|
size_t *count,
|
||||||
|
xfs_fsize_t *new_sizep,
|
||||||
int *iolock)
|
int *iolock)
|
||||||
{
|
{
|
||||||
struct inode *inode = file->f_mapping->host;
|
struct inode *inode = file->f_mapping->host;
|
||||||
@ -666,6 +704,9 @@ xfs_file_aio_write_checks(
|
|||||||
xfs_fsize_t new_size;
|
xfs_fsize_t new_size;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
|
xfs_rw_ilock(ip, XFS_ILOCK_EXCL);
|
||||||
|
*new_sizep = 0;
|
||||||
|
restart:
|
||||||
error = generic_write_checks(file, pos, count, S_ISBLK(inode->i_mode));
|
error = generic_write_checks(file, pos, count, S_ISBLK(inode->i_mode));
|
||||||
if (error) {
|
if (error) {
|
||||||
xfs_rw_iunlock(ip, XFS_ILOCK_EXCL | *iolock);
|
xfs_rw_iunlock(ip, XFS_ILOCK_EXCL | *iolock);
|
||||||
@ -673,20 +714,41 @@ xfs_file_aio_write_checks(
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
new_size = *pos + *count;
|
|
||||||
if (new_size > ip->i_size)
|
|
||||||
ip->i_new_size = new_size;
|
|
||||||
|
|
||||||
if (likely(!(file->f_mode & FMODE_NOCMTIME)))
|
if (likely(!(file->f_mode & FMODE_NOCMTIME)))
|
||||||
file_update_time(file);
|
file_update_time(file);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the offset is beyond the size of the file, we need to zero any
|
* If the offset is beyond the size of the file, we need to zero any
|
||||||
* blocks that fall between the existing EOF and the start of this
|
* blocks that fall between the existing EOF and the start of this
|
||||||
* write.
|
* write. There is no need to issue zeroing if another in-flght IO ends
|
||||||
|
* at or before this one If zeronig is needed and we are currently
|
||||||
|
* holding the iolock shared, we need to update it to exclusive which
|
||||||
|
* involves dropping all locks and relocking to maintain correct locking
|
||||||
|
* order. If we do this, restart the function to ensure all checks and
|
||||||
|
* values are still valid.
|
||||||
*/
|
*/
|
||||||
if (*pos > ip->i_size)
|
if ((ip->i_new_size && *pos > ip->i_new_size) ||
|
||||||
|
(!ip->i_new_size && *pos > ip->i_size)) {
|
||||||
|
if (*iolock == XFS_IOLOCK_SHARED) {
|
||||||
|
xfs_rw_iunlock(ip, XFS_ILOCK_EXCL | *iolock);
|
||||||
|
*iolock = XFS_IOLOCK_EXCL;
|
||||||
|
xfs_rw_ilock(ip, XFS_ILOCK_EXCL | *iolock);
|
||||||
|
goto restart;
|
||||||
|
}
|
||||||
error = -xfs_zero_eof(ip, *pos, ip->i_size);
|
error = -xfs_zero_eof(ip, *pos, ip->i_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If this IO extends beyond EOF, we may need to update ip->i_new_size.
|
||||||
|
* We have already zeroed space beyond EOF (if necessary). Only update
|
||||||
|
* ip->i_new_size if this IO ends beyond any other in-flight writes.
|
||||||
|
*/
|
||||||
|
new_size = *pos + *count;
|
||||||
|
if (new_size > ip->i_size) {
|
||||||
|
if (new_size > ip->i_new_size)
|
||||||
|
ip->i_new_size = new_size;
|
||||||
|
*new_sizep = new_size;
|
||||||
|
}
|
||||||
|
|
||||||
xfs_rw_iunlock(ip, XFS_ILOCK_EXCL);
|
xfs_rw_iunlock(ip, XFS_ILOCK_EXCL);
|
||||||
if (error)
|
if (error)
|
||||||
@ -721,7 +783,7 @@ xfs_file_aio_write_checks(
|
|||||||
* the dio layer. To avoid the problem with aio, we also need to wait for
|
* the dio layer. To avoid the problem with aio, we also need to wait for
|
||||||
* outstanding IOs to complete so that unwritten extent conversion is completed
|
* outstanding IOs to complete so that unwritten extent conversion is completed
|
||||||
* before we try to map the overlapping block. This is currently implemented by
|
* before we try to map the overlapping block. This is currently implemented by
|
||||||
* hitting it with a big hammer (i.e. xfs_ioend_wait()).
|
* hitting it with a big hammer (i.e. inode_dio_wait()).
|
||||||
*
|
*
|
||||||
* Returns with locks held indicated by @iolock and errors indicated by
|
* Returns with locks held indicated by @iolock and errors indicated by
|
||||||
* negative return values.
|
* negative return values.
|
||||||
@ -733,6 +795,7 @@ xfs_file_dio_aio_write(
|
|||||||
unsigned long nr_segs,
|
unsigned long nr_segs,
|
||||||
loff_t pos,
|
loff_t pos,
|
||||||
size_t ocount,
|
size_t ocount,
|
||||||
|
xfs_fsize_t *new_size,
|
||||||
int *iolock)
|
int *iolock)
|
||||||
{
|
{
|
||||||
struct file *file = iocb->ki_filp;
|
struct file *file = iocb->ki_filp;
|
||||||
@ -753,18 +816,35 @@ xfs_file_dio_aio_write(
|
|||||||
if ((pos & mp->m_blockmask) || ((pos + count) & mp->m_blockmask))
|
if ((pos & mp->m_blockmask) || ((pos + count) & mp->m_blockmask))
|
||||||
unaligned_io = 1;
|
unaligned_io = 1;
|
||||||
|
|
||||||
if (unaligned_io || mapping->nrpages || pos > ip->i_size)
|
/*
|
||||||
|
* We don't need to take an exclusive lock unless there page cache needs
|
||||||
|
* to be invalidated or unaligned IO is being executed. We don't need to
|
||||||
|
* consider the EOF extension case here because
|
||||||
|
* xfs_file_aio_write_checks() will relock the inode as necessary for
|
||||||
|
* EOF zeroing cases and fill out the new inode size as appropriate.
|
||||||
|
*/
|
||||||
|
if (unaligned_io || mapping->nrpages)
|
||||||
*iolock = XFS_IOLOCK_EXCL;
|
*iolock = XFS_IOLOCK_EXCL;
|
||||||
else
|
else
|
||||||
*iolock = XFS_IOLOCK_SHARED;
|
*iolock = XFS_IOLOCK_SHARED;
|
||||||
xfs_rw_ilock(ip, XFS_ILOCK_EXCL | *iolock);
|
xfs_rw_ilock(ip, *iolock);
|
||||||
|
|
||||||
ret = xfs_file_aio_write_checks(file, &pos, &count, iolock);
|
/*
|
||||||
|
* Recheck if there are cached pages that need invalidate after we got
|
||||||
|
* the iolock to protect against other threads adding new pages while
|
||||||
|
* we were waiting for the iolock.
|
||||||
|
*/
|
||||||
|
if (mapping->nrpages && *iolock == XFS_IOLOCK_SHARED) {
|
||||||
|
xfs_rw_iunlock(ip, *iolock);
|
||||||
|
*iolock = XFS_IOLOCK_EXCL;
|
||||||
|
xfs_rw_ilock(ip, *iolock);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = xfs_file_aio_write_checks(file, &pos, &count, new_size, iolock);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (mapping->nrpages) {
|
if (mapping->nrpages) {
|
||||||
WARN_ON(*iolock != XFS_IOLOCK_EXCL);
|
|
||||||
ret = -xfs_flushinval_pages(ip, (pos & PAGE_CACHE_MASK), -1,
|
ret = -xfs_flushinval_pages(ip, (pos & PAGE_CACHE_MASK), -1,
|
||||||
FI_REMAPF_LOCKED);
|
FI_REMAPF_LOCKED);
|
||||||
if (ret)
|
if (ret)
|
||||||
@ -776,7 +856,7 @@ xfs_file_dio_aio_write(
|
|||||||
* otherwise demote the lock if we had to flush cached pages
|
* otherwise demote the lock if we had to flush cached pages
|
||||||
*/
|
*/
|
||||||
if (unaligned_io)
|
if (unaligned_io)
|
||||||
xfs_ioend_wait(ip);
|
inode_dio_wait(inode);
|
||||||
else if (*iolock == XFS_IOLOCK_EXCL) {
|
else if (*iolock == XFS_IOLOCK_EXCL) {
|
||||||
xfs_rw_ilock_demote(ip, XFS_IOLOCK_EXCL);
|
xfs_rw_ilock_demote(ip, XFS_IOLOCK_EXCL);
|
||||||
*iolock = XFS_IOLOCK_SHARED;
|
*iolock = XFS_IOLOCK_SHARED;
|
||||||
@ -798,6 +878,7 @@ xfs_file_buffered_aio_write(
|
|||||||
unsigned long nr_segs,
|
unsigned long nr_segs,
|
||||||
loff_t pos,
|
loff_t pos,
|
||||||
size_t ocount,
|
size_t ocount,
|
||||||
|
xfs_fsize_t *new_size,
|
||||||
int *iolock)
|
int *iolock)
|
||||||
{
|
{
|
||||||
struct file *file = iocb->ki_filp;
|
struct file *file = iocb->ki_filp;
|
||||||
@ -809,9 +890,9 @@ xfs_file_buffered_aio_write(
|
|||||||
size_t count = ocount;
|
size_t count = ocount;
|
||||||
|
|
||||||
*iolock = XFS_IOLOCK_EXCL;
|
*iolock = XFS_IOLOCK_EXCL;
|
||||||
xfs_rw_ilock(ip, XFS_ILOCK_EXCL | *iolock);
|
xfs_rw_ilock(ip, *iolock);
|
||||||
|
|
||||||
ret = xfs_file_aio_write_checks(file, &pos, &count, iolock);
|
ret = xfs_file_aio_write_checks(file, &pos, &count, new_size, iolock);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -851,6 +932,7 @@ xfs_file_aio_write(
|
|||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
int iolock;
|
int iolock;
|
||||||
size_t ocount = 0;
|
size_t ocount = 0;
|
||||||
|
xfs_fsize_t new_size = 0;
|
||||||
|
|
||||||
XFS_STATS_INC(xs_write_calls);
|
XFS_STATS_INC(xs_write_calls);
|
||||||
|
|
||||||
@ -870,10 +952,10 @@ xfs_file_aio_write(
|
|||||||
|
|
||||||
if (unlikely(file->f_flags & O_DIRECT))
|
if (unlikely(file->f_flags & O_DIRECT))
|
||||||
ret = xfs_file_dio_aio_write(iocb, iovp, nr_segs, pos,
|
ret = xfs_file_dio_aio_write(iocb, iovp, nr_segs, pos,
|
||||||
ocount, &iolock);
|
ocount, &new_size, &iolock);
|
||||||
else
|
else
|
||||||
ret = xfs_file_buffered_aio_write(iocb, iovp, nr_segs, pos,
|
ret = xfs_file_buffered_aio_write(iocb, iovp, nr_segs, pos,
|
||||||
ocount, &iolock);
|
ocount, &new_size, &iolock);
|
||||||
|
|
||||||
xfs_aio_write_isize_update(inode, &iocb->ki_pos, ret);
|
xfs_aio_write_isize_update(inode, &iocb->ki_pos, ret);
|
||||||
|
|
||||||
@ -894,7 +976,7 @@ xfs_file_aio_write(
|
|||||||
}
|
}
|
||||||
|
|
||||||
out_unlock:
|
out_unlock:
|
||||||
xfs_aio_write_newsize_update(ip);
|
xfs_aio_write_newsize_update(ip, new_size);
|
||||||
xfs_rw_iunlock(ip, iolock);
|
xfs_rw_iunlock(ip, iolock);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -1087,7 +1169,7 @@ const struct file_operations xfs_dir_file_operations = {
|
|||||||
#ifdef CONFIG_COMPAT
|
#ifdef CONFIG_COMPAT
|
||||||
.compat_ioctl = xfs_file_compat_ioctl,
|
.compat_ioctl = xfs_file_compat_ioctl,
|
||||||
#endif
|
#endif
|
||||||
.fsync = xfs_file_fsync,
|
.fsync = xfs_dir_fsync,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct vm_operations_struct xfs_file_vm_ops = {
|
static const struct vm_operations_struct xfs_file_vm_ops = {
|
||||||
|
@ -682,7 +682,7 @@ xfs_filestream_new_ag(
|
|||||||
ip = ap->ip;
|
ip = ap->ip;
|
||||||
mp = ip->i_mount;
|
mp = ip->i_mount;
|
||||||
cache = mp->m_filestream;
|
cache = mp->m_filestream;
|
||||||
minlen = ap->alen;
|
minlen = ap->length;
|
||||||
*agp = NULLAGNUMBER;
|
*agp = NULLAGNUMBER;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -761,7 +761,7 @@ xfs_filestream_new_ag(
|
|||||||
*/
|
*/
|
||||||
ag = (ag == NULLAGNUMBER) ? 0 : (ag + 1) % mp->m_sb.sb_agcount;
|
ag = (ag == NULLAGNUMBER) ? 0 : (ag + 1) % mp->m_sb.sb_agcount;
|
||||||
flags = (ap->userdata ? XFS_PICK_USERDATA : 0) |
|
flags = (ap->userdata ? XFS_PICK_USERDATA : 0) |
|
||||||
(ap->low ? XFS_PICK_LOWSPACE : 0);
|
(ap->flist->xbf_low ? XFS_PICK_LOWSPACE : 0);
|
||||||
|
|
||||||
err = _xfs_filestream_pick_ag(mp, ag, agp, flags, minlen);
|
err = _xfs_filestream_pick_ag(mp, ag, agp, flags, minlen);
|
||||||
if (err || *agp == NULLAGNUMBER)
|
if (err || *agp == NULLAGNUMBER)
|
||||||
|
@ -194,6 +194,10 @@ xfs_growfs_data_private(
|
|||||||
bp = xfs_buf_get(mp->m_ddev_targp,
|
bp = xfs_buf_get(mp->m_ddev_targp,
|
||||||
XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)),
|
XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)),
|
||||||
XFS_FSS_TO_BB(mp, 1), XBF_LOCK | XBF_MAPPED);
|
XFS_FSS_TO_BB(mp, 1), XBF_LOCK | XBF_MAPPED);
|
||||||
|
if (!bp) {
|
||||||
|
error = ENOMEM;
|
||||||
|
goto error0;
|
||||||
|
}
|
||||||
agf = XFS_BUF_TO_AGF(bp);
|
agf = XFS_BUF_TO_AGF(bp);
|
||||||
memset(agf, 0, mp->m_sb.sb_sectsize);
|
memset(agf, 0, mp->m_sb.sb_sectsize);
|
||||||
agf->agf_magicnum = cpu_to_be32(XFS_AGF_MAGIC);
|
agf->agf_magicnum = cpu_to_be32(XFS_AGF_MAGIC);
|
||||||
@ -216,16 +220,21 @@ xfs_growfs_data_private(
|
|||||||
tmpsize = agsize - XFS_PREALLOC_BLOCKS(mp);
|
tmpsize = agsize - XFS_PREALLOC_BLOCKS(mp);
|
||||||
agf->agf_freeblks = cpu_to_be32(tmpsize);
|
agf->agf_freeblks = cpu_to_be32(tmpsize);
|
||||||
agf->agf_longest = cpu_to_be32(tmpsize);
|
agf->agf_longest = cpu_to_be32(tmpsize);
|
||||||
error = xfs_bwrite(mp, bp);
|
error = xfs_bwrite(bp);
|
||||||
if (error) {
|
xfs_buf_relse(bp);
|
||||||
|
if (error)
|
||||||
goto error0;
|
goto error0;
|
||||||
}
|
|
||||||
/*
|
/*
|
||||||
* AG inode header block
|
* AG inode header block
|
||||||
*/
|
*/
|
||||||
bp = xfs_buf_get(mp->m_ddev_targp,
|
bp = xfs_buf_get(mp->m_ddev_targp,
|
||||||
XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)),
|
XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)),
|
||||||
XFS_FSS_TO_BB(mp, 1), XBF_LOCK | XBF_MAPPED);
|
XFS_FSS_TO_BB(mp, 1), XBF_LOCK | XBF_MAPPED);
|
||||||
|
if (!bp) {
|
||||||
|
error = ENOMEM;
|
||||||
|
goto error0;
|
||||||
|
}
|
||||||
agi = XFS_BUF_TO_AGI(bp);
|
agi = XFS_BUF_TO_AGI(bp);
|
||||||
memset(agi, 0, mp->m_sb.sb_sectsize);
|
memset(agi, 0, mp->m_sb.sb_sectsize);
|
||||||
agi->agi_magicnum = cpu_to_be32(XFS_AGI_MAGIC);
|
agi->agi_magicnum = cpu_to_be32(XFS_AGI_MAGIC);
|
||||||
@ -240,10 +249,11 @@ xfs_growfs_data_private(
|
|||||||
agi->agi_dirino = cpu_to_be32(NULLAGINO);
|
agi->agi_dirino = cpu_to_be32(NULLAGINO);
|
||||||
for (bucket = 0; bucket < XFS_AGI_UNLINKED_BUCKETS; bucket++)
|
for (bucket = 0; bucket < XFS_AGI_UNLINKED_BUCKETS; bucket++)
|
||||||
agi->agi_unlinked[bucket] = cpu_to_be32(NULLAGINO);
|
agi->agi_unlinked[bucket] = cpu_to_be32(NULLAGINO);
|
||||||
error = xfs_bwrite(mp, bp);
|
error = xfs_bwrite(bp);
|
||||||
if (error) {
|
xfs_buf_relse(bp);
|
||||||
|
if (error)
|
||||||
goto error0;
|
goto error0;
|
||||||
}
|
|
||||||
/*
|
/*
|
||||||
* BNO btree root block
|
* BNO btree root block
|
||||||
*/
|
*/
|
||||||
@ -251,6 +261,10 @@ xfs_growfs_data_private(
|
|||||||
XFS_AGB_TO_DADDR(mp, agno, XFS_BNO_BLOCK(mp)),
|
XFS_AGB_TO_DADDR(mp, agno, XFS_BNO_BLOCK(mp)),
|
||||||
BTOBB(mp->m_sb.sb_blocksize),
|
BTOBB(mp->m_sb.sb_blocksize),
|
||||||
XBF_LOCK | XBF_MAPPED);
|
XBF_LOCK | XBF_MAPPED);
|
||||||
|
if (!bp) {
|
||||||
|
error = ENOMEM;
|
||||||
|
goto error0;
|
||||||
|
}
|
||||||
block = XFS_BUF_TO_BLOCK(bp);
|
block = XFS_BUF_TO_BLOCK(bp);
|
||||||
memset(block, 0, mp->m_sb.sb_blocksize);
|
memset(block, 0, mp->m_sb.sb_blocksize);
|
||||||
block->bb_magic = cpu_to_be32(XFS_ABTB_MAGIC);
|
block->bb_magic = cpu_to_be32(XFS_ABTB_MAGIC);
|
||||||
@ -262,10 +276,11 @@ xfs_growfs_data_private(
|
|||||||
arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp));
|
arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp));
|
||||||
arec->ar_blockcount = cpu_to_be32(
|
arec->ar_blockcount = cpu_to_be32(
|
||||||
agsize - be32_to_cpu(arec->ar_startblock));
|
agsize - be32_to_cpu(arec->ar_startblock));
|
||||||
error = xfs_bwrite(mp, bp);
|
error = xfs_bwrite(bp);
|
||||||
if (error) {
|
xfs_buf_relse(bp);
|
||||||
|
if (error)
|
||||||
goto error0;
|
goto error0;
|
||||||
}
|
|
||||||
/*
|
/*
|
||||||
* CNT btree root block
|
* CNT btree root block
|
||||||
*/
|
*/
|
||||||
@ -273,6 +288,10 @@ xfs_growfs_data_private(
|
|||||||
XFS_AGB_TO_DADDR(mp, agno, XFS_CNT_BLOCK(mp)),
|
XFS_AGB_TO_DADDR(mp, agno, XFS_CNT_BLOCK(mp)),
|
||||||
BTOBB(mp->m_sb.sb_blocksize),
|
BTOBB(mp->m_sb.sb_blocksize),
|
||||||
XBF_LOCK | XBF_MAPPED);
|
XBF_LOCK | XBF_MAPPED);
|
||||||
|
if (!bp) {
|
||||||
|
error = ENOMEM;
|
||||||
|
goto error0;
|
||||||
|
}
|
||||||
block = XFS_BUF_TO_BLOCK(bp);
|
block = XFS_BUF_TO_BLOCK(bp);
|
||||||
memset(block, 0, mp->m_sb.sb_blocksize);
|
memset(block, 0, mp->m_sb.sb_blocksize);
|
||||||
block->bb_magic = cpu_to_be32(XFS_ABTC_MAGIC);
|
block->bb_magic = cpu_to_be32(XFS_ABTC_MAGIC);
|
||||||
@ -285,10 +304,11 @@ xfs_growfs_data_private(
|
|||||||
arec->ar_blockcount = cpu_to_be32(
|
arec->ar_blockcount = cpu_to_be32(
|
||||||
agsize - be32_to_cpu(arec->ar_startblock));
|
agsize - be32_to_cpu(arec->ar_startblock));
|
||||||
nfree += be32_to_cpu(arec->ar_blockcount);
|
nfree += be32_to_cpu(arec->ar_blockcount);
|
||||||
error = xfs_bwrite(mp, bp);
|
error = xfs_bwrite(bp);
|
||||||
if (error) {
|
xfs_buf_relse(bp);
|
||||||
|
if (error)
|
||||||
goto error0;
|
goto error0;
|
||||||
}
|
|
||||||
/*
|
/*
|
||||||
* INO btree root block
|
* INO btree root block
|
||||||
*/
|
*/
|
||||||
@ -296,6 +316,10 @@ xfs_growfs_data_private(
|
|||||||
XFS_AGB_TO_DADDR(mp, agno, XFS_IBT_BLOCK(mp)),
|
XFS_AGB_TO_DADDR(mp, agno, XFS_IBT_BLOCK(mp)),
|
||||||
BTOBB(mp->m_sb.sb_blocksize),
|
BTOBB(mp->m_sb.sb_blocksize),
|
||||||
XBF_LOCK | XBF_MAPPED);
|
XBF_LOCK | XBF_MAPPED);
|
||||||
|
if (!bp) {
|
||||||
|
error = ENOMEM;
|
||||||
|
goto error0;
|
||||||
|
}
|
||||||
block = XFS_BUF_TO_BLOCK(bp);
|
block = XFS_BUF_TO_BLOCK(bp);
|
||||||
memset(block, 0, mp->m_sb.sb_blocksize);
|
memset(block, 0, mp->m_sb.sb_blocksize);
|
||||||
block->bb_magic = cpu_to_be32(XFS_IBT_MAGIC);
|
block->bb_magic = cpu_to_be32(XFS_IBT_MAGIC);
|
||||||
@ -303,10 +327,10 @@ xfs_growfs_data_private(
|
|||||||
block->bb_numrecs = 0;
|
block->bb_numrecs = 0;
|
||||||
block->bb_u.s.bb_leftsib = cpu_to_be32(NULLAGBLOCK);
|
block->bb_u.s.bb_leftsib = cpu_to_be32(NULLAGBLOCK);
|
||||||
block->bb_u.s.bb_rightsib = cpu_to_be32(NULLAGBLOCK);
|
block->bb_u.s.bb_rightsib = cpu_to_be32(NULLAGBLOCK);
|
||||||
error = xfs_bwrite(mp, bp);
|
error = xfs_bwrite(bp);
|
||||||
if (error) {
|
xfs_buf_relse(bp);
|
||||||
|
if (error)
|
||||||
goto error0;
|
goto error0;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
xfs_trans_agblocks_delta(tp, nfree);
|
xfs_trans_agblocks_delta(tp, nfree);
|
||||||
/*
|
/*
|
||||||
@ -396,9 +420,9 @@ xfs_growfs_data_private(
|
|||||||
* just issue a warning and continue. The real work is
|
* just issue a warning and continue. The real work is
|
||||||
* already done and committed.
|
* already done and committed.
|
||||||
*/
|
*/
|
||||||
if (!(error = xfs_bwrite(mp, bp))) {
|
error = xfs_bwrite(bp);
|
||||||
continue;
|
xfs_buf_relse(bp);
|
||||||
} else {
|
if (error) {
|
||||||
xfs_warn(mp,
|
xfs_warn(mp,
|
||||||
"write error %d updating secondary superblock for ag %d",
|
"write error %d updating secondary superblock for ag %d",
|
||||||
error, agno);
|
error, agno);
|
||||||
|
@ -150,7 +150,7 @@ xfs_check_agi_freecount(
|
|||||||
/*
|
/*
|
||||||
* Initialise a new set of inodes.
|
* Initialise a new set of inodes.
|
||||||
*/
|
*/
|
||||||
STATIC void
|
STATIC int
|
||||||
xfs_ialloc_inode_init(
|
xfs_ialloc_inode_init(
|
||||||
struct xfs_mount *mp,
|
struct xfs_mount *mp,
|
||||||
struct xfs_trans *tp,
|
struct xfs_trans *tp,
|
||||||
@ -202,8 +202,8 @@ xfs_ialloc_inode_init(
|
|||||||
fbuf = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
|
fbuf = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
|
||||||
mp->m_bsize * blks_per_cluster,
|
mp->m_bsize * blks_per_cluster,
|
||||||
XBF_LOCK);
|
XBF_LOCK);
|
||||||
ASSERT(!xfs_buf_geterror(fbuf));
|
if (!fbuf)
|
||||||
|
return ENOMEM;
|
||||||
/*
|
/*
|
||||||
* Initialize all inodes in this buffer and then log them.
|
* Initialize all inodes in this buffer and then log them.
|
||||||
*
|
*
|
||||||
@ -225,6 +225,7 @@ xfs_ialloc_inode_init(
|
|||||||
}
|
}
|
||||||
xfs_trans_inode_alloc_buf(tp, fbuf);
|
xfs_trans_inode_alloc_buf(tp, fbuf);
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -369,9 +370,11 @@ xfs_ialloc_ag_alloc(
|
|||||||
* rather than a linear progression to prevent the next generation
|
* rather than a linear progression to prevent the next generation
|
||||||
* number from being easily guessable.
|
* number from being easily guessable.
|
||||||
*/
|
*/
|
||||||
xfs_ialloc_inode_init(args.mp, tp, agno, args.agbno, args.len,
|
error = xfs_ialloc_inode_init(args.mp, tp, agno, args.agbno,
|
||||||
random32());
|
args.len, random32());
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
return error;
|
||||||
/*
|
/*
|
||||||
* Convert the results.
|
* Convert the results.
|
||||||
*/
|
*/
|
||||||
@ -1502,7 +1505,7 @@ xfs_read_agi(
|
|||||||
return XFS_ERROR(EFSCORRUPTED);
|
return XFS_ERROR(EFSCORRUPTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
XFS_BUF_SET_VTYPE_REF(*bpp, B_FS_AGI, XFS_AGI_REF);
|
xfs_buf_set_ref(*bpp, XFS_AGI_REF);
|
||||||
|
|
||||||
xfs_check_agi_unlinked(agi);
|
xfs_check_agi_unlinked(agi);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -75,7 +75,6 @@ xfs_inode_alloc(
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(atomic_read(&ip->i_iocount) == 0);
|
|
||||||
ASSERT(atomic_read(&ip->i_pincount) == 0);
|
ASSERT(atomic_read(&ip->i_pincount) == 0);
|
||||||
ASSERT(!spin_is_locked(&ip->i_flags_lock));
|
ASSERT(!spin_is_locked(&ip->i_flags_lock));
|
||||||
ASSERT(completion_done(&ip->i_flush));
|
ASSERT(completion_done(&ip->i_flush));
|
||||||
@ -150,7 +149,6 @@ xfs_inode_free(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* asserts to verify all state is correct here */
|
/* asserts to verify all state is correct here */
|
||||||
ASSERT(atomic_read(&ip->i_iocount) == 0);
|
|
||||||
ASSERT(atomic_read(&ip->i_pincount) == 0);
|
ASSERT(atomic_read(&ip->i_pincount) == 0);
|
||||||
ASSERT(!spin_is_locked(&ip->i_flags_lock));
|
ASSERT(!spin_is_locked(&ip->i_flags_lock));
|
||||||
ASSERT(completion_done(&ip->i_flush));
|
ASSERT(completion_done(&ip->i_flush));
|
||||||
|
@ -190,12 +190,6 @@ xfs_imap_to_bp(
|
|||||||
}
|
}
|
||||||
|
|
||||||
xfs_inobp_check(mp, bp);
|
xfs_inobp_check(mp, bp);
|
||||||
|
|
||||||
/*
|
|
||||||
* Mark the buffer as an inode buffer now that it looks good
|
|
||||||
*/
|
|
||||||
XFS_BUF_SET_VTYPE(bp, B_FS_INO);
|
|
||||||
|
|
||||||
*bpp = bp;
|
*bpp = bp;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1152,7 +1146,7 @@ xfs_ialloc(
|
|||||||
/*
|
/*
|
||||||
* Log the new values stuffed into the inode.
|
* Log the new values stuffed into the inode.
|
||||||
*/
|
*/
|
||||||
xfs_trans_ijoin_ref(tp, ip, XFS_ILOCK_EXCL);
|
xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
|
||||||
xfs_trans_log_inode(tp, ip, flags);
|
xfs_trans_log_inode(tp, ip, flags);
|
||||||
|
|
||||||
/* now that we have an i_mode we can setup inode ops and unlock */
|
/* now that we have an i_mode we can setup inode ops and unlock */
|
||||||
@ -1187,6 +1181,7 @@ xfs_isize_check(
|
|||||||
xfs_fileoff_t map_first;
|
xfs_fileoff_t map_first;
|
||||||
int nimaps;
|
int nimaps;
|
||||||
xfs_bmbt_irec_t imaps[2];
|
xfs_bmbt_irec_t imaps[2];
|
||||||
|
int error;
|
||||||
|
|
||||||
if (!S_ISREG(ip->i_d.di_mode))
|
if (!S_ISREG(ip->i_d.di_mode))
|
||||||
return;
|
return;
|
||||||
@ -1203,13 +1198,12 @@ xfs_isize_check(
|
|||||||
* The filesystem could be shutting down, so bmapi may return
|
* The filesystem could be shutting down, so bmapi may return
|
||||||
* an error.
|
* an error.
|
||||||
*/
|
*/
|
||||||
if (xfs_bmapi(NULL, ip, map_first,
|
error = xfs_bmapi_read(ip, map_first,
|
||||||
(XFS_B_TO_FSB(mp,
|
(XFS_B_TO_FSB(mp,
|
||||||
(xfs_ufsize_t)XFS_MAXIOFFSET(mp)) -
|
(xfs_ufsize_t)XFS_MAXIOFFSET(mp)) - map_first),
|
||||||
map_first),
|
imaps, &nimaps, XFS_BMAPI_ENTIRE);
|
||||||
XFS_BMAPI_ENTIRE, NULL, 0, imaps, &nimaps,
|
if (error)
|
||||||
NULL))
|
return;
|
||||||
return;
|
|
||||||
ASSERT(nimaps == 1);
|
ASSERT(nimaps == 1);
|
||||||
ASSERT(imaps[0].br_startblock == HOLESTARTBLOCK);
|
ASSERT(imaps[0].br_startblock == HOLESTARTBLOCK);
|
||||||
}
|
}
|
||||||
@ -1297,7 +1291,7 @@ xfs_itruncate_extents(
|
|||||||
*/
|
*/
|
||||||
error = xfs_bmap_finish(&tp, &free_list, &committed);
|
error = xfs_bmap_finish(&tp, &free_list, &committed);
|
||||||
if (committed)
|
if (committed)
|
||||||
xfs_trans_ijoin(tp, ip);
|
xfs_trans_ijoin(tp, ip, 0);
|
||||||
if (error)
|
if (error)
|
||||||
goto out_bmap_cancel;
|
goto out_bmap_cancel;
|
||||||
|
|
||||||
@ -1313,7 +1307,7 @@ xfs_itruncate_extents(
|
|||||||
error = xfs_trans_commit(tp, 0);
|
error = xfs_trans_commit(tp, 0);
|
||||||
tp = ntp;
|
tp = ntp;
|
||||||
|
|
||||||
xfs_trans_ijoin(tp, ip);
|
xfs_trans_ijoin(tp, ip, 0);
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
goto out;
|
goto out;
|
||||||
@ -1644,7 +1638,7 @@ xfs_iunlink_remove(
|
|||||||
* inodes that are in memory - they all must be marked stale and attached to
|
* inodes that are in memory - they all must be marked stale and attached to
|
||||||
* the cluster buffer.
|
* the cluster buffer.
|
||||||
*/
|
*/
|
||||||
STATIC void
|
STATIC int
|
||||||
xfs_ifree_cluster(
|
xfs_ifree_cluster(
|
||||||
xfs_inode_t *free_ip,
|
xfs_inode_t *free_ip,
|
||||||
xfs_trans_t *tp,
|
xfs_trans_t *tp,
|
||||||
@ -1690,6 +1684,8 @@ xfs_ifree_cluster(
|
|||||||
mp->m_bsize * blks_per_cluster,
|
mp->m_bsize * blks_per_cluster,
|
||||||
XBF_LOCK);
|
XBF_LOCK);
|
||||||
|
|
||||||
|
if (!bp)
|
||||||
|
return ENOMEM;
|
||||||
/*
|
/*
|
||||||
* Walk the inodes already attached to the buffer and mark them
|
* Walk the inodes already attached to the buffer and mark them
|
||||||
* stale. These will all have the flush locks held, so an
|
* stale. These will all have the flush locks held, so an
|
||||||
@ -1799,6 +1795,7 @@ retry:
|
|||||||
}
|
}
|
||||||
|
|
||||||
xfs_perag_put(pag);
|
xfs_perag_put(pag);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1878,10 +1875,10 @@ xfs_ifree(
|
|||||||
dip->di_mode = 0;
|
dip->di_mode = 0;
|
||||||
|
|
||||||
if (delete) {
|
if (delete) {
|
||||||
xfs_ifree_cluster(ip, tp, first_ino);
|
error = xfs_ifree_cluster(ip, tp, first_ino);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2472,11 +2469,11 @@ cluster_corrupt_out:
|
|||||||
*/
|
*/
|
||||||
if (bp->b_iodone) {
|
if (bp->b_iodone) {
|
||||||
XFS_BUF_UNDONE(bp);
|
XFS_BUF_UNDONE(bp);
|
||||||
XFS_BUF_STALE(bp);
|
xfs_buf_stale(bp);
|
||||||
xfs_buf_ioerror(bp, EIO);
|
xfs_buf_ioerror(bp, EIO);
|
||||||
xfs_buf_ioend(bp, 0);
|
xfs_buf_ioend(bp, 0);
|
||||||
} else {
|
} else {
|
||||||
XFS_BUF_STALE(bp);
|
xfs_buf_stale(bp);
|
||||||
xfs_buf_relse(bp);
|
xfs_buf_relse(bp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2597,9 +2594,11 @@ xfs_iflush(
|
|||||||
goto cluster_corrupt_out;
|
goto cluster_corrupt_out;
|
||||||
|
|
||||||
if (flags & SYNC_WAIT)
|
if (flags & SYNC_WAIT)
|
||||||
error = xfs_bwrite(mp, bp);
|
error = xfs_bwrite(bp);
|
||||||
else
|
else
|
||||||
xfs_bdwrite(mp, bp);
|
xfs_buf_delwri_queue(bp);
|
||||||
|
|
||||||
|
xfs_buf_relse(bp);
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
corrupt_out:
|
corrupt_out:
|
||||||
|
@ -257,7 +257,6 @@ typedef struct xfs_inode {
|
|||||||
|
|
||||||
xfs_fsize_t i_size; /* in-memory size */
|
xfs_fsize_t i_size; /* in-memory size */
|
||||||
xfs_fsize_t i_new_size; /* size when write completes */
|
xfs_fsize_t i_new_size; /* size when write completes */
|
||||||
atomic_t i_iocount; /* outstanding I/O count */
|
|
||||||
|
|
||||||
/* VFS inode */
|
/* VFS inode */
|
||||||
struct inode i_vnode; /* embedded VFS inode */
|
struct inode i_vnode; /* embedded VFS inode */
|
||||||
|
@ -658,10 +658,8 @@ xfs_inode_item_unlock(
|
|||||||
|
|
||||||
lock_flags = iip->ili_lock_flags;
|
lock_flags = iip->ili_lock_flags;
|
||||||
iip->ili_lock_flags = 0;
|
iip->ili_lock_flags = 0;
|
||||||
if (lock_flags) {
|
if (lock_flags)
|
||||||
xfs_iunlock(ip, lock_flags);
|
xfs_iunlock(ip, lock_flags);
|
||||||
IRELE(ip);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1069,7 +1069,7 @@ xfs_ioctl_setattr(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
xfs_trans_ijoin(tp, ip);
|
xfs_trans_ijoin(tp, ip, 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Change file ownership. Must be the owner or privileged.
|
* Change file ownership. Must be the owner or privileged.
|
||||||
|
@ -208,22 +208,20 @@ xfs_iomap_write_direct(
|
|||||||
if (error)
|
if (error)
|
||||||
goto error1;
|
goto error1;
|
||||||
|
|
||||||
xfs_trans_ijoin(tp, ip);
|
xfs_trans_ijoin(tp, ip, 0);
|
||||||
|
|
||||||
bmapi_flag = XFS_BMAPI_WRITE;
|
bmapi_flag = 0;
|
||||||
if (offset < ip->i_size || extsz)
|
if (offset < ip->i_size || extsz)
|
||||||
bmapi_flag |= XFS_BMAPI_PREALLOC;
|
bmapi_flag |= XFS_BMAPI_PREALLOC;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Issue the xfs_bmapi() call to allocate the blocks.
|
|
||||||
*
|
|
||||||
* From this point onwards we overwrite the imap pointer that the
|
* From this point onwards we overwrite the imap pointer that the
|
||||||
* caller gave to us.
|
* caller gave to us.
|
||||||
*/
|
*/
|
||||||
xfs_bmap_init(&free_list, &firstfsb);
|
xfs_bmap_init(&free_list, &firstfsb);
|
||||||
nimaps = 1;
|
nimaps = 1;
|
||||||
error = xfs_bmapi(tp, ip, offset_fsb, count_fsb, bmapi_flag,
|
error = xfs_bmapi_write(tp, ip, offset_fsb, count_fsb, bmapi_flag,
|
||||||
&firstfsb, 0, imap, &nimaps, &free_list);
|
&firstfsb, 0, imap, &nimaps, &free_list);
|
||||||
if (error)
|
if (error)
|
||||||
goto error0;
|
goto error0;
|
||||||
|
|
||||||
@ -300,8 +298,8 @@ xfs_iomap_eof_want_preallocate(
|
|||||||
while (count_fsb > 0) {
|
while (count_fsb > 0) {
|
||||||
imaps = nimaps;
|
imaps = nimaps;
|
||||||
firstblock = NULLFSBLOCK;
|
firstblock = NULLFSBLOCK;
|
||||||
error = xfs_bmapi(NULL, ip, start_fsb, count_fsb, 0,
|
error = xfs_bmapi_read(ip, start_fsb, count_fsb, imap, &imaps,
|
||||||
&firstblock, 0, imap, &imaps, NULL);
|
0);
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
for (n = 0; n < imaps; n++) {
|
for (n = 0; n < imaps; n++) {
|
||||||
@ -381,7 +379,6 @@ xfs_iomap_write_delay(
|
|||||||
xfs_fileoff_t last_fsb;
|
xfs_fileoff_t last_fsb;
|
||||||
xfs_off_t aligned_offset;
|
xfs_off_t aligned_offset;
|
||||||
xfs_fileoff_t ioalign;
|
xfs_fileoff_t ioalign;
|
||||||
xfs_fsblock_t firstblock;
|
|
||||||
xfs_extlen_t extsz;
|
xfs_extlen_t extsz;
|
||||||
int nimaps;
|
int nimaps;
|
||||||
xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS];
|
xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS];
|
||||||
@ -425,12 +422,8 @@ retry:
|
|||||||
}
|
}
|
||||||
|
|
||||||
nimaps = XFS_WRITE_IMAPS;
|
nimaps = XFS_WRITE_IMAPS;
|
||||||
firstblock = NULLFSBLOCK;
|
error = xfs_bmapi_delay(ip, offset_fsb, last_fsb - offset_fsb,
|
||||||
error = xfs_bmapi(NULL, ip, offset_fsb,
|
imap, &nimaps, XFS_BMAPI_ENTIRE);
|
||||||
(xfs_filblks_t)(last_fsb - offset_fsb),
|
|
||||||
XFS_BMAPI_DELAY | XFS_BMAPI_WRITE |
|
|
||||||
XFS_BMAPI_ENTIRE, &firstblock, 1, imap,
|
|
||||||
&nimaps, NULL);
|
|
||||||
switch (error) {
|
switch (error) {
|
||||||
case 0:
|
case 0:
|
||||||
case ENOSPC:
|
case ENOSPC:
|
||||||
@ -535,7 +528,7 @@ xfs_iomap_write_allocate(
|
|||||||
return XFS_ERROR(error);
|
return XFS_ERROR(error);
|
||||||
}
|
}
|
||||||
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
||||||
xfs_trans_ijoin(tp, ip);
|
xfs_trans_ijoin(tp, ip, 0);
|
||||||
|
|
||||||
xfs_bmap_init(&free_list, &first_block);
|
xfs_bmap_init(&free_list, &first_block);
|
||||||
|
|
||||||
@ -587,14 +580,12 @@ xfs_iomap_write_allocate(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Go get the actual blocks.
|
|
||||||
*
|
|
||||||
* From this point onwards we overwrite the imap
|
* From this point onwards we overwrite the imap
|
||||||
* pointer that the caller gave to us.
|
* pointer that the caller gave to us.
|
||||||
*/
|
*/
|
||||||
error = xfs_bmapi(tp, ip, map_start_fsb, count_fsb,
|
error = xfs_bmapi_write(tp, ip, map_start_fsb,
|
||||||
XFS_BMAPI_WRITE, &first_block, 1,
|
count_fsb, 0, &first_block, 1,
|
||||||
imap, &nimaps, &free_list);
|
imap, &nimaps, &free_list);
|
||||||
if (error)
|
if (error)
|
||||||
goto trans_cancel;
|
goto trans_cancel;
|
||||||
|
|
||||||
@ -701,15 +692,15 @@ xfs_iomap_write_unwritten(
|
|||||||
}
|
}
|
||||||
|
|
||||||
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
||||||
xfs_trans_ijoin(tp, ip);
|
xfs_trans_ijoin(tp, ip, 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Modify the unwritten extent state of the buffer.
|
* Modify the unwritten extent state of the buffer.
|
||||||
*/
|
*/
|
||||||
xfs_bmap_init(&free_list, &firstfsb);
|
xfs_bmap_init(&free_list, &firstfsb);
|
||||||
nimaps = 1;
|
nimaps = 1;
|
||||||
error = xfs_bmapi(tp, ip, offset_fsb, count_fsb,
|
error = xfs_bmapi_write(tp, ip, offset_fsb, count_fsb,
|
||||||
XFS_BMAPI_WRITE|XFS_BMAPI_CONVERT, &firstfsb,
|
XFS_BMAPI_CONVERT, &firstfsb,
|
||||||
1, &imap, &nimaps, &free_list);
|
1, &imap, &nimaps, &free_list);
|
||||||
if (error)
|
if (error)
|
||||||
goto error_on_bmapi_transaction;
|
goto error_on_bmapi_transaction;
|
||||||
|
@ -466,7 +466,7 @@ xfs_vn_getattr(
|
|||||||
trace_xfs_getattr(ip);
|
trace_xfs_getattr(ip);
|
||||||
|
|
||||||
if (XFS_FORCED_SHUTDOWN(mp))
|
if (XFS_FORCED_SHUTDOWN(mp))
|
||||||
return XFS_ERROR(EIO);
|
return -XFS_ERROR(EIO);
|
||||||
|
|
||||||
stat->size = XFS_ISIZE(ip);
|
stat->size = XFS_ISIZE(ip);
|
||||||
stat->dev = inode->i_sb->s_dev;
|
stat->dev = inode->i_sb->s_dev;
|
||||||
@ -612,7 +612,7 @@ xfs_setattr_nonsize(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
xfs_trans_ijoin(tp, ip);
|
xfs_trans_ijoin(tp, ip, 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Change file ownership. Must be the owner or privileged.
|
* Change file ownership. Must be the owner or privileged.
|
||||||
@ -834,16 +834,16 @@ xfs_setattr_size(
|
|||||||
* care about here.
|
* care about here.
|
||||||
*/
|
*/
|
||||||
if (ip->i_size != ip->i_d.di_size && iattr->ia_size > ip->i_d.di_size) {
|
if (ip->i_size != ip->i_d.di_size && iattr->ia_size > ip->i_d.di_size) {
|
||||||
error = xfs_flush_pages(ip, ip->i_d.di_size, iattr->ia_size,
|
error = xfs_flush_pages(ip, ip->i_d.di_size, iattr->ia_size, 0,
|
||||||
XBF_ASYNC, FI_NONE);
|
FI_NONE);
|
||||||
if (error)
|
if (error)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wait for all I/O to complete.
|
* Wait for all direct I/O to complete.
|
||||||
*/
|
*/
|
||||||
xfs_ioend_wait(ip);
|
inode_dio_wait(inode);
|
||||||
|
|
||||||
error = -block_truncate_page(inode->i_mapping, iattr->ia_size,
|
error = -block_truncate_page(inode->i_mapping, iattr->ia_size,
|
||||||
xfs_get_blocks);
|
xfs_get_blocks);
|
||||||
@ -864,7 +864,7 @@ xfs_setattr_size(
|
|||||||
|
|
||||||
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
||||||
|
|
||||||
xfs_trans_ijoin(tp, ip);
|
xfs_trans_ijoin(tp, ip, 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Only change the c/mtime if we are changing the size or we are
|
* Only change the c/mtime if we are changing the size or we are
|
||||||
|
@ -880,8 +880,8 @@ xlog_iodone(xfs_buf_t *bp)
|
|||||||
*/
|
*/
|
||||||
if (XFS_TEST_ERROR((xfs_buf_geterror(bp)), l->l_mp,
|
if (XFS_TEST_ERROR((xfs_buf_geterror(bp)), l->l_mp,
|
||||||
XFS_ERRTAG_IODONE_IOERR, XFS_RANDOM_IODONE_IOERR)) {
|
XFS_ERRTAG_IODONE_IOERR, XFS_RANDOM_IODONE_IOERR)) {
|
||||||
xfs_ioerror_alert("xlog_iodone", l->l_mp, bp, XFS_BUF_ADDR(bp));
|
xfs_buf_ioerror_alert(bp, __func__);
|
||||||
XFS_BUF_STALE(bp);
|
xfs_buf_stale(bp);
|
||||||
xfs_force_shutdown(l->l_mp, SHUTDOWN_LOG_IO_ERROR);
|
xfs_force_shutdown(l->l_mp, SHUTDOWN_LOG_IO_ERROR);
|
||||||
/*
|
/*
|
||||||
* This flag will be propagated to the trans-committed
|
* This flag will be propagated to the trans-committed
|
||||||
@ -1047,7 +1047,7 @@ xlog_alloc_log(xfs_mount_t *mp,
|
|||||||
xlog_get_iclog_buffer_size(mp, log);
|
xlog_get_iclog_buffer_size(mp, log);
|
||||||
|
|
||||||
error = ENOMEM;
|
error = ENOMEM;
|
||||||
bp = xfs_buf_get_empty(log->l_iclog_size, mp->m_logdev_targp);
|
bp = xfs_buf_alloc(mp->m_logdev_targp, 0, log->l_iclog_size, 0);
|
||||||
if (!bp)
|
if (!bp)
|
||||||
goto out_free_log;
|
goto out_free_log;
|
||||||
bp->b_iodone = xlog_iodone;
|
bp->b_iodone = xlog_iodone;
|
||||||
@ -1247,7 +1247,7 @@ xlog_bdstrat(
|
|||||||
|
|
||||||
if (iclog->ic_state & XLOG_STATE_IOERROR) {
|
if (iclog->ic_state & XLOG_STATE_IOERROR) {
|
||||||
xfs_buf_ioerror(bp, EIO);
|
xfs_buf_ioerror(bp, EIO);
|
||||||
XFS_BUF_STALE(bp);
|
xfs_buf_stale(bp);
|
||||||
xfs_buf_ioend(bp, 0);
|
xfs_buf_ioend(bp, 0);
|
||||||
/*
|
/*
|
||||||
* It would seem logical to return EIO here, but we rely on
|
* It would seem logical to return EIO here, but we rely on
|
||||||
@ -1387,9 +1387,9 @@ xlog_sync(xlog_t *log,
|
|||||||
*/
|
*/
|
||||||
XFS_BUF_WRITE(bp);
|
XFS_BUF_WRITE(bp);
|
||||||
|
|
||||||
if ((error = xlog_bdstrat(bp))) {
|
error = xlog_bdstrat(bp);
|
||||||
xfs_ioerror_alert("xlog_sync", log->l_mp, bp,
|
if (error) {
|
||||||
XFS_BUF_ADDR(bp));
|
xfs_buf_ioerror_alert(bp, "xlog_sync");
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
if (split) {
|
if (split) {
|
||||||
@ -1423,9 +1423,9 @@ xlog_sync(xlog_t *log,
|
|||||||
/* account for internal log which doesn't start at block #0 */
|
/* account for internal log which doesn't start at block #0 */
|
||||||
XFS_BUF_SET_ADDR(bp, XFS_BUF_ADDR(bp) + log->l_logBBstart);
|
XFS_BUF_SET_ADDR(bp, XFS_BUF_ADDR(bp) + log->l_logBBstart);
|
||||||
XFS_BUF_WRITE(bp);
|
XFS_BUF_WRITE(bp);
|
||||||
if ((error = xlog_bdstrat(bp))) {
|
error = xlog_bdstrat(bp);
|
||||||
xfs_ioerror_alert("xlog_sync (split)", log->l_mp,
|
if (error) {
|
||||||
bp, XFS_BUF_ADDR(bp));
|
xfs_buf_ioerror_alert(bp, "xlog_sync (split)");
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -183,8 +183,7 @@ xlog_bread_noalign(
|
|||||||
xfsbdstrat(log->l_mp, bp);
|
xfsbdstrat(log->l_mp, bp);
|
||||||
error = xfs_buf_iowait(bp);
|
error = xfs_buf_iowait(bp);
|
||||||
if (error)
|
if (error)
|
||||||
xfs_ioerror_alert("xlog_bread", log->l_mp,
|
xfs_buf_ioerror_alert(bp, __func__);
|
||||||
bp, XFS_BUF_ADDR(bp));
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,9 +267,10 @@ xlog_bwrite(
|
|||||||
xfs_buf_lock(bp);
|
xfs_buf_lock(bp);
|
||||||
XFS_BUF_SET_COUNT(bp, BBTOB(nbblks));
|
XFS_BUF_SET_COUNT(bp, BBTOB(nbblks));
|
||||||
|
|
||||||
if ((error = xfs_bwrite(log->l_mp, bp)))
|
error = xfs_bwrite(bp);
|
||||||
xfs_ioerror_alert("xlog_bwrite", log->l_mp,
|
if (error)
|
||||||
bp, XFS_BUF_ADDR(bp));
|
xfs_buf_ioerror_alert(bp, __func__);
|
||||||
|
xfs_buf_relse(bp);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -361,9 +361,7 @@ xlog_recover_iodone(
|
|||||||
* We're not going to bother about retrying
|
* We're not going to bother about retrying
|
||||||
* this during recovery. One strike!
|
* this during recovery. One strike!
|
||||||
*/
|
*/
|
||||||
xfs_ioerror_alert("xlog_recover_iodone",
|
xfs_buf_ioerror_alert(bp, __func__);
|
||||||
bp->b_target->bt_mount, bp,
|
|
||||||
XFS_BUF_ADDR(bp));
|
|
||||||
xfs_force_shutdown(bp->b_target->bt_mount,
|
xfs_force_shutdown(bp->b_target->bt_mount,
|
||||||
SHUTDOWN_META_IO_ERROR);
|
SHUTDOWN_META_IO_ERROR);
|
||||||
}
|
}
|
||||||
@ -2135,8 +2133,7 @@ xlog_recover_buffer_pass2(
|
|||||||
return XFS_ERROR(ENOMEM);
|
return XFS_ERROR(ENOMEM);
|
||||||
error = bp->b_error;
|
error = bp->b_error;
|
||||||
if (error) {
|
if (error) {
|
||||||
xfs_ioerror_alert("xlog_recover_do..(read#1)", mp,
|
xfs_buf_ioerror_alert(bp, "xlog_recover_do..(read#1)");
|
||||||
bp, buf_f->blf_blkno);
|
|
||||||
xfs_buf_relse(bp);
|
xfs_buf_relse(bp);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
@ -2171,15 +2168,16 @@ xlog_recover_buffer_pass2(
|
|||||||
be16_to_cpu(*((__be16 *)xfs_buf_offset(bp, 0))) &&
|
be16_to_cpu(*((__be16 *)xfs_buf_offset(bp, 0))) &&
|
||||||
(XFS_BUF_COUNT(bp) != MAX(log->l_mp->m_sb.sb_blocksize,
|
(XFS_BUF_COUNT(bp) != MAX(log->l_mp->m_sb.sb_blocksize,
|
||||||
(__uint32_t)XFS_INODE_CLUSTER_SIZE(log->l_mp)))) {
|
(__uint32_t)XFS_INODE_CLUSTER_SIZE(log->l_mp)))) {
|
||||||
XFS_BUF_STALE(bp);
|
xfs_buf_stale(bp);
|
||||||
error = xfs_bwrite(mp, bp);
|
error = xfs_bwrite(bp);
|
||||||
} else {
|
} else {
|
||||||
ASSERT(bp->b_target->bt_mount == mp);
|
ASSERT(bp->b_target->bt_mount == mp);
|
||||||
bp->b_iodone = xlog_recover_iodone;
|
bp->b_iodone = xlog_recover_iodone;
|
||||||
xfs_bdwrite(mp, bp);
|
xfs_buf_delwri_queue(bp);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (error);
|
xfs_buf_relse(bp);
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC int
|
STATIC int
|
||||||
@ -2230,8 +2228,7 @@ xlog_recover_inode_pass2(
|
|||||||
}
|
}
|
||||||
error = bp->b_error;
|
error = bp->b_error;
|
||||||
if (error) {
|
if (error) {
|
||||||
xfs_ioerror_alert("xlog_recover_do..(read#2)", mp,
|
xfs_buf_ioerror_alert(bp, "xlog_recover_do..(read#2)");
|
||||||
bp, in_f->ilf_blkno);
|
|
||||||
xfs_buf_relse(bp);
|
xfs_buf_relse(bp);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@ -2439,7 +2436,8 @@ xlog_recover_inode_pass2(
|
|||||||
write_inode_buffer:
|
write_inode_buffer:
|
||||||
ASSERT(bp->b_target->bt_mount == mp);
|
ASSERT(bp->b_target->bt_mount == mp);
|
||||||
bp->b_iodone = xlog_recover_iodone;
|
bp->b_iodone = xlog_recover_iodone;
|
||||||
xfs_bdwrite(mp, bp);
|
xfs_buf_delwri_queue(bp);
|
||||||
|
xfs_buf_relse(bp);
|
||||||
error:
|
error:
|
||||||
if (need_free)
|
if (need_free)
|
||||||
kmem_free(in_f);
|
kmem_free(in_f);
|
||||||
@ -2537,8 +2535,7 @@ xlog_recover_dquot_pass2(
|
|||||||
XFS_FSB_TO_BB(mp, dq_f->qlf_len),
|
XFS_FSB_TO_BB(mp, dq_f->qlf_len),
|
||||||
0, &bp);
|
0, &bp);
|
||||||
if (error) {
|
if (error) {
|
||||||
xfs_ioerror_alert("xlog_recover_do..(read#3)", mp,
|
xfs_buf_ioerror_alert(bp, "xlog_recover_do..(read#3)");
|
||||||
bp, dq_f->qlf_blkno);
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
ASSERT(bp);
|
ASSERT(bp);
|
||||||
@ -2561,7 +2558,8 @@ xlog_recover_dquot_pass2(
|
|||||||
ASSERT(dq_f->qlf_size == 2);
|
ASSERT(dq_f->qlf_size == 2);
|
||||||
ASSERT(bp->b_target->bt_mount == mp);
|
ASSERT(bp->b_target->bt_mount == mp);
|
||||||
bp->b_iodone = xlog_recover_iodone;
|
bp->b_iodone = xlog_recover_iodone;
|
||||||
xfs_bdwrite(mp, bp);
|
xfs_buf_delwri_queue(bp);
|
||||||
|
xfs_buf_relse(bp);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
@ -3656,7 +3654,7 @@ xlog_do_recover(
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
XFS_bflush(log->l_mp->m_ddev_targp);
|
xfs_flush_buftarg(log->l_mp->m_ddev_targp, 1);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If IO errors happened during recovery, bail out.
|
* If IO errors happened during recovery, bail out.
|
||||||
@ -3689,8 +3687,7 @@ xlog_do_recover(
|
|||||||
xfsbdstrat(log->l_mp, bp);
|
xfsbdstrat(log->l_mp, bp);
|
||||||
error = xfs_buf_iowait(bp);
|
error = xfs_buf_iowait(bp);
|
||||||
if (error) {
|
if (error) {
|
||||||
xfs_ioerror_alert("xlog_do_recover",
|
xfs_buf_ioerror_alert(bp, __func__);
|
||||||
log->l_mp, bp, XFS_BUF_ADDR(bp));
|
|
||||||
ASSERT(0);
|
ASSERT(0);
|
||||||
xfs_buf_relse(bp);
|
xfs_buf_relse(bp);
|
||||||
return error;
|
return error;
|
||||||
|
@ -44,9 +44,6 @@
|
|||||||
#include "xfs_trace.h"
|
#include "xfs_trace.h"
|
||||||
|
|
||||||
|
|
||||||
STATIC void xfs_unmountfs_wait(xfs_mount_t *);
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_PERCPU_SB
|
#ifdef HAVE_PERCPU_SB
|
||||||
STATIC void xfs_icsb_balance_counter(xfs_mount_t *, xfs_sb_field_t,
|
STATIC void xfs_icsb_balance_counter(xfs_mount_t *, xfs_sb_field_t,
|
||||||
int);
|
int);
|
||||||
@ -1484,7 +1481,7 @@ xfs_unmountfs(
|
|||||||
* state as much as possible.
|
* state as much as possible.
|
||||||
*/
|
*/
|
||||||
xfs_reclaim_inodes(mp, 0);
|
xfs_reclaim_inodes(mp, 0);
|
||||||
XFS_bflush(mp->m_ddev_targp);
|
xfs_flush_buftarg(mp->m_ddev_targp, 1);
|
||||||
xfs_reclaim_inodes(mp, SYNC_WAIT);
|
xfs_reclaim_inodes(mp, SYNC_WAIT);
|
||||||
|
|
||||||
xfs_qm_unmount(mp);
|
xfs_qm_unmount(mp);
|
||||||
@ -1496,11 +1493,6 @@ xfs_unmountfs(
|
|||||||
*/
|
*/
|
||||||
xfs_log_force(mp, XFS_LOG_SYNC);
|
xfs_log_force(mp, XFS_LOG_SYNC);
|
||||||
|
|
||||||
xfs_binval(mp->m_ddev_targp);
|
|
||||||
if (mp->m_rtdev_targp) {
|
|
||||||
xfs_binval(mp->m_rtdev_targp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Unreserve any blocks we have so that when we unmount we don't account
|
* Unreserve any blocks we have so that when we unmount we don't account
|
||||||
* the reserved free space as used. This is really only necessary for
|
* the reserved free space as used. This is really only necessary for
|
||||||
@ -1526,7 +1518,16 @@ xfs_unmountfs(
|
|||||||
xfs_warn(mp, "Unable to update superblock counters. "
|
xfs_warn(mp, "Unable to update superblock counters. "
|
||||||
"Freespace may not be correct on next mount.");
|
"Freespace may not be correct on next mount.");
|
||||||
xfs_unmountfs_writesb(mp);
|
xfs_unmountfs_writesb(mp);
|
||||||
xfs_unmountfs_wait(mp); /* wait for async bufs */
|
|
||||||
|
/*
|
||||||
|
* Make sure all buffers have been flushed and completed before
|
||||||
|
* unmounting the log.
|
||||||
|
*/
|
||||||
|
error = xfs_flush_buftarg(mp->m_ddev_targp, 1);
|
||||||
|
if (error)
|
||||||
|
xfs_warn(mp, "%d busy buffers during unmount.", error);
|
||||||
|
xfs_wait_buftarg(mp->m_ddev_targp);
|
||||||
|
|
||||||
xfs_log_unmount_write(mp);
|
xfs_log_unmount_write(mp);
|
||||||
xfs_log_unmount(mp);
|
xfs_log_unmount(mp);
|
||||||
xfs_uuid_unmount(mp);
|
xfs_uuid_unmount(mp);
|
||||||
@ -1537,16 +1538,6 @@ xfs_unmountfs(
|
|||||||
xfs_free_perag(mp);
|
xfs_free_perag(mp);
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC void
|
|
||||||
xfs_unmountfs_wait(xfs_mount_t *mp)
|
|
||||||
{
|
|
||||||
if (mp->m_logdev_targp != mp->m_ddev_targp)
|
|
||||||
xfs_wait_buftarg(mp->m_logdev_targp);
|
|
||||||
if (mp->m_rtdev_targp)
|
|
||||||
xfs_wait_buftarg(mp->m_rtdev_targp);
|
|
||||||
xfs_wait_buftarg(mp->m_ddev_targp);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
xfs_fs_writable(xfs_mount_t *mp)
|
xfs_fs_writable(xfs_mount_t *mp)
|
||||||
{
|
{
|
||||||
@ -1612,15 +1603,14 @@ xfs_unmountfs_writesb(xfs_mount_t *mp)
|
|||||||
|
|
||||||
XFS_BUF_UNDONE(sbp);
|
XFS_BUF_UNDONE(sbp);
|
||||||
XFS_BUF_UNREAD(sbp);
|
XFS_BUF_UNREAD(sbp);
|
||||||
XFS_BUF_UNDELAYWRITE(sbp);
|
xfs_buf_delwri_dequeue(sbp);
|
||||||
XFS_BUF_WRITE(sbp);
|
XFS_BUF_WRITE(sbp);
|
||||||
XFS_BUF_UNASYNC(sbp);
|
XFS_BUF_UNASYNC(sbp);
|
||||||
ASSERT(sbp->b_target == mp->m_ddev_targp);
|
ASSERT(sbp->b_target == mp->m_ddev_targp);
|
||||||
xfsbdstrat(mp, sbp);
|
xfsbdstrat(mp, sbp);
|
||||||
error = xfs_buf_iowait(sbp);
|
error = xfs_buf_iowait(sbp);
|
||||||
if (error)
|
if (error)
|
||||||
xfs_ioerror_alert("xfs_unmountfs_writesb",
|
xfs_buf_ioerror_alert(sbp, __func__);
|
||||||
mp, sbp, XFS_BUF_ADDR(sbp));
|
|
||||||
xfs_buf_relse(sbp);
|
xfs_buf_relse(sbp);
|
||||||
}
|
}
|
||||||
return error;
|
return error;
|
||||||
|
@ -1296,7 +1296,8 @@ xfs_qm_dqiter_bufs(
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
xfs_qm_reset_dqcounts(mp, bp, firstid, type);
|
xfs_qm_reset_dqcounts(mp, bp, firstid, type);
|
||||||
xfs_bdwrite(mp, bp);
|
xfs_buf_delwri_queue(bp);
|
||||||
|
xfs_buf_relse(bp);
|
||||||
/*
|
/*
|
||||||
* goto the next block.
|
* goto the next block.
|
||||||
*/
|
*/
|
||||||
@ -1346,11 +1347,8 @@ xfs_qm_dqiterate(
|
|||||||
* the inode is never added to the transaction.
|
* the inode is never added to the transaction.
|
||||||
*/
|
*/
|
||||||
xfs_ilock(qip, XFS_ILOCK_SHARED);
|
xfs_ilock(qip, XFS_ILOCK_SHARED);
|
||||||
error = xfs_bmapi(NULL, qip, lblkno,
|
error = xfs_bmapi_read(qip, lblkno, maxlblkcnt - lblkno,
|
||||||
maxlblkcnt - lblkno,
|
map, &nmaps, 0);
|
||||||
XFS_BMAPI_METADATA,
|
|
||||||
NULL,
|
|
||||||
0, map, &nmaps, NULL);
|
|
||||||
xfs_iunlock(qip, XFS_ILOCK_SHARED);
|
xfs_iunlock(qip, XFS_ILOCK_SHARED);
|
||||||
if (error)
|
if (error)
|
||||||
break;
|
break;
|
||||||
@ -1683,7 +1681,7 @@ xfs_qm_quotacheck(
|
|||||||
* quotacheck'd stamp on the superblock. So, here we do a synchronous
|
* quotacheck'd stamp on the superblock. So, here we do a synchronous
|
||||||
* flush.
|
* flush.
|
||||||
*/
|
*/
|
||||||
XFS_bflush(mp->m_ddev_targp);
|
xfs_flush_buftarg(mp->m_ddev_targp, 1);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If one type of quotas is off, then it will lose its
|
* If one type of quotas is off, then it will lose its
|
||||||
|
@ -261,7 +261,7 @@ xfs_qm_scall_trunc_qfile(
|
|||||||
}
|
}
|
||||||
|
|
||||||
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
||||||
xfs_trans_ijoin(tp, ip);
|
xfs_trans_ijoin(tp, ip, 0);
|
||||||
|
|
||||||
error = xfs_itruncate_data(&tp, ip, 0);
|
error = xfs_itruncate_data(&tp, ip, 0);
|
||||||
if (error) {
|
if (error) {
|
||||||
|
@ -170,12 +170,12 @@ xfs_rename(
|
|||||||
* we can rely on either trans_commit or trans_cancel to unlock
|
* we can rely on either trans_commit or trans_cancel to unlock
|
||||||
* them.
|
* them.
|
||||||
*/
|
*/
|
||||||
xfs_trans_ijoin_ref(tp, src_dp, XFS_ILOCK_EXCL);
|
xfs_trans_ijoin(tp, src_dp, XFS_ILOCK_EXCL);
|
||||||
if (new_parent)
|
if (new_parent)
|
||||||
xfs_trans_ijoin_ref(tp, target_dp, XFS_ILOCK_EXCL);
|
xfs_trans_ijoin(tp, target_dp, XFS_ILOCK_EXCL);
|
||||||
xfs_trans_ijoin_ref(tp, src_ip, XFS_ILOCK_EXCL);
|
xfs_trans_ijoin(tp, src_ip, XFS_ILOCK_EXCL);
|
||||||
if (target_ip)
|
if (target_ip)
|
||||||
xfs_trans_ijoin_ref(tp, target_ip, XFS_ILOCK_EXCL);
|
xfs_trans_ijoin(tp, target_ip, XFS_ILOCK_EXCL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we are using project inheritance, we only allow renames
|
* If we are using project inheritance, we only allow renames
|
||||||
|
@ -112,7 +112,7 @@ xfs_growfs_rt_alloc(
|
|||||||
* Lock the inode.
|
* Lock the inode.
|
||||||
*/
|
*/
|
||||||
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
||||||
xfs_trans_ijoin_ref(tp, ip, XFS_ILOCK_EXCL);
|
xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
|
||||||
|
|
||||||
xfs_bmap_init(&flist, &firstblock);
|
xfs_bmap_init(&flist, &firstblock);
|
||||||
/*
|
/*
|
||||||
@ -120,9 +120,9 @@ xfs_growfs_rt_alloc(
|
|||||||
*/
|
*/
|
||||||
nmap = 1;
|
nmap = 1;
|
||||||
cancelflags |= XFS_TRANS_ABORT;
|
cancelflags |= XFS_TRANS_ABORT;
|
||||||
error = xfs_bmapi(tp, ip, oblocks, nblocks - oblocks,
|
error = xfs_bmapi_write(tp, ip, oblocks, nblocks - oblocks,
|
||||||
XFS_BMAPI_WRITE | XFS_BMAPI_METADATA, &firstblock,
|
XFS_BMAPI_METADATA, &firstblock,
|
||||||
resblks, &map, &nmap, &flist);
|
resblks, &map, &nmap, &flist);
|
||||||
if (!error && nmap < 1)
|
if (!error && nmap < 1)
|
||||||
error = XFS_ERROR(ENOSPC);
|
error = XFS_ERROR(ENOSPC);
|
||||||
if (error)
|
if (error)
|
||||||
@ -155,7 +155,7 @@ xfs_growfs_rt_alloc(
|
|||||||
* Lock the bitmap inode.
|
* Lock the bitmap inode.
|
||||||
*/
|
*/
|
||||||
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
||||||
xfs_trans_ijoin_ref(tp, ip, XFS_ILOCK_EXCL);
|
xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
|
||||||
/*
|
/*
|
||||||
* Get a buffer for the block.
|
* Get a buffer for the block.
|
||||||
*/
|
*/
|
||||||
@ -856,33 +856,23 @@ xfs_rtbuf_get(
|
|||||||
xfs_buf_t **bpp) /* output: buffer for the block */
|
xfs_buf_t **bpp) /* output: buffer for the block */
|
||||||
{
|
{
|
||||||
xfs_buf_t *bp; /* block buffer, result */
|
xfs_buf_t *bp; /* block buffer, result */
|
||||||
xfs_daddr_t d; /* disk addr of block */
|
|
||||||
int error; /* error value */
|
|
||||||
xfs_fsblock_t fsb; /* fs block number for block */
|
|
||||||
xfs_inode_t *ip; /* bitmap or summary inode */
|
xfs_inode_t *ip; /* bitmap or summary inode */
|
||||||
|
xfs_bmbt_irec_t map;
|
||||||
|
int nmap;
|
||||||
|
int error; /* error value */
|
||||||
|
|
||||||
ip = issum ? mp->m_rsumip : mp->m_rbmip;
|
ip = issum ? mp->m_rsumip : mp->m_rbmip;
|
||||||
/*
|
|
||||||
* Map from the file offset (block) and inode number to the
|
error = xfs_bmapi_read(ip, block, 1, &map, &nmap, XFS_DATA_FORK);
|
||||||
* file system block.
|
if (error)
|
||||||
*/
|
|
||||||
error = xfs_bmapi_single(tp, ip, XFS_DATA_FORK, &fsb, block);
|
|
||||||
if (error) {
|
|
||||||
return error;
|
return error;
|
||||||
}
|
|
||||||
ASSERT(fsb != NULLFSBLOCK);
|
ASSERT(map.br_startblock != NULLFSBLOCK);
|
||||||
/*
|
error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
|
||||||
* Convert to disk address for buffer cache.
|
XFS_FSB_TO_DADDR(mp, map.br_startblock),
|
||||||
*/
|
|
||||||
d = XFS_FSB_TO_DADDR(mp, fsb);
|
|
||||||
/*
|
|
||||||
* Read the buffer.
|
|
||||||
*/
|
|
||||||
error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, d,
|
|
||||||
mp->m_bsize, 0, &bp);
|
mp->m_bsize, 0, &bp);
|
||||||
if (error) {
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
}
|
|
||||||
ASSERT(!xfs_buf_geterror(bp));
|
ASSERT(!xfs_buf_geterror(bp));
|
||||||
*bpp = bp;
|
*bpp = bp;
|
||||||
return 0;
|
return 0;
|
||||||
@ -1970,7 +1960,7 @@ xfs_growfs_rt(
|
|||||||
* Lock out other callers by grabbing the bitmap inode lock.
|
* Lock out other callers by grabbing the bitmap inode lock.
|
||||||
*/
|
*/
|
||||||
xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL);
|
xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL);
|
||||||
xfs_trans_ijoin_ref(tp, mp->m_rbmip, XFS_ILOCK_EXCL);
|
xfs_trans_ijoin(tp, mp->m_rbmip, XFS_ILOCK_EXCL);
|
||||||
/*
|
/*
|
||||||
* Update the bitmap inode's size.
|
* Update the bitmap inode's size.
|
||||||
*/
|
*/
|
||||||
@ -1982,7 +1972,7 @@ xfs_growfs_rt(
|
|||||||
* Get the summary inode into the transaction.
|
* Get the summary inode into the transaction.
|
||||||
*/
|
*/
|
||||||
xfs_ilock(mp->m_rsumip, XFS_ILOCK_EXCL);
|
xfs_ilock(mp->m_rsumip, XFS_ILOCK_EXCL);
|
||||||
xfs_trans_ijoin_ref(tp, mp->m_rsumip, XFS_ILOCK_EXCL);
|
xfs_trans_ijoin(tp, mp->m_rsumip, XFS_ILOCK_EXCL);
|
||||||
/*
|
/*
|
||||||
* Update the summary inode's size.
|
* Update the summary inode's size.
|
||||||
*/
|
*/
|
||||||
@ -2153,7 +2143,7 @@ xfs_rtfree_extent(
|
|||||||
* Synchronize by locking the bitmap inode.
|
* Synchronize by locking the bitmap inode.
|
||||||
*/
|
*/
|
||||||
xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL);
|
xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL);
|
||||||
xfs_trans_ijoin_ref(tp, mp->m_rbmip, XFS_ILOCK_EXCL);
|
xfs_trans_ijoin(tp, mp->m_rbmip, XFS_ILOCK_EXCL);
|
||||||
|
|
||||||
#if defined(__KERNEL__) && defined(DEBUG)
|
#if defined(__KERNEL__) && defined(DEBUG)
|
||||||
/*
|
/*
|
||||||
|
@ -91,24 +91,6 @@ xfs_do_force_shutdown(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Prints out an ALERT message about I/O error.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
xfs_ioerror_alert(
|
|
||||||
char *func,
|
|
||||||
struct xfs_mount *mp,
|
|
||||||
xfs_buf_t *bp,
|
|
||||||
xfs_daddr_t blkno)
|
|
||||||
{
|
|
||||||
xfs_alert(mp,
|
|
||||||
"I/O error occurred: meta-data dev %s block 0x%llx"
|
|
||||||
" (\"%s\") error %d buf count %zd",
|
|
||||||
xfs_buf_target_name(bp->b_target),
|
|
||||||
(__uint64_t)blkno, func,
|
|
||||||
bp->b_error, XFS_BUF_COUNT(bp));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This isn't an absolute requirement, but it is
|
* This isn't an absolute requirement, but it is
|
||||||
* just a good idea to call xfs_read_buf instead of
|
* just a good idea to call xfs_read_buf instead of
|
||||||
@ -143,14 +125,13 @@ xfs_read_buf(
|
|||||||
} else {
|
} else {
|
||||||
*bpp = NULL;
|
*bpp = NULL;
|
||||||
if (error) {
|
if (error) {
|
||||||
xfs_ioerror_alert("xfs_read_buf", mp, bp, XFS_BUF_ADDR(bp));
|
xfs_buf_ioerror_alert(bp, __func__);
|
||||||
} else {
|
} else {
|
||||||
error = XFS_ERROR(EIO);
|
error = XFS_ERROR(EIO);
|
||||||
}
|
}
|
||||||
if (bp) {
|
if (bp) {
|
||||||
XFS_BUF_UNDONE(bp);
|
XFS_BUF_UNDONE(bp);
|
||||||
XFS_BUF_UNDELAYWRITE(bp);
|
xfs_buf_stale(bp);
|
||||||
XFS_BUF_STALE(bp);
|
|
||||||
/*
|
/*
|
||||||
* brelse clears B_ERROR and b_error
|
* brelse clears B_ERROR and b_error
|
||||||
*/
|
*/
|
||||||
|
@ -42,8 +42,6 @@ xfs_fsb_to_db(struct xfs_inode *ip, xfs_fsblock_t fsb)
|
|||||||
extern int xfs_read_buf(struct xfs_mount *mp, xfs_buftarg_t *btp,
|
extern int xfs_read_buf(struct xfs_mount *mp, xfs_buftarg_t *btp,
|
||||||
xfs_daddr_t blkno, int len, uint flags,
|
xfs_daddr_t blkno, int len, uint flags,
|
||||||
struct xfs_buf **bpp);
|
struct xfs_buf **bpp);
|
||||||
extern void xfs_ioerror_alert(char *func, struct xfs_mount *mp,
|
|
||||||
xfs_buf_t *bp, xfs_daddr_t blkno);
|
|
||||||
extern xfs_extlen_t xfs_get_extsz_hint(struct xfs_inode *ip);
|
extern xfs_extlen_t xfs_get_extsz_hint(struct xfs_inode *ip);
|
||||||
|
|
||||||
#endif /* __XFS_RW_H__ */
|
#endif /* __XFS_RW_H__ */
|
||||||
|
@ -796,8 +796,6 @@ xfs_fs_destroy_inode(
|
|||||||
if (is_bad_inode(inode))
|
if (is_bad_inode(inode))
|
||||||
goto out_reclaim;
|
goto out_reclaim;
|
||||||
|
|
||||||
xfs_ioend_wait(ip);
|
|
||||||
|
|
||||||
ASSERT(XFS_FORCED_SHUTDOWN(ip->i_mount) || ip->i_delayed_blks == 0);
|
ASSERT(XFS_FORCED_SHUTDOWN(ip->i_mount) || ip->i_delayed_blks == 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -837,7 +835,6 @@ xfs_fs_inode_init_once(
|
|||||||
inode_init_once(VFS_I(ip));
|
inode_init_once(VFS_I(ip));
|
||||||
|
|
||||||
/* xfs inode */
|
/* xfs inode */
|
||||||
atomic_set(&ip->i_iocount, 0);
|
|
||||||
atomic_set(&ip->i_pincount, 0);
|
atomic_set(&ip->i_pincount, 0);
|
||||||
spin_lock_init(&ip->i_flags_lock);
|
spin_lock_init(&ip->i_flags_lock);
|
||||||
init_waitqueue_head(&ip->i_ipin_wait);
|
init_waitqueue_head(&ip->i_ipin_wait);
|
||||||
@ -887,7 +884,7 @@ xfs_log_inode(
|
|||||||
}
|
}
|
||||||
|
|
||||||
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
||||||
xfs_trans_ijoin_ref(tp, ip, XFS_ILOCK_EXCL);
|
xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
|
||||||
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
|
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
|
||||||
return xfs_trans_commit(tp, 0);
|
return xfs_trans_commit(tp, 0);
|
||||||
}
|
}
|
||||||
@ -914,9 +911,8 @@ xfs_fs_write_inode(
|
|||||||
* of forcing it all the way to stable storage using a
|
* of forcing it all the way to stable storage using a
|
||||||
* synchronous transaction we let the log force inside the
|
* synchronous transaction we let the log force inside the
|
||||||
* ->sync_fs call do that for thus, which reduces the number
|
* ->sync_fs call do that for thus, which reduces the number
|
||||||
* of synchronous log foces dramatically.
|
* of synchronous log forces dramatically.
|
||||||
*/
|
*/
|
||||||
xfs_ioend_wait(ip);
|
|
||||||
error = xfs_log_inode(ip);
|
error = xfs_log_inode(ip);
|
||||||
if (error)
|
if (error)
|
||||||
goto out;
|
goto out;
|
||||||
@ -1019,7 +1015,7 @@ xfs_fs_put_super(
|
|||||||
*/
|
*/
|
||||||
xfs_filestream_unmount(mp);
|
xfs_filestream_unmount(mp);
|
||||||
|
|
||||||
XFS_bflush(mp->m_ddev_targp);
|
xfs_flush_buftarg(mp->m_ddev_targp, 1);
|
||||||
|
|
||||||
xfs_unmountfs(mp);
|
xfs_unmountfs(mp);
|
||||||
xfs_freesb(mp);
|
xfs_freesb(mp);
|
||||||
@ -1443,7 +1439,7 @@ xfs_fs_fill_super(
|
|||||||
*/
|
*/
|
||||||
xfs_filestream_unmount(mp);
|
xfs_filestream_unmount(mp);
|
||||||
|
|
||||||
XFS_bflush(mp->m_ddev_targp);
|
xfs_flush_buftarg(mp->m_ddev_targp, 1);
|
||||||
|
|
||||||
xfs_unmountfs(mp);
|
xfs_unmountfs(mp);
|
||||||
goto out_free_sb;
|
goto out_free_sb;
|
||||||
@ -1670,7 +1666,6 @@ init_xfs_fs(void)
|
|||||||
printk(KERN_INFO XFS_VERSION_STRING " with "
|
printk(KERN_INFO XFS_VERSION_STRING " with "
|
||||||
XFS_BUILD_OPTIONS " enabled\n");
|
XFS_BUILD_OPTIONS " enabled\n");
|
||||||
|
|
||||||
xfs_ioend_init();
|
|
||||||
xfs_dir_startup();
|
xfs_dir_startup();
|
||||||
|
|
||||||
error = xfs_init_zones();
|
error = xfs_init_zones();
|
||||||
|
@ -227,21 +227,17 @@ xfs_sync_inode_data(
|
|||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
if (!mapping_tagged(mapping, PAGECACHE_TAG_DIRTY))
|
if (!mapping_tagged(mapping, PAGECACHE_TAG_DIRTY))
|
||||||
goto out_wait;
|
return 0;
|
||||||
|
|
||||||
if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED)) {
|
if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED)) {
|
||||||
if (flags & SYNC_TRYLOCK)
|
if (flags & SYNC_TRYLOCK)
|
||||||
goto out_wait;
|
return 0;
|
||||||
xfs_ilock(ip, XFS_IOLOCK_SHARED);
|
xfs_ilock(ip, XFS_IOLOCK_SHARED);
|
||||||
}
|
}
|
||||||
|
|
||||||
error = xfs_flush_pages(ip, 0, -1, (flags & SYNC_WAIT) ?
|
error = xfs_flush_pages(ip, 0, -1, (flags & SYNC_WAIT) ?
|
||||||
0 : XBF_ASYNC, FI_NONE);
|
0 : XBF_ASYNC, FI_NONE);
|
||||||
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
|
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
|
||||||
|
|
||||||
out_wait:
|
|
||||||
if (flags & SYNC_WAIT)
|
|
||||||
xfs_ioend_wait(ip);
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -322,6 +318,7 @@ xfs_sync_fsdata(
|
|||||||
struct xfs_mount *mp)
|
struct xfs_mount *mp)
|
||||||
{
|
{
|
||||||
struct xfs_buf *bp;
|
struct xfs_buf *bp;
|
||||||
|
int error;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the buffer is pinned then push on the log so we won't get stuck
|
* If the buffer is pinned then push on the log so we won't get stuck
|
||||||
@ -334,8 +331,9 @@ xfs_sync_fsdata(
|
|||||||
bp = xfs_getsb(mp, 0);
|
bp = xfs_getsb(mp, 0);
|
||||||
if (xfs_buf_ispinned(bp))
|
if (xfs_buf_ispinned(bp))
|
||||||
xfs_log_force(mp, 0);
|
xfs_log_force(mp, 0);
|
||||||
|
error = xfs_bwrite(bp);
|
||||||
return xfs_bwrite(mp, bp);
|
xfs_buf_relse(bp);
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -379,7 +377,7 @@ xfs_quiesce_data(
|
|||||||
|
|
||||||
/* flush data-only devices */
|
/* flush data-only devices */
|
||||||
if (mp->m_rtdev_targp)
|
if (mp->m_rtdev_targp)
|
||||||
XFS_bflush(mp->m_rtdev_targp);
|
xfs_flush_buftarg(mp->m_rtdev_targp, 1);
|
||||||
|
|
||||||
return error ? error : error2;
|
return error ? error : error2;
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,7 @@ struct xfs_buf_log_item;
|
|||||||
struct xfs_da_args;
|
struct xfs_da_args;
|
||||||
struct xfs_da_node_entry;
|
struct xfs_da_node_entry;
|
||||||
struct xfs_dquot;
|
struct xfs_dquot;
|
||||||
|
struct xfs_log_item;
|
||||||
struct xlog_ticket;
|
struct xlog_ticket;
|
||||||
struct log;
|
struct log;
|
||||||
struct xlog_recover;
|
struct xlog_recover;
|
||||||
@ -320,7 +321,6 @@ DEFINE_BUF_EVENT(xfs_buf_rele);
|
|||||||
DEFINE_BUF_EVENT(xfs_buf_iodone);
|
DEFINE_BUF_EVENT(xfs_buf_iodone);
|
||||||
DEFINE_BUF_EVENT(xfs_buf_iorequest);
|
DEFINE_BUF_EVENT(xfs_buf_iorequest);
|
||||||
DEFINE_BUF_EVENT(xfs_buf_bawrite);
|
DEFINE_BUF_EVENT(xfs_buf_bawrite);
|
||||||
DEFINE_BUF_EVENT(xfs_buf_bdwrite);
|
|
||||||
DEFINE_BUF_EVENT(xfs_buf_lock);
|
DEFINE_BUF_EVENT(xfs_buf_lock);
|
||||||
DEFINE_BUF_EVENT(xfs_buf_lock_done);
|
DEFINE_BUF_EVENT(xfs_buf_lock_done);
|
||||||
DEFINE_BUF_EVENT(xfs_buf_trylock);
|
DEFINE_BUF_EVENT(xfs_buf_trylock);
|
||||||
@ -577,6 +577,7 @@ DEFINE_INODE_EVENT(xfs_vm_bmap);
|
|||||||
DEFINE_INODE_EVENT(xfs_file_ioctl);
|
DEFINE_INODE_EVENT(xfs_file_ioctl);
|
||||||
DEFINE_INODE_EVENT(xfs_file_compat_ioctl);
|
DEFINE_INODE_EVENT(xfs_file_compat_ioctl);
|
||||||
DEFINE_INODE_EVENT(xfs_ioctl_setattr);
|
DEFINE_INODE_EVENT(xfs_ioctl_setattr);
|
||||||
|
DEFINE_INODE_EVENT(xfs_dir_fsync);
|
||||||
DEFINE_INODE_EVENT(xfs_file_fsync);
|
DEFINE_INODE_EVENT(xfs_file_fsync);
|
||||||
DEFINE_INODE_EVENT(xfs_destroy_inode);
|
DEFINE_INODE_EVENT(xfs_destroy_inode);
|
||||||
DEFINE_INODE_EVENT(xfs_write_inode);
|
DEFINE_INODE_EVENT(xfs_write_inode);
|
||||||
@ -853,6 +854,42 @@ DEFINE_LOGGRANT_EVENT(xfs_log_ungrant_enter);
|
|||||||
DEFINE_LOGGRANT_EVENT(xfs_log_ungrant_exit);
|
DEFINE_LOGGRANT_EVENT(xfs_log_ungrant_exit);
|
||||||
DEFINE_LOGGRANT_EVENT(xfs_log_ungrant_sub);
|
DEFINE_LOGGRANT_EVENT(xfs_log_ungrant_sub);
|
||||||
|
|
||||||
|
DECLARE_EVENT_CLASS(xfs_log_item_class,
|
||||||
|
TP_PROTO(struct xfs_log_item *lip),
|
||||||
|
TP_ARGS(lip),
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__field(dev_t, dev)
|
||||||
|
__field(void *, lip)
|
||||||
|
__field(uint, type)
|
||||||
|
__field(uint, flags)
|
||||||
|
__field(xfs_lsn_t, lsn)
|
||||||
|
),
|
||||||
|
TP_fast_assign(
|
||||||
|
__entry->dev = lip->li_mountp->m_super->s_dev;
|
||||||
|
__entry->lip = lip;
|
||||||
|
__entry->type = lip->li_type;
|
||||||
|
__entry->flags = lip->li_flags;
|
||||||
|
__entry->lsn = lip->li_lsn;
|
||||||
|
),
|
||||||
|
TP_printk("dev %d:%d lip 0x%p lsn %d/%d type %s flags %s",
|
||||||
|
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||||
|
__entry->lip,
|
||||||
|
CYCLE_LSN(__entry->lsn), BLOCK_LSN(__entry->lsn),
|
||||||
|
__print_symbolic(__entry->type, XFS_LI_TYPE_DESC),
|
||||||
|
__print_flags(__entry->flags, "|", XFS_LI_FLAGS))
|
||||||
|
)
|
||||||
|
|
||||||
|
#define DEFINE_LOG_ITEM_EVENT(name) \
|
||||||
|
DEFINE_EVENT(xfs_log_item_class, name, \
|
||||||
|
TP_PROTO(struct xfs_log_item *lip), \
|
||||||
|
TP_ARGS(lip))
|
||||||
|
DEFINE_LOG_ITEM_EVENT(xfs_ail_push);
|
||||||
|
DEFINE_LOG_ITEM_EVENT(xfs_ail_pushbuf);
|
||||||
|
DEFINE_LOG_ITEM_EVENT(xfs_ail_pushbuf_pinned);
|
||||||
|
DEFINE_LOG_ITEM_EVENT(xfs_ail_pinned);
|
||||||
|
DEFINE_LOG_ITEM_EVENT(xfs_ail_locked);
|
||||||
|
|
||||||
|
|
||||||
DECLARE_EVENT_CLASS(xfs_file_class,
|
DECLARE_EVENT_CLASS(xfs_file_class,
|
||||||
TP_PROTO(struct xfs_inode *ip, size_t count, loff_t offset, int flags),
|
TP_PROTO(struct xfs_inode *ip, size_t count, loff_t offset, int flags),
|
||||||
TP_ARGS(ip, count, offset, flags),
|
TP_ARGS(ip, count, offset, flags),
|
||||||
|
@ -1790,9 +1790,7 @@ xfs_trans_commit_cil(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* xfs_trans_commit
|
* Commit the given transaction to the log.
|
||||||
*
|
|
||||||
* Commit the given transaction to the log a/synchronously.
|
|
||||||
*
|
*
|
||||||
* XFS disk error handling mechanism is not based on a typical
|
* XFS disk error handling mechanism is not based on a typical
|
||||||
* transaction abort mechanism. Logically after the filesystem
|
* transaction abort mechanism. Logically after the filesystem
|
||||||
@ -1804,10 +1802,9 @@ xfs_trans_commit_cil(
|
|||||||
* Do not reference the transaction structure after this call.
|
* Do not reference the transaction structure after this call.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
_xfs_trans_commit(
|
xfs_trans_commit(
|
||||||
struct xfs_trans *tp,
|
struct xfs_trans *tp,
|
||||||
uint flags,
|
uint flags)
|
||||||
int *log_flushed)
|
|
||||||
{
|
{
|
||||||
struct xfs_mount *mp = tp->t_mountp;
|
struct xfs_mount *mp = tp->t_mountp;
|
||||||
xfs_lsn_t commit_lsn = -1;
|
xfs_lsn_t commit_lsn = -1;
|
||||||
@ -1866,7 +1863,7 @@ _xfs_trans_commit(
|
|||||||
if (sync) {
|
if (sync) {
|
||||||
if (!error) {
|
if (!error) {
|
||||||
error = _xfs_log_force_lsn(mp, commit_lsn,
|
error = _xfs_log_force_lsn(mp, commit_lsn,
|
||||||
XFS_LOG_SYNC, log_flushed);
|
XFS_LOG_SYNC, NULL);
|
||||||
}
|
}
|
||||||
XFS_STATS_INC(xs_trans_sync);
|
XFS_STATS_INC(xs_trans_sync);
|
||||||
} else {
|
} else {
|
||||||
@ -2021,6 +2018,6 @@ xfs_trans_roll(
|
|||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
xfs_trans_ijoin(trans, dp);
|
xfs_trans_ijoin(trans, dp, 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -470,8 +470,7 @@ void xfs_trans_stale_inode_buf(xfs_trans_t *, struct xfs_buf *);
|
|||||||
void xfs_trans_dquot_buf(xfs_trans_t *, struct xfs_buf *, uint);
|
void xfs_trans_dquot_buf(xfs_trans_t *, struct xfs_buf *, uint);
|
||||||
void xfs_trans_inode_alloc_buf(xfs_trans_t *, struct xfs_buf *);
|
void xfs_trans_inode_alloc_buf(xfs_trans_t *, struct xfs_buf *);
|
||||||
void xfs_trans_ichgtime(struct xfs_trans *, struct xfs_inode *, int);
|
void xfs_trans_ichgtime(struct xfs_trans *, struct xfs_inode *, int);
|
||||||
void xfs_trans_ijoin_ref(struct xfs_trans *, struct xfs_inode *, uint);
|
void xfs_trans_ijoin(struct xfs_trans *, struct xfs_inode *, uint);
|
||||||
void xfs_trans_ijoin(struct xfs_trans *, struct xfs_inode *);
|
|
||||||
void xfs_trans_log_buf(xfs_trans_t *, struct xfs_buf *, uint, uint);
|
void xfs_trans_log_buf(xfs_trans_t *, struct xfs_buf *, uint, uint);
|
||||||
void xfs_trans_log_inode(xfs_trans_t *, struct xfs_inode *, uint);
|
void xfs_trans_log_inode(xfs_trans_t *, struct xfs_inode *, uint);
|
||||||
struct xfs_efi_log_item *xfs_trans_get_efi(xfs_trans_t *, uint);
|
struct xfs_efi_log_item *xfs_trans_get_efi(xfs_trans_t *, uint);
|
||||||
@ -487,10 +486,7 @@ void xfs_trans_log_efd_extent(xfs_trans_t *,
|
|||||||
struct xfs_efd_log_item *,
|
struct xfs_efd_log_item *,
|
||||||
xfs_fsblock_t,
|
xfs_fsblock_t,
|
||||||
xfs_extlen_t);
|
xfs_extlen_t);
|
||||||
int _xfs_trans_commit(xfs_trans_t *,
|
int xfs_trans_commit(xfs_trans_t *, uint flags);
|
||||||
uint flags,
|
|
||||||
int *);
|
|
||||||
#define xfs_trans_commit(tp, flags) _xfs_trans_commit(tp, flags, NULL)
|
|
||||||
void xfs_trans_cancel(xfs_trans_t *, int);
|
void xfs_trans_cancel(xfs_trans_t *, int);
|
||||||
int xfs_trans_ail_init(struct xfs_mount *);
|
int xfs_trans_ail_init(struct xfs_mount *);
|
||||||
void xfs_trans_ail_destroy(struct xfs_mount *);
|
void xfs_trans_ail_destroy(struct xfs_mount *);
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "xfs_ag.h"
|
#include "xfs_ag.h"
|
||||||
#include "xfs_mount.h"
|
#include "xfs_mount.h"
|
||||||
#include "xfs_trans_priv.h"
|
#include "xfs_trans_priv.h"
|
||||||
|
#include "xfs_trace.h"
|
||||||
#include "xfs_error.h"
|
#include "xfs_error.h"
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
@ -364,12 +365,24 @@ xfsaild_push(
|
|||||||
xfs_lsn_t lsn;
|
xfs_lsn_t lsn;
|
||||||
xfs_lsn_t target;
|
xfs_lsn_t target;
|
||||||
long tout = 10;
|
long tout = 10;
|
||||||
int flush_log = 0;
|
|
||||||
int stuck = 0;
|
int stuck = 0;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
int push_xfsbufd = 0;
|
int push_xfsbufd = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If last time we ran we encountered pinned items, force the log first
|
||||||
|
* and wait for it before pushing again.
|
||||||
|
*/
|
||||||
spin_lock(&ailp->xa_lock);
|
spin_lock(&ailp->xa_lock);
|
||||||
|
if (ailp->xa_last_pushed_lsn == 0 && ailp->xa_log_flush &&
|
||||||
|
!list_empty(&ailp->xa_ail)) {
|
||||||
|
ailp->xa_log_flush = 0;
|
||||||
|
spin_unlock(&ailp->xa_lock);
|
||||||
|
XFS_STATS_INC(xs_push_ail_flush);
|
||||||
|
xfs_log_force(mp, XFS_LOG_SYNC);
|
||||||
|
spin_lock(&ailp->xa_lock);
|
||||||
|
}
|
||||||
|
|
||||||
target = ailp->xa_target;
|
target = ailp->xa_target;
|
||||||
lip = xfs_trans_ail_cursor_first(ailp, &cur, ailp->xa_last_pushed_lsn);
|
lip = xfs_trans_ail_cursor_first(ailp, &cur, ailp->xa_last_pushed_lsn);
|
||||||
if (!lip || XFS_FORCED_SHUTDOWN(mp)) {
|
if (!lip || XFS_FORCED_SHUTDOWN(mp)) {
|
||||||
@ -413,16 +426,20 @@ xfsaild_push(
|
|||||||
switch (lock_result) {
|
switch (lock_result) {
|
||||||
case XFS_ITEM_SUCCESS:
|
case XFS_ITEM_SUCCESS:
|
||||||
XFS_STATS_INC(xs_push_ail_success);
|
XFS_STATS_INC(xs_push_ail_success);
|
||||||
|
trace_xfs_ail_push(lip);
|
||||||
|
|
||||||
IOP_PUSH(lip);
|
IOP_PUSH(lip);
|
||||||
ailp->xa_last_pushed_lsn = lsn;
|
ailp->xa_last_pushed_lsn = lsn;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XFS_ITEM_PUSHBUF:
|
case XFS_ITEM_PUSHBUF:
|
||||||
XFS_STATS_INC(xs_push_ail_pushbuf);
|
XFS_STATS_INC(xs_push_ail_pushbuf);
|
||||||
|
trace_xfs_ail_pushbuf(lip);
|
||||||
|
|
||||||
if (!IOP_PUSHBUF(lip)) {
|
if (!IOP_PUSHBUF(lip)) {
|
||||||
|
trace_xfs_ail_pushbuf_pinned(lip);
|
||||||
stuck++;
|
stuck++;
|
||||||
flush_log = 1;
|
ailp->xa_log_flush++;
|
||||||
} else {
|
} else {
|
||||||
ailp->xa_last_pushed_lsn = lsn;
|
ailp->xa_last_pushed_lsn = lsn;
|
||||||
}
|
}
|
||||||
@ -431,12 +448,15 @@ xfsaild_push(
|
|||||||
|
|
||||||
case XFS_ITEM_PINNED:
|
case XFS_ITEM_PINNED:
|
||||||
XFS_STATS_INC(xs_push_ail_pinned);
|
XFS_STATS_INC(xs_push_ail_pinned);
|
||||||
|
trace_xfs_ail_pinned(lip);
|
||||||
|
|
||||||
stuck++;
|
stuck++;
|
||||||
flush_log = 1;
|
ailp->xa_log_flush++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XFS_ITEM_LOCKED:
|
case XFS_ITEM_LOCKED:
|
||||||
XFS_STATS_INC(xs_push_ail_locked);
|
XFS_STATS_INC(xs_push_ail_locked);
|
||||||
|
trace_xfs_ail_locked(lip);
|
||||||
stuck++;
|
stuck++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -476,16 +496,6 @@ xfsaild_push(
|
|||||||
xfs_trans_ail_cursor_done(ailp, &cur);
|
xfs_trans_ail_cursor_done(ailp, &cur);
|
||||||
spin_unlock(&ailp->xa_lock);
|
spin_unlock(&ailp->xa_lock);
|
||||||
|
|
||||||
if (flush_log) {
|
|
||||||
/*
|
|
||||||
* If something we need to push out was pinned, then
|
|
||||||
* push out the log so it will become unpinned and
|
|
||||||
* move forward in the AIL.
|
|
||||||
*/
|
|
||||||
XFS_STATS_INC(xs_push_ail_flush);
|
|
||||||
xfs_log_force(mp, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (push_xfsbufd) {
|
if (push_xfsbufd) {
|
||||||
/* we've got delayed write buffers to flush */
|
/* we've got delayed write buffers to flush */
|
||||||
wake_up_process(mp->m_ddev_targp->bt_task);
|
wake_up_process(mp->m_ddev_targp->bt_task);
|
||||||
@ -496,6 +506,7 @@ out_done:
|
|||||||
if (!count) {
|
if (!count) {
|
||||||
/* We're past our target or empty, so idle */
|
/* We're past our target or empty, so idle */
|
||||||
ailp->xa_last_pushed_lsn = 0;
|
ailp->xa_last_pushed_lsn = 0;
|
||||||
|
ailp->xa_log_flush = 0;
|
||||||
|
|
||||||
tout = 50;
|
tout = 50;
|
||||||
} else if (XFS_LSN_CMP(lsn, target) >= 0) {
|
} else if (XFS_LSN_CMP(lsn, target) >= 0) {
|
||||||
@ -514,9 +525,13 @@ out_done:
|
|||||||
* were stuck.
|
* were stuck.
|
||||||
*
|
*
|
||||||
* Backoff a bit more to allow some I/O to complete before
|
* Backoff a bit more to allow some I/O to complete before
|
||||||
* continuing from where we were.
|
* restarting from the start of the AIL. This prevents us
|
||||||
|
* from spinning on the same items, and if they are pinned will
|
||||||
|
* all the restart to issue a log force to unpin the stuck
|
||||||
|
* items.
|
||||||
*/
|
*/
|
||||||
tout = 20;
|
tout = 20;
|
||||||
|
ailp->xa_last_pushed_lsn = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return tout;
|
return tout;
|
||||||
|
@ -160,8 +160,10 @@ xfs_trans_get_buf(xfs_trans_t *tp,
|
|||||||
bp = xfs_trans_buf_item_match(tp, target_dev, blkno, len);
|
bp = xfs_trans_buf_item_match(tp, target_dev, blkno, len);
|
||||||
if (bp != NULL) {
|
if (bp != NULL) {
|
||||||
ASSERT(xfs_buf_islocked(bp));
|
ASSERT(xfs_buf_islocked(bp));
|
||||||
if (XFS_FORCED_SHUTDOWN(tp->t_mountp))
|
if (XFS_FORCED_SHUTDOWN(tp->t_mountp)) {
|
||||||
XFS_BUF_SUPER_STALE(bp);
|
xfs_buf_stale(bp);
|
||||||
|
XFS_BUF_DONE(bp);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the buffer is stale then it was binval'ed
|
* If the buffer is stale then it was binval'ed
|
||||||
@ -294,8 +296,7 @@ xfs_trans_read_buf(
|
|||||||
|
|
||||||
if (bp->b_error) {
|
if (bp->b_error) {
|
||||||
error = bp->b_error;
|
error = bp->b_error;
|
||||||
xfs_ioerror_alert("xfs_trans_read_buf", mp,
|
xfs_buf_ioerror_alert(bp, __func__);
|
||||||
bp, blkno);
|
|
||||||
xfs_buf_relse(bp);
|
xfs_buf_relse(bp);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
@ -337,8 +338,7 @@ xfs_trans_read_buf(
|
|||||||
xfsbdstrat(tp->t_mountp, bp);
|
xfsbdstrat(tp->t_mountp, bp);
|
||||||
error = xfs_buf_iowait(bp);
|
error = xfs_buf_iowait(bp);
|
||||||
if (error) {
|
if (error) {
|
||||||
xfs_ioerror_alert("xfs_trans_read_buf", mp,
|
xfs_buf_ioerror_alert(bp, __func__);
|
||||||
bp, blkno);
|
|
||||||
xfs_buf_relse(bp);
|
xfs_buf_relse(bp);
|
||||||
/*
|
/*
|
||||||
* We can gracefully recover from most read
|
* We can gracefully recover from most read
|
||||||
@ -387,9 +387,9 @@ xfs_trans_read_buf(
|
|||||||
}
|
}
|
||||||
if (bp->b_error) {
|
if (bp->b_error) {
|
||||||
error = bp->b_error;
|
error = bp->b_error;
|
||||||
XFS_BUF_SUPER_STALE(bp);
|
xfs_buf_stale(bp);
|
||||||
xfs_ioerror_alert("xfs_trans_read_buf", mp,
|
XFS_BUF_DONE(bp);
|
||||||
bp, blkno);
|
xfs_buf_ioerror_alert(bp, __func__);
|
||||||
if (tp->t_flags & XFS_TRANS_DIRTY)
|
if (tp->t_flags & XFS_TRANS_DIRTY)
|
||||||
xfs_force_shutdown(tp->t_mountp, SHUTDOWN_META_IO_ERROR);
|
xfs_force_shutdown(tp->t_mountp, SHUTDOWN_META_IO_ERROR);
|
||||||
xfs_buf_relse(bp);
|
xfs_buf_relse(bp);
|
||||||
@ -643,13 +643,14 @@ xfs_trans_log_buf(xfs_trans_t *tp,
|
|||||||
* inside the b_bdstrat callback so that this won't get written to
|
* inside the b_bdstrat callback so that this won't get written to
|
||||||
* disk.
|
* disk.
|
||||||
*/
|
*/
|
||||||
XFS_BUF_DELAYWRITE(bp);
|
|
||||||
XFS_BUF_DONE(bp);
|
XFS_BUF_DONE(bp);
|
||||||
|
|
||||||
ASSERT(atomic_read(&bip->bli_refcount) > 0);
|
ASSERT(atomic_read(&bip->bli_refcount) > 0);
|
||||||
bp->b_iodone = xfs_buf_iodone_callbacks;
|
bp->b_iodone = xfs_buf_iodone_callbacks;
|
||||||
bip->bli_item.li_cb = xfs_buf_iodone;
|
bip->bli_item.li_cb = xfs_buf_iodone;
|
||||||
|
|
||||||
|
xfs_buf_delwri_queue(bp);
|
||||||
|
|
||||||
trace_xfs_trans_log_buf(bip);
|
trace_xfs_trans_log_buf(bip);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -738,8 +739,7 @@ xfs_trans_binval(
|
|||||||
* We set the stale bit in the buffer as well since we're getting
|
* We set the stale bit in the buffer as well since we're getting
|
||||||
* rid of it.
|
* rid of it.
|
||||||
*/
|
*/
|
||||||
XFS_BUF_UNDELAYWRITE(bp);
|
xfs_buf_stale(bp);
|
||||||
XFS_BUF_STALE(bp);
|
|
||||||
bip->bli_flags |= XFS_BLI_STALE;
|
bip->bli_flags |= XFS_BLI_STALE;
|
||||||
bip->bli_flags &= ~(XFS_BLI_INODE_BUF | XFS_BLI_LOGGED | XFS_BLI_DIRTY);
|
bip->bli_flags &= ~(XFS_BLI_INODE_BUF | XFS_BLI_LOGGED | XFS_BLI_DIRTY);
|
||||||
bip->bli_format.blf_flags &= ~XFS_BLF_INODE_BUF;
|
bip->bli_format.blf_flags &= ~XFS_BLF_INODE_BUF;
|
||||||
|
@ -47,11 +47,13 @@ xfs_trans_inode_broot_debug(
|
|||||||
* Add a locked inode to the transaction.
|
* Add a locked inode to the transaction.
|
||||||
*
|
*
|
||||||
* The inode must be locked, and it cannot be associated with any transaction.
|
* The inode must be locked, and it cannot be associated with any transaction.
|
||||||
|
* If lock_flags is non-zero the inode will be unlocked on transaction commit.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
xfs_trans_ijoin(
|
xfs_trans_ijoin(
|
||||||
struct xfs_trans *tp,
|
struct xfs_trans *tp,
|
||||||
struct xfs_inode *ip)
|
struct xfs_inode *ip,
|
||||||
|
uint lock_flags)
|
||||||
{
|
{
|
||||||
xfs_inode_log_item_t *iip;
|
xfs_inode_log_item_t *iip;
|
||||||
|
|
||||||
@ -59,7 +61,9 @@ xfs_trans_ijoin(
|
|||||||
if (ip->i_itemp == NULL)
|
if (ip->i_itemp == NULL)
|
||||||
xfs_inode_item_init(ip, ip->i_mount);
|
xfs_inode_item_init(ip, ip->i_mount);
|
||||||
iip = ip->i_itemp;
|
iip = ip->i_itemp;
|
||||||
|
|
||||||
ASSERT(iip->ili_lock_flags == 0);
|
ASSERT(iip->ili_lock_flags == 0);
|
||||||
|
iip->ili_lock_flags = lock_flags;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get a log_item_desc to point at the new item.
|
* Get a log_item_desc to point at the new item.
|
||||||
@ -69,25 +73,6 @@ xfs_trans_ijoin(
|
|||||||
xfs_trans_inode_broot_debug(ip);
|
xfs_trans_inode_broot_debug(ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Add a locked inode to the transaction.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Grabs a reference to the inode which will be dropped when the transaction
|
|
||||||
* is committed. The inode will also be unlocked at that point. The inode
|
|
||||||
* must be locked, and it cannot be associated with any transaction.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
xfs_trans_ijoin_ref(
|
|
||||||
struct xfs_trans *tp,
|
|
||||||
struct xfs_inode *ip,
|
|
||||||
uint lock_flags)
|
|
||||||
{
|
|
||||||
xfs_trans_ijoin(tp, ip);
|
|
||||||
IHOLD(ip);
|
|
||||||
ip->i_itemp->ili_lock_flags = lock_flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Transactional inode timestamp update. Requires the inode to be locked and
|
* Transactional inode timestamp update. Requires the inode to be locked and
|
||||||
* joined to the transaction supplied. Relies on the transaction subsystem to
|
* joined to the transaction supplied. Relies on the transaction subsystem to
|
||||||
|
@ -70,6 +70,7 @@ struct xfs_ail {
|
|||||||
struct list_head xa_cursors;
|
struct list_head xa_cursors;
|
||||||
spinlock_t xa_lock;
|
spinlock_t xa_lock;
|
||||||
xfs_lsn_t xa_last_pushed_lsn;
|
xfs_lsn_t xa_last_pushed_lsn;
|
||||||
|
int xa_log_flush;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -72,8 +72,8 @@ xfs_readlink_bmap(
|
|||||||
xfs_buf_t *bp;
|
xfs_buf_t *bp;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
error = xfs_bmapi(NULL, ip, 0, XFS_B_TO_FSB(mp, pathlen), 0, NULL, 0,
|
error = xfs_bmapi_read(ip, 0, XFS_B_TO_FSB(mp, pathlen), mval, &nmaps,
|
||||||
mval, &nmaps, NULL);
|
0);
|
||||||
if (error)
|
if (error)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
@ -87,8 +87,7 @@ xfs_readlink_bmap(
|
|||||||
return XFS_ERROR(ENOMEM);
|
return XFS_ERROR(ENOMEM);
|
||||||
error = bp->b_error;
|
error = bp->b_error;
|
||||||
if (error) {
|
if (error) {
|
||||||
xfs_ioerror_alert("xfs_readlink",
|
xfs_buf_ioerror_alert(bp, __func__);
|
||||||
ip->i_mount, bp, XFS_BUF_ADDR(bp));
|
|
||||||
xfs_buf_relse(bp);
|
xfs_buf_relse(bp);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -178,8 +177,7 @@ xfs_free_eofblocks(
|
|||||||
|
|
||||||
nimaps = 1;
|
nimaps = 1;
|
||||||
xfs_ilock(ip, XFS_ILOCK_SHARED);
|
xfs_ilock(ip, XFS_ILOCK_SHARED);
|
||||||
error = xfs_bmapi(NULL, ip, end_fsb, map_len, 0,
|
error = xfs_bmapi_read(ip, end_fsb, map_len, &imap, &nimaps, 0);
|
||||||
NULL, 0, &imap, &nimaps, NULL);
|
|
||||||
xfs_iunlock(ip, XFS_ILOCK_SHARED);
|
xfs_iunlock(ip, XFS_ILOCK_SHARED);
|
||||||
|
|
||||||
if (!error && (nimaps != 0) &&
|
if (!error && (nimaps != 0) &&
|
||||||
@ -220,7 +218,7 @@ xfs_free_eofblocks(
|
|||||||
}
|
}
|
||||||
|
|
||||||
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
||||||
xfs_trans_ijoin(tp, ip);
|
xfs_trans_ijoin(tp, ip, 0);
|
||||||
|
|
||||||
error = xfs_itruncate_data(&tp, ip, ip->i_size);
|
error = xfs_itruncate_data(&tp, ip, ip->i_size);
|
||||||
if (error) {
|
if (error) {
|
||||||
@ -289,7 +287,7 @@ xfs_inactive_symlink_rmt(
|
|||||||
xfs_ilock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
|
xfs_ilock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
|
||||||
size = (int)ip->i_d.di_size;
|
size = (int)ip->i_d.di_size;
|
||||||
ip->i_d.di_size = 0;
|
ip->i_d.di_size = 0;
|
||||||
xfs_trans_ijoin(tp, ip);
|
xfs_trans_ijoin(tp, ip, 0);
|
||||||
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
|
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
|
||||||
/*
|
/*
|
||||||
* Find the block(s) so we can inval and unmap them.
|
* Find the block(s) so we can inval and unmap them.
|
||||||
@ -297,9 +295,9 @@ xfs_inactive_symlink_rmt(
|
|||||||
done = 0;
|
done = 0;
|
||||||
xfs_bmap_init(&free_list, &first_block);
|
xfs_bmap_init(&free_list, &first_block);
|
||||||
nmaps = ARRAY_SIZE(mval);
|
nmaps = ARRAY_SIZE(mval);
|
||||||
if ((error = xfs_bmapi(tp, ip, 0, XFS_B_TO_FSB(mp, size),
|
error = xfs_bmapi_read(ip, 0, XFS_B_TO_FSB(mp, size),
|
||||||
XFS_BMAPI_METADATA, &first_block, 0, mval, &nmaps,
|
mval, &nmaps, 0);
|
||||||
&free_list)))
|
if (error)
|
||||||
goto error0;
|
goto error0;
|
||||||
/*
|
/*
|
||||||
* Invalidate the block(s).
|
* Invalidate the block(s).
|
||||||
@ -308,6 +306,10 @@ xfs_inactive_symlink_rmt(
|
|||||||
bp = xfs_trans_get_buf(tp, mp->m_ddev_targp,
|
bp = xfs_trans_get_buf(tp, mp->m_ddev_targp,
|
||||||
XFS_FSB_TO_DADDR(mp, mval[i].br_startblock),
|
XFS_FSB_TO_DADDR(mp, mval[i].br_startblock),
|
||||||
XFS_FSB_TO_BB(mp, mval[i].br_blockcount), 0);
|
XFS_FSB_TO_BB(mp, mval[i].br_blockcount), 0);
|
||||||
|
if (!bp) {
|
||||||
|
error = ENOMEM;
|
||||||
|
goto error1;
|
||||||
|
}
|
||||||
xfs_trans_binval(tp, bp);
|
xfs_trans_binval(tp, bp);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@ -333,7 +335,7 @@ xfs_inactive_symlink_rmt(
|
|||||||
* Mark it dirty so it will be logged and moved forward in the log as
|
* Mark it dirty so it will be logged and moved forward in the log as
|
||||||
* part of every commit.
|
* part of every commit.
|
||||||
*/
|
*/
|
||||||
xfs_trans_ijoin(tp, ip);
|
xfs_trans_ijoin(tp, ip, 0);
|
||||||
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
|
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
|
||||||
/*
|
/*
|
||||||
* Get a new, empty transaction to return to our caller.
|
* Get a new, empty transaction to return to our caller.
|
||||||
@ -466,7 +468,7 @@ xfs_inactive_attrs(
|
|||||||
goto error_cancel;
|
goto error_cancel;
|
||||||
|
|
||||||
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
||||||
xfs_trans_ijoin(tp, ip);
|
xfs_trans_ijoin(tp, ip, 0);
|
||||||
xfs_idestroy_fork(ip, XFS_ATTR_FORK);
|
xfs_idestroy_fork(ip, XFS_ATTR_FORK);
|
||||||
|
|
||||||
ASSERT(ip->i_d.di_anextents == 0);
|
ASSERT(ip->i_d.di_anextents == 0);
|
||||||
@ -647,8 +649,6 @@ xfs_inactive(
|
|||||||
if (truncate) {
|
if (truncate) {
|
||||||
xfs_ilock(ip, XFS_IOLOCK_EXCL);
|
xfs_ilock(ip, XFS_IOLOCK_EXCL);
|
||||||
|
|
||||||
xfs_ioend_wait(ip);
|
|
||||||
|
|
||||||
error = xfs_trans_reserve(tp, 0,
|
error = xfs_trans_reserve(tp, 0,
|
||||||
XFS_ITRUNCATE_LOG_RES(mp),
|
XFS_ITRUNCATE_LOG_RES(mp),
|
||||||
0, XFS_TRANS_PERM_LOG_RES,
|
0, XFS_TRANS_PERM_LOG_RES,
|
||||||
@ -662,7 +662,7 @@ xfs_inactive(
|
|||||||
}
|
}
|
||||||
|
|
||||||
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
||||||
xfs_trans_ijoin(tp, ip);
|
xfs_trans_ijoin(tp, ip, 0);
|
||||||
|
|
||||||
error = xfs_itruncate_data(&tp, ip, 0);
|
error = xfs_itruncate_data(&tp, ip, 0);
|
||||||
if (error) {
|
if (error) {
|
||||||
@ -686,7 +686,7 @@ xfs_inactive(
|
|||||||
return VN_INACTIVE_CACHE;
|
return VN_INACTIVE_CACHE;
|
||||||
}
|
}
|
||||||
|
|
||||||
xfs_trans_ijoin(tp, ip);
|
xfs_trans_ijoin(tp, ip, 0);
|
||||||
} else {
|
} else {
|
||||||
error = xfs_trans_reserve(tp, 0,
|
error = xfs_trans_reserve(tp, 0,
|
||||||
XFS_IFREE_LOG_RES(mp),
|
XFS_IFREE_LOG_RES(mp),
|
||||||
@ -699,7 +699,7 @@ xfs_inactive(
|
|||||||
}
|
}
|
||||||
|
|
||||||
xfs_ilock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
|
xfs_ilock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
|
||||||
xfs_trans_ijoin(tp, ip);
|
xfs_trans_ijoin(tp, ip, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -939,7 +939,7 @@ xfs_create(
|
|||||||
* the transaction cancel unlocking dp so don't do it explicitly in the
|
* the transaction cancel unlocking dp so don't do it explicitly in the
|
||||||
* error path.
|
* error path.
|
||||||
*/
|
*/
|
||||||
xfs_trans_ijoin_ref(tp, dp, XFS_ILOCK_EXCL);
|
xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
|
||||||
unlock_dp_on_error = B_FALSE;
|
unlock_dp_on_error = B_FALSE;
|
||||||
|
|
||||||
error = xfs_dir_createname(tp, dp, name, ip->i_ino,
|
error = xfs_dir_createname(tp, dp, name, ip->i_ino,
|
||||||
@ -1260,8 +1260,8 @@ xfs_remove(
|
|||||||
|
|
||||||
xfs_lock_two_inodes(dp, ip, XFS_ILOCK_EXCL);
|
xfs_lock_two_inodes(dp, ip, XFS_ILOCK_EXCL);
|
||||||
|
|
||||||
xfs_trans_ijoin_ref(tp, dp, XFS_ILOCK_EXCL);
|
xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
|
||||||
xfs_trans_ijoin_ref(tp, ip, XFS_ILOCK_EXCL);
|
xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we're removing a directory perform some additional validation.
|
* If we're removing a directory perform some additional validation.
|
||||||
@ -1406,8 +1406,8 @@ xfs_link(
|
|||||||
|
|
||||||
xfs_lock_two_inodes(sip, tdp, XFS_ILOCK_EXCL);
|
xfs_lock_two_inodes(sip, tdp, XFS_ILOCK_EXCL);
|
||||||
|
|
||||||
xfs_trans_ijoin_ref(tp, sip, XFS_ILOCK_EXCL);
|
xfs_trans_ijoin(tp, sip, XFS_ILOCK_EXCL);
|
||||||
xfs_trans_ijoin_ref(tp, tdp, XFS_ILOCK_EXCL);
|
xfs_trans_ijoin(tp, tdp, XFS_ILOCK_EXCL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the source has too many links, we can't make any more to it.
|
* If the source has too many links, we can't make any more to it.
|
||||||
@ -1601,7 +1601,7 @@ xfs_symlink(
|
|||||||
* transaction cancel unlocking dp so don't do it explicitly in the
|
* transaction cancel unlocking dp so don't do it explicitly in the
|
||||||
* error path.
|
* error path.
|
||||||
*/
|
*/
|
||||||
xfs_trans_ijoin_ref(tp, dp, XFS_ILOCK_EXCL);
|
xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
|
||||||
unlock_dp_on_error = B_FALSE;
|
unlock_dp_on_error = B_FALSE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1632,10 +1632,9 @@ xfs_symlink(
|
|||||||
first_fsb = 0;
|
first_fsb = 0;
|
||||||
nmaps = SYMLINK_MAPS;
|
nmaps = SYMLINK_MAPS;
|
||||||
|
|
||||||
error = xfs_bmapi(tp, ip, first_fsb, fs_blocks,
|
error = xfs_bmapi_write(tp, ip, first_fsb, fs_blocks,
|
||||||
XFS_BMAPI_WRITE | XFS_BMAPI_METADATA,
|
XFS_BMAPI_METADATA, &first_block, resblks,
|
||||||
&first_block, resblks, mval, &nmaps,
|
mval, &nmaps, &free_list);
|
||||||
&free_list);
|
|
||||||
if (error)
|
if (error)
|
||||||
goto error2;
|
goto error2;
|
||||||
|
|
||||||
@ -1650,7 +1649,10 @@ xfs_symlink(
|
|||||||
byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount);
|
byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount);
|
||||||
bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
|
bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
|
||||||
BTOBB(byte_cnt), 0);
|
BTOBB(byte_cnt), 0);
|
||||||
ASSERT(!xfs_buf_geterror(bp));
|
if (!bp) {
|
||||||
|
error = ENOMEM;
|
||||||
|
goto error2;
|
||||||
|
}
|
||||||
if (pathlen < byte_cnt) {
|
if (pathlen < byte_cnt) {
|
||||||
byte_cnt = pathlen;
|
byte_cnt = pathlen;
|
||||||
}
|
}
|
||||||
@ -1732,7 +1734,7 @@ xfs_set_dmattrs(
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
||||||
xfs_trans_ijoin_ref(tp, ip, XFS_ILOCK_EXCL);
|
xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
|
||||||
|
|
||||||
ip->i_d.di_dmevmask = evmask;
|
ip->i_d.di_dmevmask = evmask;
|
||||||
ip->i_d.di_dmstate = state;
|
ip->i_d.di_dmstate = state;
|
||||||
@ -1778,7 +1780,6 @@ xfs_alloc_file_space(
|
|||||||
xfs_fileoff_t startoffset_fsb;
|
xfs_fileoff_t startoffset_fsb;
|
||||||
xfs_fsblock_t firstfsb;
|
xfs_fsblock_t firstfsb;
|
||||||
int nimaps;
|
int nimaps;
|
||||||
int bmapi_flag;
|
|
||||||
int quota_flag;
|
int quota_flag;
|
||||||
int rt;
|
int rt;
|
||||||
xfs_trans_t *tp;
|
xfs_trans_t *tp;
|
||||||
@ -1806,7 +1807,6 @@ xfs_alloc_file_space(
|
|||||||
count = len;
|
count = len;
|
||||||
imapp = &imaps[0];
|
imapp = &imaps[0];
|
||||||
nimaps = 1;
|
nimaps = 1;
|
||||||
bmapi_flag = XFS_BMAPI_WRITE | alloc_type;
|
|
||||||
startoffset_fsb = XFS_B_TO_FSBT(mp, offset);
|
startoffset_fsb = XFS_B_TO_FSBT(mp, offset);
|
||||||
allocatesize_fsb = XFS_B_TO_FSB(mp, count);
|
allocatesize_fsb = XFS_B_TO_FSB(mp, count);
|
||||||
|
|
||||||
@ -1877,16 +1877,12 @@ xfs_alloc_file_space(
|
|||||||
if (error)
|
if (error)
|
||||||
goto error1;
|
goto error1;
|
||||||
|
|
||||||
xfs_trans_ijoin(tp, ip);
|
xfs_trans_ijoin(tp, ip, 0);
|
||||||
|
|
||||||
/*
|
|
||||||
* Issue the xfs_bmapi() call to allocate the blocks
|
|
||||||
*/
|
|
||||||
xfs_bmap_init(&free_list, &firstfsb);
|
xfs_bmap_init(&free_list, &firstfsb);
|
||||||
error = xfs_bmapi(tp, ip, startoffset_fsb,
|
error = xfs_bmapi_write(tp, ip, startoffset_fsb,
|
||||||
allocatesize_fsb, bmapi_flag,
|
allocatesize_fsb, alloc_type, &firstfsb,
|
||||||
&firstfsb, 0, imapp, &nimaps,
|
0, imapp, &nimaps, &free_list);
|
||||||
&free_list);
|
|
||||||
if (error) {
|
if (error) {
|
||||||
goto error0;
|
goto error0;
|
||||||
}
|
}
|
||||||
@ -1976,8 +1972,7 @@ xfs_zero_remaining_bytes(
|
|||||||
for (offset = startoff; offset <= endoff; offset = lastoffset + 1) {
|
for (offset = startoff; offset <= endoff; offset = lastoffset + 1) {
|
||||||
offset_fsb = XFS_B_TO_FSBT(mp, offset);
|
offset_fsb = XFS_B_TO_FSBT(mp, offset);
|
||||||
nimap = 1;
|
nimap = 1;
|
||||||
error = xfs_bmapi(NULL, ip, offset_fsb, 1, 0,
|
error = xfs_bmapi_read(ip, offset_fsb, 1, &imap, &nimap, 0);
|
||||||
NULL, 0, &imap, &nimap, NULL);
|
|
||||||
if (error || nimap < 1)
|
if (error || nimap < 1)
|
||||||
break;
|
break;
|
||||||
ASSERT(imap.br_blockcount >= 1);
|
ASSERT(imap.br_blockcount >= 1);
|
||||||
@ -1997,8 +1992,8 @@ xfs_zero_remaining_bytes(
|
|||||||
xfsbdstrat(mp, bp);
|
xfsbdstrat(mp, bp);
|
||||||
error = xfs_buf_iowait(bp);
|
error = xfs_buf_iowait(bp);
|
||||||
if (error) {
|
if (error) {
|
||||||
xfs_ioerror_alert("xfs_zero_remaining_bytes(read)",
|
xfs_buf_ioerror_alert(bp,
|
||||||
mp, bp, XFS_BUF_ADDR(bp));
|
"xfs_zero_remaining_bytes(read)");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
memset(bp->b_addr +
|
memset(bp->b_addr +
|
||||||
@ -2010,8 +2005,8 @@ xfs_zero_remaining_bytes(
|
|||||||
xfsbdstrat(mp, bp);
|
xfsbdstrat(mp, bp);
|
||||||
error = xfs_buf_iowait(bp);
|
error = xfs_buf_iowait(bp);
|
||||||
if (error) {
|
if (error) {
|
||||||
xfs_ioerror_alert("xfs_zero_remaining_bytes(write)",
|
xfs_buf_ioerror_alert(bp,
|
||||||
mp, bp, XFS_BUF_ADDR(bp));
|
"xfs_zero_remaining_bytes(write)");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2076,7 +2071,7 @@ xfs_free_file_space(
|
|||||||
if (need_iolock) {
|
if (need_iolock) {
|
||||||
xfs_ilock(ip, XFS_IOLOCK_EXCL);
|
xfs_ilock(ip, XFS_IOLOCK_EXCL);
|
||||||
/* wait for the completion of any pending DIOs */
|
/* wait for the completion of any pending DIOs */
|
||||||
xfs_ioend_wait(ip);
|
inode_dio_wait(VFS_I(ip));
|
||||||
}
|
}
|
||||||
|
|
||||||
rounding = max_t(uint, 1 << mp->m_sb.sb_blocklog, PAGE_CACHE_SIZE);
|
rounding = max_t(uint, 1 << mp->m_sb.sb_blocklog, PAGE_CACHE_SIZE);
|
||||||
@ -2096,8 +2091,8 @@ xfs_free_file_space(
|
|||||||
*/
|
*/
|
||||||
if (rt && !xfs_sb_version_hasextflgbit(&mp->m_sb)) {
|
if (rt && !xfs_sb_version_hasextflgbit(&mp->m_sb)) {
|
||||||
nimap = 1;
|
nimap = 1;
|
||||||
error = xfs_bmapi(NULL, ip, startoffset_fsb,
|
error = xfs_bmapi_read(ip, startoffset_fsb, 1,
|
||||||
1, 0, NULL, 0, &imap, &nimap, NULL);
|
&imap, &nimap, 0);
|
||||||
if (error)
|
if (error)
|
||||||
goto out_unlock_iolock;
|
goto out_unlock_iolock;
|
||||||
ASSERT(nimap == 0 || nimap == 1);
|
ASSERT(nimap == 0 || nimap == 1);
|
||||||
@ -2111,8 +2106,8 @@ xfs_free_file_space(
|
|||||||
startoffset_fsb += mp->m_sb.sb_rextsize - mod;
|
startoffset_fsb += mp->m_sb.sb_rextsize - mod;
|
||||||
}
|
}
|
||||||
nimap = 1;
|
nimap = 1;
|
||||||
error = xfs_bmapi(NULL, ip, endoffset_fsb - 1,
|
error = xfs_bmapi_read(ip, endoffset_fsb - 1, 1,
|
||||||
1, 0, NULL, 0, &imap, &nimap, NULL);
|
&imap, &nimap, 0);
|
||||||
if (error)
|
if (error)
|
||||||
goto out_unlock_iolock;
|
goto out_unlock_iolock;
|
||||||
ASSERT(nimap == 0 || nimap == 1);
|
ASSERT(nimap == 0 || nimap == 1);
|
||||||
@ -2180,7 +2175,7 @@ xfs_free_file_space(
|
|||||||
if (error)
|
if (error)
|
||||||
goto error1;
|
goto error1;
|
||||||
|
|
||||||
xfs_trans_ijoin(tp, ip);
|
xfs_trans_ijoin(tp, ip, 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* issue the bunmapi() call to free the blocks
|
* issue the bunmapi() call to free the blocks
|
||||||
@ -2353,8 +2348,7 @@ xfs_change_file_space(
|
|||||||
}
|
}
|
||||||
|
|
||||||
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
||||||
|
xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
|
||||||
xfs_trans_ijoin(tp, ip);
|
|
||||||
|
|
||||||
if ((attr_flags & XFS_ATTR_DMI) == 0) {
|
if ((attr_flags & XFS_ATTR_DMI) == 0) {
|
||||||
ip->i_d.di_mode &= ~S_ISUID;
|
ip->i_d.di_mode &= ~S_ISUID;
|
||||||
@ -2379,10 +2373,5 @@ xfs_change_file_space(
|
|||||||
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
|
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
|
||||||
if (attr_flags & XFS_ATTR_SYNC)
|
if (attr_flags & XFS_ATTR_SYNC)
|
||||||
xfs_trans_set_sync(tp);
|
xfs_trans_set_sync(tp);
|
||||||
|
return xfs_trans_commit(tp, 0);
|
||||||
error = xfs_trans_commit(tp, 0);
|
|
||||||
|
|
||||||
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user