Merge branch 'for-linus' of git://oss.sgi.com/xfs/xfs
* 'for-linus' of git://oss.sgi.com/xfs/xfs: xfs: improve xfs_isilocked xfs: skip writeback from reclaim context xfs: remove done roadmap item from xfs-delayed-logging-design.txt xfs: fix race in inode cluster freeing failing to stale inodes xfs: fix access to upper inodes without inode64 xfs: fix might_sleep() warning when initialising per-ag tree fs/xfs/quota: Add missing mutex_unlock xfs: remove duplicated #include xfs: convert more trace events to DEFINE_EVENT xfs: xfs_trace.c: remove duplicated #include xfs: Check new inode size is OK before preallocating xfs: clean up xlog_align xfs: cleanup log reservation calculactions xfs: be more explicit if RT mount fails due to config xfs: replace E2BIG with EFBIG where appropriate
This commit is contained in:
Коммит
6c5de280b6
|
@ -794,11 +794,6 @@ designed.
|
|||
|
||||
Roadmap:
|
||||
|
||||
2.6.35 Inclusion in mainline as an experimental mount option
|
||||
=> approximately 2-3 months to merge window
|
||||
=> needs to be in xfs-dev tree in 4-6 weeks
|
||||
=> code is nearing readiness for review
|
||||
|
||||
2.6.37 Remove experimental tag from mount option
|
||||
=> should be roughly 6 months after initial merge
|
||||
=> enough time to:
|
||||
|
|
|
@ -1332,6 +1332,21 @@ xfs_vm_writepage(
|
|||
|
||||
trace_xfs_writepage(inode, page, 0);
|
||||
|
||||
/*
|
||||
* Refuse to write the page out if we are called from reclaim context.
|
||||
*
|
||||
* This is primarily to avoid stack overflows when called from deep
|
||||
* used stacks in random callers for direct reclaim, but disabling
|
||||
* reclaim for kswap is a nice side-effect as kswapd causes rather
|
||||
* suboptimal I/O patters, too.
|
||||
*
|
||||
* This should really be done by the core VM, but until that happens
|
||||
* filesystems like XFS, btrfs and ext4 have to take care of this
|
||||
* by themselves.
|
||||
*/
|
||||
if (current->flags & PF_MEMALLOC)
|
||||
goto out_fail;
|
||||
|
||||
/*
|
||||
* We need a transaction if:
|
||||
* 1. There are delalloc buffers on the page
|
||||
|
|
|
@ -585,11 +585,20 @@ xfs_vn_fallocate(
|
|||
bf.l_len = len;
|
||||
|
||||
xfs_ilock(ip, XFS_IOLOCK_EXCL);
|
||||
|
||||
/* check the new inode size is valid before allocating */
|
||||
if (!(mode & FALLOC_FL_KEEP_SIZE) &&
|
||||
offset + len > i_size_read(inode)) {
|
||||
new_size = offset + len;
|
||||
error = inode_newsize_ok(inode, new_size);
|
||||
if (error)
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
error = -xfs_change_file_space(ip, XFS_IOC_RESVSP, &bf,
|
||||
0, XFS_ATTR_NOLOCK);
|
||||
if (!error && !(mode & FALLOC_FL_KEEP_SIZE) &&
|
||||
offset + len > i_size_read(inode))
|
||||
new_size = offset + len;
|
||||
if (error)
|
||||
goto out_unlock;
|
||||
|
||||
/* Change file size if needed */
|
||||
if (new_size) {
|
||||
|
@ -600,6 +609,7 @@ xfs_vn_fallocate(
|
|||
error = -xfs_setattr(ip, &iattr, XFS_ATTR_NOLOCK);
|
||||
}
|
||||
|
||||
out_unlock:
|
||||
xfs_iunlock(ip, XFS_IOLOCK_EXCL);
|
||||
out_error:
|
||||
return error;
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include "xfs_ag.h"
|
||||
#include "xfs_mount.h"
|
||||
#include "xfs_quota.h"
|
||||
#include "xfs_log.h"
|
||||
#include "xfs_trans.h"
|
||||
#include "xfs_bmap_btree.h"
|
||||
#include "xfs_inode.h"
|
||||
|
|
|
@ -164,10 +164,6 @@ xfs_inode_ag_iterator(
|
|||
struct xfs_perag *pag;
|
||||
|
||||
pag = xfs_perag_get(mp, ag);
|
||||
if (!pag->pag_ici_init) {
|
||||
xfs_perag_put(pag);
|
||||
continue;
|
||||
}
|
||||
error = xfs_inode_ag_walk(mp, pag, execute, flags, tag,
|
||||
exclusive, &nr);
|
||||
xfs_perag_put(pag);
|
||||
|
@ -867,12 +863,7 @@ xfs_reclaim_inode_shrink(
|
|||
down_read(&xfs_mount_list_lock);
|
||||
list_for_each_entry(mp, &xfs_mount_list, m_mplist) {
|
||||
for (ag = 0; ag < mp->m_sb.sb_agcount; ag++) {
|
||||
|
||||
pag = xfs_perag_get(mp, ag);
|
||||
if (!pag->pag_ici_init) {
|
||||
xfs_perag_put(pag);
|
||||
continue;
|
||||
}
|
||||
reclaimable += pag->pag_ici_reclaimable;
|
||||
xfs_perag_put(pag);
|
||||
}
|
||||
|
|
|
@ -50,7 +50,6 @@
|
|||
#include "quota/xfs_dquot_item.h"
|
||||
#include "quota/xfs_dquot.h"
|
||||
#include "xfs_log_recover.h"
|
||||
#include "xfs_buf_item.h"
|
||||
#include "xfs_inode_item.h"
|
||||
|
||||
/*
|
||||
|
|
|
@ -82,33 +82,6 @@ DECLARE_EVENT_CLASS(xfs_attr_list_class,
|
|||
)
|
||||
)
|
||||
|
||||
#define DEFINE_PERAG_REF_EVENT(name) \
|
||||
TRACE_EVENT(name, \
|
||||
TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, int refcount, \
|
||||
unsigned long caller_ip), \
|
||||
TP_ARGS(mp, agno, refcount, caller_ip), \
|
||||
TP_STRUCT__entry( \
|
||||
__field(dev_t, dev) \
|
||||
__field(xfs_agnumber_t, agno) \
|
||||
__field(int, refcount) \
|
||||
__field(unsigned long, caller_ip) \
|
||||
), \
|
||||
TP_fast_assign( \
|
||||
__entry->dev = mp->m_super->s_dev; \
|
||||
__entry->agno = agno; \
|
||||
__entry->refcount = refcount; \
|
||||
__entry->caller_ip = caller_ip; \
|
||||
), \
|
||||
TP_printk("dev %d:%d agno %u refcount %d caller %pf", \
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev), \
|
||||
__entry->agno, \
|
||||
__entry->refcount, \
|
||||
(char *)__entry->caller_ip) \
|
||||
);
|
||||
|
||||
DEFINE_PERAG_REF_EVENT(xfs_perag_get)
|
||||
DEFINE_PERAG_REF_EVENT(xfs_perag_put)
|
||||
|
||||
#define DEFINE_ATTR_LIST_EVENT(name) \
|
||||
DEFINE_EVENT(xfs_attr_list_class, name, \
|
||||
TP_PROTO(struct xfs_attr_list_context *ctx), \
|
||||
|
@ -122,6 +95,37 @@ DEFINE_ATTR_LIST_EVENT(xfs_attr_list_add);
|
|||
DEFINE_ATTR_LIST_EVENT(xfs_attr_list_wrong_blk);
|
||||
DEFINE_ATTR_LIST_EVENT(xfs_attr_list_notfound);
|
||||
|
||||
DECLARE_EVENT_CLASS(xfs_perag_class,
|
||||
TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, int refcount,
|
||||
unsigned long caller_ip),
|
||||
TP_ARGS(mp, agno, refcount, caller_ip),
|
||||
TP_STRUCT__entry(
|
||||
__field(dev_t, dev)
|
||||
__field(xfs_agnumber_t, agno)
|
||||
__field(int, refcount)
|
||||
__field(unsigned long, caller_ip)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->dev = mp->m_super->s_dev;
|
||||
__entry->agno = agno;
|
||||
__entry->refcount = refcount;
|
||||
__entry->caller_ip = caller_ip;
|
||||
),
|
||||
TP_printk("dev %d:%d agno %u refcount %d caller %pf",
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||
__entry->agno,
|
||||
__entry->refcount,
|
||||
(char *)__entry->caller_ip)
|
||||
);
|
||||
|
||||
#define DEFINE_PERAG_REF_EVENT(name) \
|
||||
DEFINE_EVENT(xfs_perag_class, name, \
|
||||
TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, int refcount, \
|
||||
unsigned long caller_ip), \
|
||||
TP_ARGS(mp, agno, refcount, caller_ip))
|
||||
DEFINE_PERAG_REF_EVENT(xfs_perag_get);
|
||||
DEFINE_PERAG_REF_EVENT(xfs_perag_put);
|
||||
|
||||
TRACE_EVENT(xfs_attr_list_node_descend,
|
||||
TP_PROTO(struct xfs_attr_list_context *ctx,
|
||||
struct xfs_da_node_entry *btree),
|
||||
|
@ -775,165 +779,181 @@ DEFINE_LOGGRANT_EVENT(xfs_log_ungrant_enter);
|
|||
DEFINE_LOGGRANT_EVENT(xfs_log_ungrant_exit);
|
||||
DEFINE_LOGGRANT_EVENT(xfs_log_ungrant_sub);
|
||||
|
||||
#define DEFINE_RW_EVENT(name) \
|
||||
TRACE_EVENT(name, \
|
||||
TP_PROTO(struct xfs_inode *ip, size_t count, loff_t offset, int flags), \
|
||||
TP_ARGS(ip, count, offset, flags), \
|
||||
TP_STRUCT__entry( \
|
||||
__field(dev_t, dev) \
|
||||
__field(xfs_ino_t, ino) \
|
||||
__field(xfs_fsize_t, size) \
|
||||
__field(xfs_fsize_t, new_size) \
|
||||
__field(loff_t, offset) \
|
||||
__field(size_t, count) \
|
||||
__field(int, flags) \
|
||||
), \
|
||||
TP_fast_assign( \
|
||||
__entry->dev = VFS_I(ip)->i_sb->s_dev; \
|
||||
__entry->ino = ip->i_ino; \
|
||||
__entry->size = ip->i_d.di_size; \
|
||||
__entry->new_size = ip->i_new_size; \
|
||||
__entry->offset = offset; \
|
||||
__entry->count = count; \
|
||||
__entry->flags = flags; \
|
||||
), \
|
||||
TP_printk("dev %d:%d ino 0x%llx size 0x%llx new_size 0x%llx " \
|
||||
"offset 0x%llx count 0x%zx ioflags %s", \
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev), \
|
||||
__entry->ino, \
|
||||
__entry->size, \
|
||||
__entry->new_size, \
|
||||
__entry->offset, \
|
||||
__entry->count, \
|
||||
__print_flags(__entry->flags, "|", XFS_IO_FLAGS)) \
|
||||
DECLARE_EVENT_CLASS(xfs_file_class,
|
||||
TP_PROTO(struct xfs_inode *ip, size_t count, loff_t offset, int flags),
|
||||
TP_ARGS(ip, count, offset, flags),
|
||||
TP_STRUCT__entry(
|
||||
__field(dev_t, dev)
|
||||
__field(xfs_ino_t, ino)
|
||||
__field(xfs_fsize_t, size)
|
||||
__field(xfs_fsize_t, new_size)
|
||||
__field(loff_t, offset)
|
||||
__field(size_t, count)
|
||||
__field(int, flags)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->dev = VFS_I(ip)->i_sb->s_dev;
|
||||
__entry->ino = ip->i_ino;
|
||||
__entry->size = ip->i_d.di_size;
|
||||
__entry->new_size = ip->i_new_size;
|
||||
__entry->offset = offset;
|
||||
__entry->count = count;
|
||||
__entry->flags = flags;
|
||||
),
|
||||
TP_printk("dev %d:%d ino 0x%llx size 0x%llx new_size 0x%llx "
|
||||
"offset 0x%llx count 0x%zx ioflags %s",
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||
__entry->ino,
|
||||
__entry->size,
|
||||
__entry->new_size,
|
||||
__entry->offset,
|
||||
__entry->count,
|
||||
__print_flags(__entry->flags, "|", XFS_IO_FLAGS))
|
||||
)
|
||||
|
||||
#define DEFINE_RW_EVENT(name) \
|
||||
DEFINE_EVENT(xfs_file_class, name, \
|
||||
TP_PROTO(struct xfs_inode *ip, size_t count, loff_t offset, int flags), \
|
||||
TP_ARGS(ip, count, offset, flags))
|
||||
DEFINE_RW_EVENT(xfs_file_read);
|
||||
DEFINE_RW_EVENT(xfs_file_buffered_write);
|
||||
DEFINE_RW_EVENT(xfs_file_direct_write);
|
||||
DEFINE_RW_EVENT(xfs_file_splice_read);
|
||||
DEFINE_RW_EVENT(xfs_file_splice_write);
|
||||
|
||||
DECLARE_EVENT_CLASS(xfs_page_class,
|
||||
TP_PROTO(struct inode *inode, struct page *page, unsigned long off),
|
||||
TP_ARGS(inode, page, off),
|
||||
TP_STRUCT__entry(
|
||||
__field(dev_t, dev)
|
||||
__field(xfs_ino_t, ino)
|
||||
__field(pgoff_t, pgoff)
|
||||
__field(loff_t, size)
|
||||
__field(unsigned long, offset)
|
||||
__field(int, delalloc)
|
||||
__field(int, unmapped)
|
||||
__field(int, unwritten)
|
||||
),
|
||||
TP_fast_assign(
|
||||
int delalloc = -1, unmapped = -1, unwritten = -1;
|
||||
|
||||
#define DEFINE_PAGE_EVENT(name) \
|
||||
TRACE_EVENT(name, \
|
||||
TP_PROTO(struct inode *inode, struct page *page, unsigned long off), \
|
||||
TP_ARGS(inode, page, off), \
|
||||
TP_STRUCT__entry( \
|
||||
__field(dev_t, dev) \
|
||||
__field(xfs_ino_t, ino) \
|
||||
__field(pgoff_t, pgoff) \
|
||||
__field(loff_t, size) \
|
||||
__field(unsigned long, offset) \
|
||||
__field(int, delalloc) \
|
||||
__field(int, unmapped) \
|
||||
__field(int, unwritten) \
|
||||
), \
|
||||
TP_fast_assign( \
|
||||
int delalloc = -1, unmapped = -1, unwritten = -1; \
|
||||
\
|
||||
if (page_has_buffers(page)) \
|
||||
xfs_count_page_state(page, &delalloc, \
|
||||
&unmapped, &unwritten); \
|
||||
__entry->dev = inode->i_sb->s_dev; \
|
||||
__entry->ino = XFS_I(inode)->i_ino; \
|
||||
__entry->pgoff = page_offset(page); \
|
||||
__entry->size = i_size_read(inode); \
|
||||
__entry->offset = off; \
|
||||
__entry->delalloc = delalloc; \
|
||||
__entry->unmapped = unmapped; \
|
||||
__entry->unwritten = unwritten; \
|
||||
), \
|
||||
TP_printk("dev %d:%d ino 0x%llx pgoff 0x%lx size 0x%llx offset %lx " \
|
||||
"delalloc %d unmapped %d unwritten %d", \
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev), \
|
||||
__entry->ino, \
|
||||
__entry->pgoff, \
|
||||
__entry->size, \
|
||||
__entry->offset, \
|
||||
__entry->delalloc, \
|
||||
__entry->unmapped, \
|
||||
__entry->unwritten) \
|
||||
if (page_has_buffers(page))
|
||||
xfs_count_page_state(page, &delalloc,
|
||||
&unmapped, &unwritten);
|
||||
__entry->dev = inode->i_sb->s_dev;
|
||||
__entry->ino = XFS_I(inode)->i_ino;
|
||||
__entry->pgoff = page_offset(page);
|
||||
__entry->size = i_size_read(inode);
|
||||
__entry->offset = off;
|
||||
__entry->delalloc = delalloc;
|
||||
__entry->unmapped = unmapped;
|
||||
__entry->unwritten = unwritten;
|
||||
),
|
||||
TP_printk("dev %d:%d ino 0x%llx pgoff 0x%lx size 0x%llx offset %lx "
|
||||
"delalloc %d unmapped %d unwritten %d",
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||
__entry->ino,
|
||||
__entry->pgoff,
|
||||
__entry->size,
|
||||
__entry->offset,
|
||||
__entry->delalloc,
|
||||
__entry->unmapped,
|
||||
__entry->unwritten)
|
||||
)
|
||||
|
||||
#define DEFINE_PAGE_EVENT(name) \
|
||||
DEFINE_EVENT(xfs_page_class, name, \
|
||||
TP_PROTO(struct inode *inode, struct page *page, unsigned long off), \
|
||||
TP_ARGS(inode, page, off))
|
||||
DEFINE_PAGE_EVENT(xfs_writepage);
|
||||
DEFINE_PAGE_EVENT(xfs_releasepage);
|
||||
DEFINE_PAGE_EVENT(xfs_invalidatepage);
|
||||
|
||||
#define DEFINE_IOMAP_EVENT(name) \
|
||||
TRACE_EVENT(name, \
|
||||
TP_PROTO(struct xfs_inode *ip, xfs_off_t offset, ssize_t count, \
|
||||
int flags, struct xfs_bmbt_irec *irec), \
|
||||
TP_ARGS(ip, offset, count, flags, irec), \
|
||||
TP_STRUCT__entry( \
|
||||
__field(dev_t, dev) \
|
||||
__field(xfs_ino_t, ino) \
|
||||
__field(loff_t, size) \
|
||||
__field(loff_t, new_size) \
|
||||
__field(loff_t, offset) \
|
||||
__field(size_t, count) \
|
||||
__field(int, flags) \
|
||||
__field(xfs_fileoff_t, startoff) \
|
||||
__field(xfs_fsblock_t, startblock) \
|
||||
__field(xfs_filblks_t, blockcount) \
|
||||
), \
|
||||
TP_fast_assign( \
|
||||
__entry->dev = VFS_I(ip)->i_sb->s_dev; \
|
||||
__entry->ino = ip->i_ino; \
|
||||
__entry->size = ip->i_d.di_size; \
|
||||
__entry->new_size = ip->i_new_size; \
|
||||
__entry->offset = offset; \
|
||||
__entry->count = count; \
|
||||
__entry->flags = flags; \
|
||||
__entry->startoff = irec ? irec->br_startoff : 0; \
|
||||
__entry->startblock = irec ? irec->br_startblock : 0; \
|
||||
__entry->blockcount = irec ? irec->br_blockcount : 0; \
|
||||
), \
|
||||
TP_printk("dev %d:%d ino 0x%llx size 0x%llx new_size 0x%llx " \
|
||||
"offset 0x%llx count %zd flags %s " \
|
||||
"startoff 0x%llx startblock %lld blockcount 0x%llx", \
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev), \
|
||||
__entry->ino, \
|
||||
__entry->size, \
|
||||
__entry->new_size, \
|
||||
__entry->offset, \
|
||||
__entry->count, \
|
||||
__print_flags(__entry->flags, "|", BMAPI_FLAGS), \
|
||||
__entry->startoff, \
|
||||
(__int64_t)__entry->startblock, \
|
||||
__entry->blockcount) \
|
||||
DECLARE_EVENT_CLASS(xfs_iomap_class,
|
||||
TP_PROTO(struct xfs_inode *ip, xfs_off_t offset, ssize_t count,
|
||||
int flags, struct xfs_bmbt_irec *irec),
|
||||
TP_ARGS(ip, offset, count, flags, irec),
|
||||
TP_STRUCT__entry(
|
||||
__field(dev_t, dev)
|
||||
__field(xfs_ino_t, ino)
|
||||
__field(loff_t, size)
|
||||
__field(loff_t, new_size)
|
||||
__field(loff_t, offset)
|
||||
__field(size_t, count)
|
||||
__field(int, flags)
|
||||
__field(xfs_fileoff_t, startoff)
|
||||
__field(xfs_fsblock_t, startblock)
|
||||
__field(xfs_filblks_t, blockcount)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->dev = VFS_I(ip)->i_sb->s_dev;
|
||||
__entry->ino = ip->i_ino;
|
||||
__entry->size = ip->i_d.di_size;
|
||||
__entry->new_size = ip->i_new_size;
|
||||
__entry->offset = offset;
|
||||
__entry->count = count;
|
||||
__entry->flags = flags;
|
||||
__entry->startoff = irec ? irec->br_startoff : 0;
|
||||
__entry->startblock = irec ? irec->br_startblock : 0;
|
||||
__entry->blockcount = irec ? irec->br_blockcount : 0;
|
||||
),
|
||||
TP_printk("dev %d:%d ino 0x%llx size 0x%llx new_size 0x%llx "
|
||||
"offset 0x%llx count %zd flags %s "
|
||||
"startoff 0x%llx startblock %lld blockcount 0x%llx",
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||
__entry->ino,
|
||||
__entry->size,
|
||||
__entry->new_size,
|
||||
__entry->offset,
|
||||
__entry->count,
|
||||
__print_flags(__entry->flags, "|", BMAPI_FLAGS),
|
||||
__entry->startoff,
|
||||
(__int64_t)__entry->startblock,
|
||||
__entry->blockcount)
|
||||
)
|
||||
|
||||
#define DEFINE_IOMAP_EVENT(name) \
|
||||
DEFINE_EVENT(xfs_iomap_class, name, \
|
||||
TP_PROTO(struct xfs_inode *ip, xfs_off_t offset, ssize_t count, \
|
||||
int flags, struct xfs_bmbt_irec *irec), \
|
||||
TP_ARGS(ip, offset, count, flags, irec))
|
||||
DEFINE_IOMAP_EVENT(xfs_iomap_enter);
|
||||
DEFINE_IOMAP_EVENT(xfs_iomap_found);
|
||||
DEFINE_IOMAP_EVENT(xfs_iomap_alloc);
|
||||
|
||||
#define DEFINE_SIMPLE_IO_EVENT(name) \
|
||||
TRACE_EVENT(name, \
|
||||
TP_PROTO(struct xfs_inode *ip, xfs_off_t offset, ssize_t count), \
|
||||
TP_ARGS(ip, offset, count), \
|
||||
TP_STRUCT__entry( \
|
||||
__field(dev_t, dev) \
|
||||
__field(xfs_ino_t, ino) \
|
||||
__field(loff_t, size) \
|
||||
__field(loff_t, new_size) \
|
||||
__field(loff_t, offset) \
|
||||
__field(size_t, count) \
|
||||
), \
|
||||
TP_fast_assign( \
|
||||
__entry->dev = VFS_I(ip)->i_sb->s_dev; \
|
||||
__entry->ino = ip->i_ino; \
|
||||
__entry->size = ip->i_d.di_size; \
|
||||
__entry->new_size = ip->i_new_size; \
|
||||
__entry->offset = offset; \
|
||||
__entry->count = count; \
|
||||
), \
|
||||
TP_printk("dev %d:%d ino 0x%llx size 0x%llx new_size 0x%llx " \
|
||||
"offset 0x%llx count %zd", \
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev), \
|
||||
__entry->ino, \
|
||||
__entry->size, \
|
||||
__entry->new_size, \
|
||||
__entry->offset, \
|
||||
__entry->count) \
|
||||
DECLARE_EVENT_CLASS(xfs_simple_io_class,
|
||||
TP_PROTO(struct xfs_inode *ip, xfs_off_t offset, ssize_t count),
|
||||
TP_ARGS(ip, offset, count),
|
||||
TP_STRUCT__entry(
|
||||
__field(dev_t, dev)
|
||||
__field(xfs_ino_t, ino)
|
||||
__field(loff_t, size)
|
||||
__field(loff_t, new_size)
|
||||
__field(loff_t, offset)
|
||||
__field(size_t, count)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->dev = VFS_I(ip)->i_sb->s_dev;
|
||||
__entry->ino = ip->i_ino;
|
||||
__entry->size = ip->i_d.di_size;
|
||||
__entry->new_size = ip->i_new_size;
|
||||
__entry->offset = offset;
|
||||
__entry->count = count;
|
||||
),
|
||||
TP_printk("dev %d:%d ino 0x%llx size 0x%llx new_size 0x%llx "
|
||||
"offset 0x%llx count %zd",
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||
__entry->ino,
|
||||
__entry->size,
|
||||
__entry->new_size,
|
||||
__entry->offset,
|
||||
__entry->count)
|
||||
);
|
||||
|
||||
#define DEFINE_SIMPLE_IO_EVENT(name) \
|
||||
DEFINE_EVENT(xfs_simple_io_class, name, \
|
||||
TP_PROTO(struct xfs_inode *ip, xfs_off_t offset, ssize_t count), \
|
||||
TP_ARGS(ip, offset, count))
|
||||
DEFINE_SIMPLE_IO_EVENT(xfs_delalloc_enospc);
|
||||
DEFINE_SIMPLE_IO_EVENT(xfs_unwritten_convert);
|
||||
|
||||
|
|
|
@ -249,8 +249,10 @@ xfs_qm_hold_quotafs_ref(
|
|||
|
||||
if (!xfs_Gqm) {
|
||||
xfs_Gqm = xfs_Gqm_init();
|
||||
if (!xfs_Gqm)
|
||||
if (!xfs_Gqm) {
|
||||
mutex_unlock(&xfs_Gqm_lock);
|
||||
return ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -227,7 +227,6 @@ typedef struct xfs_perag {
|
|||
|
||||
atomic_t pagf_fstrms; /* # of filestreams active in this AG */
|
||||
|
||||
int pag_ici_init; /* incore inode cache initialised */
|
||||
rwlock_t pag_ici_lock; /* incore inode lock */
|
||||
struct radix_tree_root pag_ici_root; /* incore inode cache root */
|
||||
int pag_ici_reclaimable; /* reclaimable inodes */
|
||||
|
|
|
@ -382,9 +382,6 @@ xfs_iget(
|
|||
|
||||
/* get the perag structure and ensure that it's inode capable */
|
||||
pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ino));
|
||||
if (!pag->pagi_inodeok)
|
||||
return EINVAL;
|
||||
ASSERT(pag->pag_ici_init);
|
||||
agino = XFS_INO_TO_AGINO(mp, ino);
|
||||
|
||||
again:
|
||||
|
@ -744,30 +741,24 @@ xfs_ilock_demote(
|
|||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
/*
|
||||
* Debug-only routine, without additional rw_semaphore APIs, we can
|
||||
* now only answer requests regarding whether we hold the lock for write
|
||||
* (reader state is outside our visibility, we only track writer state).
|
||||
*
|
||||
* Note: this means !xfs_isilocked would give false positives, so don't do that.
|
||||
*/
|
||||
int
|
||||
xfs_isilocked(
|
||||
xfs_inode_t *ip,
|
||||
uint lock_flags)
|
||||
{
|
||||
if ((lock_flags & (XFS_ILOCK_EXCL|XFS_ILOCK_SHARED)) ==
|
||||
XFS_ILOCK_EXCL) {
|
||||
if (!ip->i_lock.mr_writer)
|
||||
return 0;
|
||||
if (lock_flags & (XFS_ILOCK_EXCL|XFS_ILOCK_SHARED)) {
|
||||
if (!(lock_flags & XFS_ILOCK_SHARED))
|
||||
return !!ip->i_lock.mr_writer;
|
||||
return rwsem_is_locked(&ip->i_lock.mr_lock);
|
||||
}
|
||||
|
||||
if ((lock_flags & (XFS_IOLOCK_EXCL|XFS_IOLOCK_SHARED)) ==
|
||||
XFS_IOLOCK_EXCL) {
|
||||
if (!ip->i_iolock.mr_writer)
|
||||
return 0;
|
||||
if (lock_flags & (XFS_IOLOCK_EXCL|XFS_IOLOCK_SHARED)) {
|
||||
if (!(lock_flags & XFS_IOLOCK_SHARED))
|
||||
return !!ip->i_iolock.mr_writer;
|
||||
return rwsem_is_locked(&ip->i_iolock.mr_lock);
|
||||
}
|
||||
|
||||
return 1;
|
||||
ASSERT(0);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1940,10 +1940,10 @@ xfs_ifree_cluster(
|
|||
int blks_per_cluster;
|
||||
int nbufs;
|
||||
int ninodes;
|
||||
int i, j, found, pre_flushed;
|
||||
int i, j;
|
||||
xfs_daddr_t blkno;
|
||||
xfs_buf_t *bp;
|
||||
xfs_inode_t *ip, **ip_found;
|
||||
xfs_inode_t *ip;
|
||||
xfs_inode_log_item_t *iip;
|
||||
xfs_log_item_t *lip;
|
||||
struct xfs_perag *pag;
|
||||
|
@ -1960,89 +1960,29 @@ xfs_ifree_cluster(
|
|||
nbufs = XFS_IALLOC_BLOCKS(mp) / blks_per_cluster;
|
||||
}
|
||||
|
||||
ip_found = kmem_alloc(ninodes * sizeof(xfs_inode_t *), KM_NOFS);
|
||||
|
||||
for (j = 0; j < nbufs; j++, inum += ninodes) {
|
||||
int found = 0;
|
||||
|
||||
blkno = XFS_AGB_TO_DADDR(mp, XFS_INO_TO_AGNO(mp, inum),
|
||||
XFS_INO_TO_AGBNO(mp, inum));
|
||||
|
||||
|
||||
/*
|
||||
* Look for each inode in memory and attempt to lock it,
|
||||
* we can be racing with flush and tail pushing here.
|
||||
* any inode we get the locks on, add to an array of
|
||||
* inode items to process later.
|
||||
*
|
||||
* The get the buffer lock, we could beat a flush
|
||||
* or tail pushing thread to the lock here, in which
|
||||
* case they will go looking for the inode buffer
|
||||
* and fail, we need some other form of interlock
|
||||
* here.
|
||||
* We obtain and lock the backing buffer first in the process
|
||||
* here, as we have to ensure that any dirty inode that we
|
||||
* can't get the flush lock on is attached to the buffer.
|
||||
* If we scan the in-memory inodes first, then buffer IO can
|
||||
* complete before we get a lock on it, and hence we may fail
|
||||
* to mark all the active inodes on the buffer stale.
|
||||
*/
|
||||
found = 0;
|
||||
for (i = 0; i < ninodes; i++) {
|
||||
read_lock(&pag->pag_ici_lock);
|
||||
ip = radix_tree_lookup(&pag->pag_ici_root,
|
||||
XFS_INO_TO_AGINO(mp, (inum + i)));
|
||||
|
||||
/* Inode not in memory or we found it already,
|
||||
* nothing to do
|
||||
*/
|
||||
if (!ip || xfs_iflags_test(ip, XFS_ISTALE)) {
|
||||
read_unlock(&pag->pag_ici_lock);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (xfs_inode_clean(ip)) {
|
||||
read_unlock(&pag->pag_ici_lock);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If we can get the locks then add it to the
|
||||
* list, otherwise by the time we get the bp lock
|
||||
* below it will already be attached to the
|
||||
* inode buffer.
|
||||
*/
|
||||
|
||||
/* This inode will already be locked - by us, lets
|
||||
* keep it that way.
|
||||
*/
|
||||
|
||||
if (ip == free_ip) {
|
||||
if (xfs_iflock_nowait(ip)) {
|
||||
xfs_iflags_set(ip, XFS_ISTALE);
|
||||
if (xfs_inode_clean(ip)) {
|
||||
xfs_ifunlock(ip);
|
||||
} else {
|
||||
ip_found[found++] = ip;
|
||||
}
|
||||
}
|
||||
read_unlock(&pag->pag_ici_lock);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) {
|
||||
if (xfs_iflock_nowait(ip)) {
|
||||
xfs_iflags_set(ip, XFS_ISTALE);
|
||||
|
||||
if (xfs_inode_clean(ip)) {
|
||||
xfs_ifunlock(ip);
|
||||
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
||||
} else {
|
||||
ip_found[found++] = ip;
|
||||
}
|
||||
} else {
|
||||
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
||||
}
|
||||
}
|
||||
read_unlock(&pag->pag_ici_lock);
|
||||
}
|
||||
|
||||
bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, blkno,
|
||||
mp->m_bsize * blks_per_cluster,
|
||||
XBF_LOCK);
|
||||
|
||||
pre_flushed = 0;
|
||||
/*
|
||||
* Walk the inodes already attached to the buffer and mark them
|
||||
* stale. These will all have the flush locks held, so an
|
||||
* in-memory inode walk can't lock them.
|
||||
*/
|
||||
lip = XFS_BUF_FSPRIVATE(bp, xfs_log_item_t *);
|
||||
while (lip) {
|
||||
if (lip->li_type == XFS_LI_INODE) {
|
||||
|
@ -2053,21 +1993,64 @@ xfs_ifree_cluster(
|
|||
&iip->ili_flush_lsn,
|
||||
&iip->ili_item.li_lsn);
|
||||
xfs_iflags_set(iip->ili_inode, XFS_ISTALE);
|
||||
pre_flushed++;
|
||||
found++;
|
||||
}
|
||||
lip = lip->li_bio_list;
|
||||
}
|
||||
|
||||
for (i = 0; i < found; i++) {
|
||||
ip = ip_found[i];
|
||||
iip = ip->i_itemp;
|
||||
/*
|
||||
* For each inode in memory attempt to add it to the inode
|
||||
* buffer and set it up for being staled on buffer IO
|
||||
* completion. This is safe as we've locked out tail pushing
|
||||
* and flushing by locking the buffer.
|
||||
*
|
||||
* We have already marked every inode that was part of a
|
||||
* transaction stale above, which means there is no point in
|
||||
* even trying to lock them.
|
||||
*/
|
||||
for (i = 0; i < ninodes; i++) {
|
||||
read_lock(&pag->pag_ici_lock);
|
||||
ip = radix_tree_lookup(&pag->pag_ici_root,
|
||||
XFS_INO_TO_AGINO(mp, (inum + i)));
|
||||
|
||||
/* Inode not in memory or stale, nothing to do */
|
||||
if (!ip || xfs_iflags_test(ip, XFS_ISTALE)) {
|
||||
read_unlock(&pag->pag_ici_lock);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* don't try to lock/unlock the current inode */
|
||||
if (ip != free_ip &&
|
||||
!xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) {
|
||||
read_unlock(&pag->pag_ici_lock);
|
||||
continue;
|
||||
}
|
||||
read_unlock(&pag->pag_ici_lock);
|
||||
|
||||
if (!xfs_iflock_nowait(ip)) {
|
||||
if (ip != free_ip)
|
||||
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
||||
continue;
|
||||
}
|
||||
|
||||
xfs_iflags_set(ip, XFS_ISTALE);
|
||||
if (xfs_inode_clean(ip)) {
|
||||
ASSERT(ip != free_ip);
|
||||
xfs_ifunlock(ip);
|
||||
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
||||
continue;
|
||||
}
|
||||
|
||||
iip = ip->i_itemp;
|
||||
if (!iip) {
|
||||
/* inode with unlogged changes only */
|
||||
ASSERT(ip != free_ip);
|
||||
ip->i_update_core = 0;
|
||||
xfs_ifunlock(ip);
|
||||
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
||||
continue;
|
||||
}
|
||||
found++;
|
||||
|
||||
iip->ili_last_fields = iip->ili_format.ilf_fields;
|
||||
iip->ili_format.ilf_fields = 0;
|
||||
|
@ -2078,17 +2061,16 @@ xfs_ifree_cluster(
|
|||
xfs_buf_attach_iodone(bp,
|
||||
(void(*)(xfs_buf_t*,xfs_log_item_t*))
|
||||
xfs_istale_done, (xfs_log_item_t *)iip);
|
||||
if (ip != free_ip) {
|
||||
|
||||
if (ip != free_ip)
|
||||
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
||||
}
|
||||
}
|
||||
|
||||
if (found || pre_flushed)
|
||||
if (found)
|
||||
xfs_trans_stale_inode_buf(tp, bp);
|
||||
xfs_trans_binval(tp, bp);
|
||||
}
|
||||
|
||||
kmem_free(ip_found);
|
||||
xfs_perag_put(pag);
|
||||
}
|
||||
|
||||
|
@ -2649,8 +2631,6 @@ xfs_iflush_cluster(
|
|||
int i;
|
||||
|
||||
pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino));
|
||||
ASSERT(pag->pagi_inodeok);
|
||||
ASSERT(pag->pag_ici_init);
|
||||
|
||||
inodes_per_cluster = XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_inodelog;
|
||||
ilist_size = inodes_per_cluster * sizeof(xfs_inode_t *);
|
||||
|
|
|
@ -132,15 +132,10 @@ xlog_align(
|
|||
int nbblks,
|
||||
xfs_buf_t *bp)
|
||||
{
|
||||
xfs_daddr_t offset;
|
||||
xfs_caddr_t ptr;
|
||||
xfs_daddr_t offset = blk_no & ((xfs_daddr_t)log->l_sectBBsize - 1);
|
||||
|
||||
offset = blk_no & ((xfs_daddr_t) log->l_sectBBsize - 1);
|
||||
ptr = XFS_BUF_PTR(bp) + BBTOB(offset);
|
||||
|
||||
ASSERT(ptr + BBTOB(nbblks) <= XFS_BUF_PTR(bp) + XFS_BUF_SIZE(bp));
|
||||
|
||||
return ptr;
|
||||
ASSERT(BBTOB(offset + nbblks) <= XFS_BUF_SIZE(bp));
|
||||
return XFS_BUF_PTR(bp) + BBTOB(offset);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -268,10 +268,10 @@ xfs_sb_validate_fsb_count(
|
|||
|
||||
#if XFS_BIG_BLKNOS /* Limited by ULONG_MAX of page cache index */
|
||||
if (nblocks >> (PAGE_CACHE_SHIFT - sbp->sb_blocklog) > ULONG_MAX)
|
||||
return E2BIG;
|
||||
return EFBIG;
|
||||
#else /* Limited by UINT_MAX of sectors */
|
||||
if (nblocks << (sbp->sb_blocklog - BBSHIFT) > UINT_MAX)
|
||||
return E2BIG;
|
||||
return EFBIG;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
@ -393,7 +393,7 @@ xfs_mount_validate_sb(
|
|||
xfs_sb_validate_fsb_count(sbp, sbp->sb_rblocks)) {
|
||||
xfs_fs_mount_cmn_err(flags,
|
||||
"file system too large to be mounted on this system.");
|
||||
return XFS_ERROR(E2BIG);
|
||||
return XFS_ERROR(EFBIG);
|
||||
}
|
||||
|
||||
if (unlikely(sbp->sb_inprogress)) {
|
||||
|
@ -413,17 +413,6 @@ xfs_mount_validate_sb(
|
|||
return 0;
|
||||
}
|
||||
|
||||
STATIC void
|
||||
xfs_initialize_perag_icache(
|
||||
xfs_perag_t *pag)
|
||||
{
|
||||
if (!pag->pag_ici_init) {
|
||||
rwlock_init(&pag->pag_ici_lock);
|
||||
INIT_RADIX_TREE(&pag->pag_ici_root, GFP_ATOMIC);
|
||||
pag->pag_ici_init = 1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
xfs_initialize_perag(
|
||||
xfs_mount_t *mp,
|
||||
|
@ -436,13 +425,8 @@ xfs_initialize_perag(
|
|||
xfs_agino_t agino;
|
||||
xfs_ino_t ino;
|
||||
xfs_sb_t *sbp = &mp->m_sb;
|
||||
xfs_ino_t max_inum = XFS_MAXINUMBER_32;
|
||||
int error = -ENOMEM;
|
||||
|
||||
/* Check to see if the filesystem can overflow 32 bit inodes */
|
||||
agino = XFS_OFFBNO_TO_AGINO(mp, sbp->sb_agblocks - 1, 0);
|
||||
ino = XFS_AGINO_TO_INO(mp, agcount - 1, agino);
|
||||
|
||||
/*
|
||||
* Walk the current per-ag tree so we don't try to initialise AGs
|
||||
* that already exist (growfs case). Allocate and insert all the
|
||||
|
@ -456,11 +440,18 @@ xfs_initialize_perag(
|
|||
}
|
||||
if (!first_initialised)
|
||||
first_initialised = index;
|
||||
|
||||
pag = kmem_zalloc(sizeof(*pag), KM_MAYFAIL);
|
||||
if (!pag)
|
||||
goto out_unwind;
|
||||
pag->pag_agno = index;
|
||||
pag->pag_mount = mp;
|
||||
rwlock_init(&pag->pag_ici_lock);
|
||||
INIT_RADIX_TREE(&pag->pag_ici_root, GFP_ATOMIC);
|
||||
|
||||
if (radix_tree_preload(GFP_NOFS))
|
||||
goto out_unwind;
|
||||
|
||||
spin_lock(&mp->m_perag_lock);
|
||||
if (radix_tree_insert(&mp->m_perag_tree, index, pag)) {
|
||||
BUG();
|
||||
|
@ -469,25 +460,26 @@ xfs_initialize_perag(
|
|||
error = -EEXIST;
|
||||
goto out_unwind;
|
||||
}
|
||||
pag->pag_agno = index;
|
||||
pag->pag_mount = mp;
|
||||
spin_unlock(&mp->m_perag_lock);
|
||||
radix_tree_preload_end();
|
||||
}
|
||||
|
||||
/* Clear the mount flag if no inode can overflow 32 bits
|
||||
* on this filesystem, or if specifically requested..
|
||||
/*
|
||||
* If we mount with the inode64 option, or no inode overflows
|
||||
* the legacy 32-bit address space clear the inode32 option.
|
||||
*/
|
||||
if ((mp->m_flags & XFS_MOUNT_SMALL_INUMS) && ino > max_inum) {
|
||||
mp->m_flags |= XFS_MOUNT_32BITINODES;
|
||||
} else {
|
||||
mp->m_flags &= ~XFS_MOUNT_32BITINODES;
|
||||
}
|
||||
agino = XFS_OFFBNO_TO_AGINO(mp, sbp->sb_agblocks - 1, 0);
|
||||
ino = XFS_AGINO_TO_INO(mp, agcount - 1, agino);
|
||||
|
||||
if ((mp->m_flags & XFS_MOUNT_SMALL_INUMS) && ino > XFS_MAXINUMBER_32)
|
||||
mp->m_flags |= XFS_MOUNT_32BITINODES;
|
||||
else
|
||||
mp->m_flags &= ~XFS_MOUNT_32BITINODES;
|
||||
|
||||
/* If we can overflow then setup the ag headers accordingly */
|
||||
if (mp->m_flags & XFS_MOUNT_32BITINODES) {
|
||||
/* Calculate how much should be reserved for inodes to
|
||||
* meet the max inode percentage.
|
||||
/*
|
||||
* Calculate how much should be reserved for inodes to meet
|
||||
* the max inode percentage.
|
||||
*/
|
||||
if (mp->m_maxicount) {
|
||||
__uint64_t icount;
|
||||
|
@ -500,30 +492,28 @@ xfs_initialize_perag(
|
|||
} else {
|
||||
max_metadata = agcount;
|
||||
}
|
||||
|
||||
for (index = 0; index < agcount; index++) {
|
||||
ino = XFS_AGINO_TO_INO(mp, index, agino);
|
||||
if (ino > max_inum) {
|
||||
if (ino > XFS_MAXINUMBER_32) {
|
||||
index++;
|
||||
break;
|
||||
}
|
||||
|
||||
/* This ag is preferred for inodes */
|
||||
pag = xfs_perag_get(mp, index);
|
||||
pag->pagi_inodeok = 1;
|
||||
if (index < max_metadata)
|
||||
pag->pagf_metadata = 1;
|
||||
xfs_initialize_perag_icache(pag);
|
||||
xfs_perag_put(pag);
|
||||
}
|
||||
} else {
|
||||
/* Setup default behavior for smaller filesystems */
|
||||
for (index = 0; index < agcount; index++) {
|
||||
pag = xfs_perag_get(mp, index);
|
||||
pag->pagi_inodeok = 1;
|
||||
xfs_initialize_perag_icache(pag);
|
||||
xfs_perag_put(pag);
|
||||
}
|
||||
}
|
||||
|
||||
if (maxagi)
|
||||
*maxagi = index;
|
||||
return 0;
|
||||
|
@ -1009,7 +999,7 @@ xfs_check_sizes(xfs_mount_t *mp)
|
|||
d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks);
|
||||
if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_dblocks) {
|
||||
cmn_err(CE_WARN, "XFS: size check 1 failed");
|
||||
return XFS_ERROR(E2BIG);
|
||||
return XFS_ERROR(EFBIG);
|
||||
}
|
||||
error = xfs_read_buf(mp, mp->m_ddev_targp,
|
||||
d - XFS_FSS_TO_BB(mp, 1),
|
||||
|
@ -1019,7 +1009,7 @@ xfs_check_sizes(xfs_mount_t *mp)
|
|||
} else {
|
||||
cmn_err(CE_WARN, "XFS: size check 2 failed");
|
||||
if (error == ENOSPC)
|
||||
error = XFS_ERROR(E2BIG);
|
||||
error = XFS_ERROR(EFBIG);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -1027,7 +1017,7 @@ xfs_check_sizes(xfs_mount_t *mp)
|
|||
d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks);
|
||||
if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_logblocks) {
|
||||
cmn_err(CE_WARN, "XFS: size check 3 failed");
|
||||
return XFS_ERROR(E2BIG);
|
||||
return XFS_ERROR(EFBIG);
|
||||
}
|
||||
error = xfs_read_buf(mp, mp->m_logdev_targp,
|
||||
d - XFS_FSB_TO_BB(mp, 1),
|
||||
|
@ -1037,7 +1027,7 @@ xfs_check_sizes(xfs_mount_t *mp)
|
|||
} else {
|
||||
cmn_err(CE_WARN, "XFS: size check 3 failed");
|
||||
if (error == ENOSPC)
|
||||
error = XFS_ERROR(E2BIG);
|
||||
error = XFS_ERROR(EFBIG);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
@ -1254,7 +1244,7 @@ xfs_mountfs(
|
|||
* Allocate and initialize the per-ag data.
|
||||
*/
|
||||
spin_lock_init(&mp->m_perag_lock);
|
||||
INIT_RADIX_TREE(&mp->m_perag_tree, GFP_NOFS);
|
||||
INIT_RADIX_TREE(&mp->m_perag_tree, GFP_ATOMIC);
|
||||
error = xfs_initialize_perag(mp, sbp->sb_agcount, &mp->m_maxagi);
|
||||
if (error) {
|
||||
cmn_err(CE_WARN, "XFS: Failed per-ag init: %d", error);
|
||||
|
|
|
@ -2247,7 +2247,7 @@ xfs_rtmount_init(
|
|||
cmn_err(CE_WARN, "XFS: realtime mount -- %llu != %llu",
|
||||
(unsigned long long) XFS_BB_TO_FSB(mp, d),
|
||||
(unsigned long long) mp->m_sb.sb_rblocks);
|
||||
return XFS_ERROR(E2BIG);
|
||||
return XFS_ERROR(EFBIG);
|
||||
}
|
||||
error = xfs_read_buf(mp, mp->m_rtdev_targp,
|
||||
d - XFS_FSB_TO_BB(mp, 1),
|
||||
|
@ -2256,7 +2256,7 @@ xfs_rtmount_init(
|
|||
cmn_err(CE_WARN,
|
||||
"XFS: realtime mount -- xfs_read_buf failed, returned %d", error);
|
||||
if (error == ENOSPC)
|
||||
return XFS_ERROR(E2BIG);
|
||||
return XFS_ERROR(EFBIG);
|
||||
return error;
|
||||
}
|
||||
xfs_buf_relse(bp);
|
||||
|
|
|
@ -147,7 +147,16 @@ xfs_growfs_rt(
|
|||
# define xfs_rtfree_extent(t,b,l) (ENOSYS)
|
||||
# define xfs_rtpick_extent(m,t,l,rb) (ENOSYS)
|
||||
# define xfs_growfs_rt(mp,in) (ENOSYS)
|
||||
# define xfs_rtmount_init(m) (((mp)->m_sb.sb_rblocks == 0)? 0 : (ENOSYS))
|
||||
static inline int /* error */
|
||||
xfs_rtmount_init(
|
||||
xfs_mount_t *mp) /* file system mount structure */
|
||||
{
|
||||
if (mp->m_sb.sb_rblocks == 0)
|
||||
return 0;
|
||||
|
||||
cmn_err(CE_WARN, "XFS: Not built with CONFIG_XFS_RT");
|
||||
return ENOSYS;
|
||||
}
|
||||
# define xfs_rtmount_inodes(m) (((mp)->m_sb.sb_rblocks == 0)? 0 : (ENOSYS))
|
||||
# define xfs_rtunmount_inodes(m)
|
||||
#endif /* CONFIG_XFS_RT */
|
||||
|
|
|
@ -48,134 +48,489 @@
|
|||
|
||||
kmem_zone_t *xfs_trans_zone;
|
||||
|
||||
|
||||
/*
|
||||
* Reservation functions here avoid a huge stack in xfs_trans_init
|
||||
* due to register overflow from temporaries in the calculations.
|
||||
* Various log reservation values.
|
||||
*
|
||||
* These are based on the size of the file system block because that is what
|
||||
* most transactions manipulate. Each adds in an additional 128 bytes per
|
||||
* item logged to try to account for the overhead of the transaction mechanism.
|
||||
*
|
||||
* Note: Most of the reservations underestimate the number of allocation
|
||||
* groups into which they could free extents in the xfs_bmap_finish() call.
|
||||
* This is because the number in the worst case is quite high and quite
|
||||
* unusual. In order to fix this we need to change xfs_bmap_finish() to free
|
||||
* extents in only a single AG at a time. This will require changes to the
|
||||
* EFI code as well, however, so that the EFI for the extents not freed is
|
||||
* logged again in each transaction. See SGI PV #261917.
|
||||
*
|
||||
* Reservation functions here avoid a huge stack in xfs_trans_init due to
|
||||
* register overflow from temporaries in the calculations.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* In a write transaction we can allocate a maximum of 2
|
||||
* extents. This gives:
|
||||
* the inode getting the new extents: inode size
|
||||
* the inode's bmap btree: max depth * block size
|
||||
* the agfs of the ags from which the extents are allocated: 2 * sector
|
||||
* the superblock free block counter: sector size
|
||||
* the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
|
||||
* And the bmap_finish transaction can free bmap blocks in a join:
|
||||
* the agfs of the ags containing the blocks: 2 * sector size
|
||||
* the agfls of the ags containing the blocks: 2 * sector size
|
||||
* the super block free block counter: sector size
|
||||
* the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
|
||||
*/
|
||||
STATIC uint
|
||||
xfs_calc_write_reservation(xfs_mount_t *mp)
|
||||
xfs_calc_write_reservation(
|
||||
struct xfs_mount *mp)
|
||||
{
|
||||
return XFS_CALC_WRITE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
|
||||
return XFS_DQUOT_LOGRES(mp) +
|
||||
MAX((mp->m_sb.sb_inodesize +
|
||||
XFS_FSB_TO_B(mp, XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK)) +
|
||||
2 * mp->m_sb.sb_sectsize +
|
||||
mp->m_sb.sb_sectsize +
|
||||
XFS_ALLOCFREE_LOG_RES(mp, 2) +
|
||||
128 * (4 + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) +
|
||||
XFS_ALLOCFREE_LOG_COUNT(mp, 2))),
|
||||
(2 * mp->m_sb.sb_sectsize +
|
||||
2 * mp->m_sb.sb_sectsize +
|
||||
mp->m_sb.sb_sectsize +
|
||||
XFS_ALLOCFREE_LOG_RES(mp, 2) +
|
||||
128 * (5 + XFS_ALLOCFREE_LOG_COUNT(mp, 2))));
|
||||
}
|
||||
|
||||
/*
|
||||
* In truncating a file we free up to two extents at once. We can modify:
|
||||
* the inode being truncated: inode size
|
||||
* the inode's bmap btree: (max depth + 1) * block size
|
||||
* And the bmap_finish transaction can free the blocks and bmap blocks:
|
||||
* the agf for each of the ags: 4 * sector size
|
||||
* the agfl for each of the ags: 4 * sector size
|
||||
* the super block to reflect the freed blocks: sector size
|
||||
* worst case split in allocation btrees per extent assuming 4 extents:
|
||||
* 4 exts * 2 trees * (2 * max depth - 1) * block size
|
||||
* the inode btree: max depth * blocksize
|
||||
* the allocation btrees: 2 trees * (max depth - 1) * block size
|
||||
*/
|
||||
STATIC uint
|
||||
xfs_calc_itruncate_reservation(xfs_mount_t *mp)
|
||||
xfs_calc_itruncate_reservation(
|
||||
struct xfs_mount *mp)
|
||||
{
|
||||
return XFS_CALC_ITRUNCATE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
|
||||
return XFS_DQUOT_LOGRES(mp) +
|
||||
MAX((mp->m_sb.sb_inodesize +
|
||||
XFS_FSB_TO_B(mp, XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + 1) +
|
||||
128 * (2 + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK))),
|
||||
(4 * mp->m_sb.sb_sectsize +
|
||||
4 * mp->m_sb.sb_sectsize +
|
||||
mp->m_sb.sb_sectsize +
|
||||
XFS_ALLOCFREE_LOG_RES(mp, 4) +
|
||||
128 * (9 + XFS_ALLOCFREE_LOG_COUNT(mp, 4)) +
|
||||
128 * 5 +
|
||||
XFS_ALLOCFREE_LOG_RES(mp, 1) +
|
||||
128 * (2 + XFS_IALLOC_BLOCKS(mp) + mp->m_in_maxlevels +
|
||||
XFS_ALLOCFREE_LOG_COUNT(mp, 1))));
|
||||
}
|
||||
|
||||
/*
|
||||
* In renaming a files we can modify:
|
||||
* the four inodes involved: 4 * inode size
|
||||
* the two directory btrees: 2 * (max depth + v2) * dir block size
|
||||
* the two directory bmap btrees: 2 * max depth * block size
|
||||
* And the bmap_finish transaction can free dir and bmap blocks (two sets
|
||||
* of bmap blocks) giving:
|
||||
* the agf for the ags in which the blocks live: 3 * sector size
|
||||
* the agfl for the ags in which the blocks live: 3 * sector size
|
||||
* the superblock for the free block count: sector size
|
||||
* the allocation btrees: 3 exts * 2 trees * (2 * max depth - 1) * block size
|
||||
*/
|
||||
STATIC uint
|
||||
xfs_calc_rename_reservation(xfs_mount_t *mp)
|
||||
xfs_calc_rename_reservation(
|
||||
struct xfs_mount *mp)
|
||||
{
|
||||
return XFS_CALC_RENAME_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
|
||||
return XFS_DQUOT_LOGRES(mp) +
|
||||
MAX((4 * mp->m_sb.sb_inodesize +
|
||||
2 * XFS_DIROP_LOG_RES(mp) +
|
||||
128 * (4 + 2 * XFS_DIROP_LOG_COUNT(mp))),
|
||||
(3 * mp->m_sb.sb_sectsize +
|
||||
3 * mp->m_sb.sb_sectsize +
|
||||
mp->m_sb.sb_sectsize +
|
||||
XFS_ALLOCFREE_LOG_RES(mp, 3) +
|
||||
128 * (7 + XFS_ALLOCFREE_LOG_COUNT(mp, 3))));
|
||||
}
|
||||
|
||||
/*
|
||||
* For creating a link to an inode:
|
||||
* the parent directory inode: inode size
|
||||
* the linked inode: inode size
|
||||
* the directory btree could split: (max depth + v2) * dir block size
|
||||
* the directory bmap btree could join or split: (max depth + v2) * blocksize
|
||||
* And the bmap_finish transaction can free some bmap blocks giving:
|
||||
* the agf for the ag in which the blocks live: sector size
|
||||
* the agfl for the ag in which the blocks live: sector size
|
||||
* the superblock for the free block count: sector size
|
||||
* the allocation btrees: 2 trees * (2 * max depth - 1) * block size
|
||||
*/
|
||||
STATIC uint
|
||||
xfs_calc_link_reservation(xfs_mount_t *mp)
|
||||
xfs_calc_link_reservation(
|
||||
struct xfs_mount *mp)
|
||||
{
|
||||
return XFS_CALC_LINK_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
|
||||
return XFS_DQUOT_LOGRES(mp) +
|
||||
MAX((mp->m_sb.sb_inodesize +
|
||||
mp->m_sb.sb_inodesize +
|
||||
XFS_DIROP_LOG_RES(mp) +
|
||||
128 * (2 + XFS_DIROP_LOG_COUNT(mp))),
|
||||
(mp->m_sb.sb_sectsize +
|
||||
mp->m_sb.sb_sectsize +
|
||||
mp->m_sb.sb_sectsize +
|
||||
XFS_ALLOCFREE_LOG_RES(mp, 1) +
|
||||
128 * (3 + XFS_ALLOCFREE_LOG_COUNT(mp, 1))));
|
||||
}
|
||||
|
||||
/*
|
||||
* For removing a directory entry we can modify:
|
||||
* the parent directory inode: inode size
|
||||
* the removed inode: inode size
|
||||
* the directory btree could join: (max depth + v2) * dir block size
|
||||
* the directory bmap btree could join or split: (max depth + v2) * blocksize
|
||||
* And the bmap_finish transaction can free the dir and bmap blocks giving:
|
||||
* the agf for the ag in which the blocks live: 2 * sector size
|
||||
* the agfl for the ag in which the blocks live: 2 * sector size
|
||||
* the superblock for the free block count: sector size
|
||||
* the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
|
||||
*/
|
||||
STATIC uint
|
||||
xfs_calc_remove_reservation(xfs_mount_t *mp)
|
||||
xfs_calc_remove_reservation(
|
||||
struct xfs_mount *mp)
|
||||
{
|
||||
return XFS_CALC_REMOVE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
|
||||
return XFS_DQUOT_LOGRES(mp) +
|
||||
MAX((mp->m_sb.sb_inodesize +
|
||||
mp->m_sb.sb_inodesize +
|
||||
XFS_DIROP_LOG_RES(mp) +
|
||||
128 * (2 + XFS_DIROP_LOG_COUNT(mp))),
|
||||
(2 * mp->m_sb.sb_sectsize +
|
||||
2 * mp->m_sb.sb_sectsize +
|
||||
mp->m_sb.sb_sectsize +
|
||||
XFS_ALLOCFREE_LOG_RES(mp, 2) +
|
||||
128 * (5 + XFS_ALLOCFREE_LOG_COUNT(mp, 2))));
|
||||
}
|
||||
|
||||
/*
|
||||
* For symlink we can modify:
|
||||
* the parent directory inode: inode size
|
||||
* the new inode: inode size
|
||||
* the inode btree entry: 1 block
|
||||
* the directory btree: (max depth + v2) * dir block size
|
||||
* the directory inode's bmap btree: (max depth + v2) * block size
|
||||
* the blocks for the symlink: 1 kB
|
||||
* Or in the first xact we allocate some inodes giving:
|
||||
* the agi and agf of the ag getting the new inodes: 2 * sectorsize
|
||||
* the inode blocks allocated: XFS_IALLOC_BLOCKS * blocksize
|
||||
* the inode btree: max depth * blocksize
|
||||
* the allocation btrees: 2 trees * (2 * max depth - 1) * block size
|
||||
*/
|
||||
STATIC uint
|
||||
xfs_calc_symlink_reservation(xfs_mount_t *mp)
|
||||
xfs_calc_symlink_reservation(
|
||||
struct xfs_mount *mp)
|
||||
{
|
||||
return XFS_CALC_SYMLINK_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
|
||||
return XFS_DQUOT_LOGRES(mp) +
|
||||
MAX((mp->m_sb.sb_inodesize +
|
||||
mp->m_sb.sb_inodesize +
|
||||
XFS_FSB_TO_B(mp, 1) +
|
||||
XFS_DIROP_LOG_RES(mp) +
|
||||
1024 +
|
||||
128 * (4 + XFS_DIROP_LOG_COUNT(mp))),
|
||||
(2 * mp->m_sb.sb_sectsize +
|
||||
XFS_FSB_TO_B(mp, XFS_IALLOC_BLOCKS(mp)) +
|
||||
XFS_FSB_TO_B(mp, mp->m_in_maxlevels) +
|
||||
XFS_ALLOCFREE_LOG_RES(mp, 1) +
|
||||
128 * (2 + XFS_IALLOC_BLOCKS(mp) + mp->m_in_maxlevels +
|
||||
XFS_ALLOCFREE_LOG_COUNT(mp, 1))));
|
||||
}
|
||||
|
||||
/*
|
||||
* For create we can modify:
|
||||
* the parent directory inode: inode size
|
||||
* the new inode: inode size
|
||||
* the inode btree entry: block size
|
||||
* the superblock for the nlink flag: sector size
|
||||
* the directory btree: (max depth + v2) * dir block size
|
||||
* the directory inode's bmap btree: (max depth + v2) * block size
|
||||
* Or in the first xact we allocate some inodes giving:
|
||||
* the agi and agf of the ag getting the new inodes: 2 * sectorsize
|
||||
* the superblock for the nlink flag: sector size
|
||||
* the inode blocks allocated: XFS_IALLOC_BLOCKS * blocksize
|
||||
* the inode btree: max depth * blocksize
|
||||
* the allocation btrees: 2 trees * (max depth - 1) * block size
|
||||
*/
|
||||
STATIC uint
|
||||
xfs_calc_create_reservation(xfs_mount_t *mp)
|
||||
xfs_calc_create_reservation(
|
||||
struct xfs_mount *mp)
|
||||
{
|
||||
return XFS_CALC_CREATE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
|
||||
return XFS_DQUOT_LOGRES(mp) +
|
||||
MAX((mp->m_sb.sb_inodesize +
|
||||
mp->m_sb.sb_inodesize +
|
||||
mp->m_sb.sb_sectsize +
|
||||
XFS_FSB_TO_B(mp, 1) +
|
||||
XFS_DIROP_LOG_RES(mp) +
|
||||
128 * (3 + XFS_DIROP_LOG_COUNT(mp))),
|
||||
(3 * mp->m_sb.sb_sectsize +
|
||||
XFS_FSB_TO_B(mp, XFS_IALLOC_BLOCKS(mp)) +
|
||||
XFS_FSB_TO_B(mp, mp->m_in_maxlevels) +
|
||||
XFS_ALLOCFREE_LOG_RES(mp, 1) +
|
||||
128 * (2 + XFS_IALLOC_BLOCKS(mp) + mp->m_in_maxlevels +
|
||||
XFS_ALLOCFREE_LOG_COUNT(mp, 1))));
|
||||
}
|
||||
|
||||
/*
|
||||
* Making a new directory is the same as creating a new file.
|
||||
*/
|
||||
STATIC uint
|
||||
xfs_calc_mkdir_reservation(xfs_mount_t *mp)
|
||||
xfs_calc_mkdir_reservation(
|
||||
struct xfs_mount *mp)
|
||||
{
|
||||
return XFS_CALC_MKDIR_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
|
||||
return xfs_calc_create_reservation(mp);
|
||||
}
|
||||
|
||||
/*
|
||||
* In freeing an inode we can modify:
|
||||
* the inode being freed: inode size
|
||||
* the super block free inode counter: sector size
|
||||
* the agi hash list and counters: sector size
|
||||
* the inode btree entry: block size
|
||||
* the on disk inode before ours in the agi hash list: inode cluster size
|
||||
* the inode btree: max depth * blocksize
|
||||
* the allocation btrees: 2 trees * (max depth - 1) * block size
|
||||
*/
|
||||
STATIC uint
|
||||
xfs_calc_ifree_reservation(xfs_mount_t *mp)
|
||||
xfs_calc_ifree_reservation(
|
||||
struct xfs_mount *mp)
|
||||
{
|
||||
return XFS_CALC_IFREE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
|
||||
return XFS_DQUOT_LOGRES(mp) +
|
||||
mp->m_sb.sb_inodesize +
|
||||
mp->m_sb.sb_sectsize +
|
||||
mp->m_sb.sb_sectsize +
|
||||
XFS_FSB_TO_B(mp, 1) +
|
||||
MAX((__uint16_t)XFS_FSB_TO_B(mp, 1),
|
||||
XFS_INODE_CLUSTER_SIZE(mp)) +
|
||||
128 * 5 +
|
||||
XFS_ALLOCFREE_LOG_RES(mp, 1) +
|
||||
128 * (2 + XFS_IALLOC_BLOCKS(mp) + mp->m_in_maxlevels +
|
||||
XFS_ALLOCFREE_LOG_COUNT(mp, 1));
|
||||
}
|
||||
|
||||
/*
|
||||
* When only changing the inode we log the inode and possibly the superblock
|
||||
* We also add a bit of slop for the transaction stuff.
|
||||
*/
|
||||
STATIC uint
|
||||
xfs_calc_ichange_reservation(xfs_mount_t *mp)
|
||||
xfs_calc_ichange_reservation(
|
||||
struct xfs_mount *mp)
|
||||
{
|
||||
return XFS_CALC_ICHANGE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
|
||||
return XFS_DQUOT_LOGRES(mp) +
|
||||
mp->m_sb.sb_inodesize +
|
||||
mp->m_sb.sb_sectsize +
|
||||
512;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Growing the data section of the filesystem.
|
||||
* superblock
|
||||
* agi and agf
|
||||
* allocation btrees
|
||||
*/
|
||||
STATIC uint
|
||||
xfs_calc_growdata_reservation(xfs_mount_t *mp)
|
||||
xfs_calc_growdata_reservation(
|
||||
struct xfs_mount *mp)
|
||||
{
|
||||
return XFS_CALC_GROWDATA_LOG_RES(mp);
|
||||
return mp->m_sb.sb_sectsize * 3 +
|
||||
XFS_ALLOCFREE_LOG_RES(mp, 1) +
|
||||
128 * (3 + XFS_ALLOCFREE_LOG_COUNT(mp, 1));
|
||||
}
|
||||
|
||||
/*
|
||||
* Growing the rt section of the filesystem.
|
||||
* In the first set of transactions (ALLOC) we allocate space to the
|
||||
* bitmap or summary files.
|
||||
* superblock: sector size
|
||||
* agf of the ag from which the extent is allocated: sector size
|
||||
* bmap btree for bitmap/summary inode: max depth * blocksize
|
||||
* bitmap/summary inode: inode size
|
||||
* allocation btrees for 1 block alloc: 2 * (2 * maxdepth - 1) * blocksize
|
||||
*/
|
||||
STATIC uint
|
||||
xfs_calc_growrtalloc_reservation(xfs_mount_t *mp)
|
||||
xfs_calc_growrtalloc_reservation(
|
||||
struct xfs_mount *mp)
|
||||
{
|
||||
return XFS_CALC_GROWRTALLOC_LOG_RES(mp);
|
||||
return 2 * mp->m_sb.sb_sectsize +
|
||||
XFS_FSB_TO_B(mp, XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK)) +
|
||||
mp->m_sb.sb_inodesize +
|
||||
XFS_ALLOCFREE_LOG_RES(mp, 1) +
|
||||
128 * (3 + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) +
|
||||
XFS_ALLOCFREE_LOG_COUNT(mp, 1));
|
||||
}
|
||||
|
||||
/*
|
||||
* Growing the rt section of the filesystem.
|
||||
* In the second set of transactions (ZERO) we zero the new metadata blocks.
|
||||
* one bitmap/summary block: blocksize
|
||||
*/
|
||||
STATIC uint
|
||||
xfs_calc_growrtzero_reservation(xfs_mount_t *mp)
|
||||
xfs_calc_growrtzero_reservation(
|
||||
struct xfs_mount *mp)
|
||||
{
|
||||
return XFS_CALC_GROWRTZERO_LOG_RES(mp);
|
||||
return mp->m_sb.sb_blocksize + 128;
|
||||
}
|
||||
|
||||
/*
|
||||
* Growing the rt section of the filesystem.
|
||||
* In the third set of transactions (FREE) we update metadata without
|
||||
* allocating any new blocks.
|
||||
* superblock: sector size
|
||||
* bitmap inode: inode size
|
||||
* summary inode: inode size
|
||||
* one bitmap block: blocksize
|
||||
* summary blocks: new summary size
|
||||
*/
|
||||
STATIC uint
|
||||
xfs_calc_growrtfree_reservation(xfs_mount_t *mp)
|
||||
xfs_calc_growrtfree_reservation(
|
||||
struct xfs_mount *mp)
|
||||
{
|
||||
return XFS_CALC_GROWRTFREE_LOG_RES(mp);
|
||||
return mp->m_sb.sb_sectsize +
|
||||
2 * mp->m_sb.sb_inodesize +
|
||||
mp->m_sb.sb_blocksize +
|
||||
mp->m_rsumsize +
|
||||
128 * 5;
|
||||
}
|
||||
|
||||
/*
|
||||
* Logging the inode modification timestamp on a synchronous write.
|
||||
* inode
|
||||
*/
|
||||
STATIC uint
|
||||
xfs_calc_swrite_reservation(xfs_mount_t *mp)
|
||||
xfs_calc_swrite_reservation(
|
||||
struct xfs_mount *mp)
|
||||
{
|
||||
return XFS_CALC_SWRITE_LOG_RES(mp);
|
||||
return mp->m_sb.sb_inodesize + 128;
|
||||
}
|
||||
|
||||
/*
|
||||
* Logging the inode mode bits when writing a setuid/setgid file
|
||||
* inode
|
||||
*/
|
||||
STATIC uint
|
||||
xfs_calc_writeid_reservation(xfs_mount_t *mp)
|
||||
{
|
||||
return XFS_CALC_WRITEID_LOG_RES(mp);
|
||||
return mp->m_sb.sb_inodesize + 128;
|
||||
}
|
||||
|
||||
/*
|
||||
* Converting the inode from non-attributed to attributed.
|
||||
* the inode being converted: inode size
|
||||
* agf block and superblock (for block allocation)
|
||||
* the new block (directory sized)
|
||||
* bmap blocks for the new directory block
|
||||
* allocation btrees
|
||||
*/
|
||||
STATIC uint
|
||||
xfs_calc_addafork_reservation(xfs_mount_t *mp)
|
||||
xfs_calc_addafork_reservation(
|
||||
struct xfs_mount *mp)
|
||||
{
|
||||
return XFS_CALC_ADDAFORK_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
|
||||
return XFS_DQUOT_LOGRES(mp) +
|
||||
mp->m_sb.sb_inodesize +
|
||||
mp->m_sb.sb_sectsize * 2 +
|
||||
mp->m_dirblksize +
|
||||
XFS_FSB_TO_B(mp, XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1) +
|
||||
XFS_ALLOCFREE_LOG_RES(mp, 1) +
|
||||
128 * (4 + XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1 +
|
||||
XFS_ALLOCFREE_LOG_COUNT(mp, 1));
|
||||
}
|
||||
|
||||
/*
|
||||
* Removing the attribute fork of a file
|
||||
* the inode being truncated: inode size
|
||||
* the inode's bmap btree: max depth * block size
|
||||
* And the bmap_finish transaction can free the blocks and bmap blocks:
|
||||
* the agf for each of the ags: 4 * sector size
|
||||
* the agfl for each of the ags: 4 * sector size
|
||||
* the super block to reflect the freed blocks: sector size
|
||||
* worst case split in allocation btrees per extent assuming 4 extents:
|
||||
* 4 exts * 2 trees * (2 * max depth - 1) * block size
|
||||
*/
|
||||
STATIC uint
|
||||
xfs_calc_attrinval_reservation(xfs_mount_t *mp)
|
||||
xfs_calc_attrinval_reservation(
|
||||
struct xfs_mount *mp)
|
||||
{
|
||||
return XFS_CALC_ATTRINVAL_LOG_RES(mp);
|
||||
return MAX((mp->m_sb.sb_inodesize +
|
||||
XFS_FSB_TO_B(mp, XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)) +
|
||||
128 * (1 + XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK))),
|
||||
(4 * mp->m_sb.sb_sectsize +
|
||||
4 * mp->m_sb.sb_sectsize +
|
||||
mp->m_sb.sb_sectsize +
|
||||
XFS_ALLOCFREE_LOG_RES(mp, 4) +
|
||||
128 * (9 + XFS_ALLOCFREE_LOG_COUNT(mp, 4))));
|
||||
}
|
||||
|
||||
/*
|
||||
* Setting an attribute.
|
||||
* the inode getting the attribute
|
||||
* the superblock for allocations
|
||||
* the agfs extents are allocated from
|
||||
* the attribute btree * max depth
|
||||
* the inode allocation btree
|
||||
* Since attribute transaction space is dependent on the size of the attribute,
|
||||
* the calculation is done partially at mount time and partially at runtime.
|
||||
*/
|
||||
STATIC uint
|
||||
xfs_calc_attrset_reservation(xfs_mount_t *mp)
|
||||
xfs_calc_attrset_reservation(
|
||||
struct xfs_mount *mp)
|
||||
{
|
||||
return XFS_CALC_ATTRSET_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
|
||||
return XFS_DQUOT_LOGRES(mp) +
|
||||
mp->m_sb.sb_inodesize +
|
||||
mp->m_sb.sb_sectsize +
|
||||
XFS_FSB_TO_B(mp, XFS_DA_NODE_MAXDEPTH) +
|
||||
128 * (2 + XFS_DA_NODE_MAXDEPTH);
|
||||
}
|
||||
|
||||
/*
|
||||
* Removing an attribute.
|
||||
* the inode: inode size
|
||||
* the attribute btree could join: max depth * block size
|
||||
* the inode bmap btree could join or split: max depth * block size
|
||||
* And the bmap_finish transaction can free the attr blocks freed giving:
|
||||
* the agf for the ag in which the blocks live: 2 * sector size
|
||||
* the agfl for the ag in which the blocks live: 2 * sector size
|
||||
* the superblock for the free block count: sector size
|
||||
* the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
|
||||
*/
|
||||
STATIC uint
|
||||
xfs_calc_attrrm_reservation(xfs_mount_t *mp)
|
||||
xfs_calc_attrrm_reservation(
|
||||
struct xfs_mount *mp)
|
||||
{
|
||||
return XFS_CALC_ATTRRM_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
|
||||
return XFS_DQUOT_LOGRES(mp) +
|
||||
MAX((mp->m_sb.sb_inodesize +
|
||||
XFS_FSB_TO_B(mp, XFS_DA_NODE_MAXDEPTH) +
|
||||
XFS_FSB_TO_B(mp, XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)) +
|
||||
128 * (1 + XFS_DA_NODE_MAXDEPTH +
|
||||
XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK))),
|
||||
(2 * mp->m_sb.sb_sectsize +
|
||||
2 * mp->m_sb.sb_sectsize +
|
||||
mp->m_sb.sb_sectsize +
|
||||
XFS_ALLOCFREE_LOG_RES(mp, 2) +
|
||||
128 * (5 + XFS_ALLOCFREE_LOG_COUNT(mp, 2))));
|
||||
}
|
||||
|
||||
/*
|
||||
* Clearing a bad agino number in an agi hash bucket.
|
||||
*/
|
||||
STATIC uint
|
||||
xfs_calc_clear_agi_bucket_reservation(xfs_mount_t *mp)
|
||||
xfs_calc_clear_agi_bucket_reservation(
|
||||
struct xfs_mount *mp)
|
||||
{
|
||||
return XFS_CALC_CLEAR_AGI_BUCKET_LOG_RES(mp);
|
||||
return mp->m_sb.sb_sectsize + 128;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -184,11 +539,10 @@ xfs_calc_clear_agi_bucket_reservation(xfs_mount_t *mp)
|
|||
*/
|
||||
void
|
||||
xfs_trans_init(
|
||||
xfs_mount_t *mp)
|
||||
struct xfs_mount *mp)
|
||||
{
|
||||
xfs_trans_reservations_t *resp;
|
||||
struct xfs_trans_reservations *resp = &mp->m_reservations;
|
||||
|
||||
resp = &(mp->m_reservations);
|
||||
resp->tr_write = xfs_calc_write_reservation(mp);
|
||||
resp->tr_itruncate = xfs_calc_itruncate_reservation(mp);
|
||||
resp->tr_rename = xfs_calc_rename_reservation(mp);
|
||||
|
|
|
@ -299,24 +299,6 @@ xfs_lic_desc_to_chunk(xfs_log_item_desc_t *dp)
|
|||
#define XFS_TRANS_SB_REXTSLOG 0x00002000
|
||||
|
||||
|
||||
/*
|
||||
* Various log reservation values.
|
||||
* These are based on the size of the file system block
|
||||
* because that is what most transactions manipulate.
|
||||
* Each adds in an additional 128 bytes per item logged to
|
||||
* try to account for the overhead of the transaction mechanism.
|
||||
*
|
||||
* Note:
|
||||
* Most of the reservations underestimate the number of allocation
|
||||
* groups into which they could free extents in the xfs_bmap_finish()
|
||||
* call. This is because the number in the worst case is quite high
|
||||
* and quite unusual. In order to fix this we need to change
|
||||
* xfs_bmap_finish() to free extents in only a single AG at a time.
|
||||
* This will require changes to the EFI code as well, however, so that
|
||||
* the EFI for the extents not freed is logged again in each transaction.
|
||||
* See bug 261917.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Per-extent log reservation for the allocation btree changes
|
||||
* involved in freeing or allocating an extent.
|
||||
|
@ -341,429 +323,36 @@ xfs_lic_desc_to_chunk(xfs_log_item_desc_t *dp)
|
|||
(XFS_DAENTER_BLOCKS(mp, XFS_DATA_FORK) + \
|
||||
XFS_DAENTER_BMAPS(mp, XFS_DATA_FORK) + 1)
|
||||
|
||||
/*
|
||||
* In a write transaction we can allocate a maximum of 2
|
||||
* extents. This gives:
|
||||
* the inode getting the new extents: inode size
|
||||
* the inode's bmap btree: max depth * block size
|
||||
* the agfs of the ags from which the extents are allocated: 2 * sector
|
||||
* the superblock free block counter: sector size
|
||||
* the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
|
||||
* And the bmap_finish transaction can free bmap blocks in a join:
|
||||
* the agfs of the ags containing the blocks: 2 * sector size
|
||||
* the agfls of the ags containing the blocks: 2 * sector size
|
||||
* the super block free block counter: sector size
|
||||
* the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
|
||||
*/
|
||||
#define XFS_CALC_WRITE_LOG_RES(mp) \
|
||||
(MAX( \
|
||||
((mp)->m_sb.sb_inodesize + \
|
||||
XFS_FSB_TO_B((mp), XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK)) + \
|
||||
(2 * (mp)->m_sb.sb_sectsize) + \
|
||||
(mp)->m_sb.sb_sectsize + \
|
||||
XFS_ALLOCFREE_LOG_RES(mp, 2) + \
|
||||
(128 * (4 + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + XFS_ALLOCFREE_LOG_COUNT(mp, 2)))),\
|
||||
((2 * (mp)->m_sb.sb_sectsize) + \
|
||||
(2 * (mp)->m_sb.sb_sectsize) + \
|
||||
(mp)->m_sb.sb_sectsize + \
|
||||
XFS_ALLOCFREE_LOG_RES(mp, 2) + \
|
||||
(128 * (5 + XFS_ALLOCFREE_LOG_COUNT(mp, 2))))))
|
||||
|
||||
#define XFS_WRITE_LOG_RES(mp) ((mp)->m_reservations.tr_write)
|
||||
|
||||
/*
|
||||
* In truncating a file we free up to two extents at once. We can modify:
|
||||
* the inode being truncated: inode size
|
||||
* the inode's bmap btree: (max depth + 1) * block size
|
||||
* And the bmap_finish transaction can free the blocks and bmap blocks:
|
||||
* the agf for each of the ags: 4 * sector size
|
||||
* the agfl for each of the ags: 4 * sector size
|
||||
* the super block to reflect the freed blocks: sector size
|
||||
* worst case split in allocation btrees per extent assuming 4 extents:
|
||||
* 4 exts * 2 trees * (2 * max depth - 1) * block size
|
||||
* the inode btree: max depth * blocksize
|
||||
* the allocation btrees: 2 trees * (max depth - 1) * block size
|
||||
*/
|
||||
#define XFS_CALC_ITRUNCATE_LOG_RES(mp) \
|
||||
(MAX( \
|
||||
((mp)->m_sb.sb_inodesize + \
|
||||
XFS_FSB_TO_B((mp), XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + 1) + \
|
||||
(128 * (2 + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK)))), \
|
||||
((4 * (mp)->m_sb.sb_sectsize) + \
|
||||
(4 * (mp)->m_sb.sb_sectsize) + \
|
||||
(mp)->m_sb.sb_sectsize + \
|
||||
XFS_ALLOCFREE_LOG_RES(mp, 4) + \
|
||||
(128 * (9 + XFS_ALLOCFREE_LOG_COUNT(mp, 4))) + \
|
||||
(128 * 5) + \
|
||||
XFS_ALLOCFREE_LOG_RES(mp, 1) + \
|
||||
(128 * (2 + XFS_IALLOC_BLOCKS(mp) + (mp)->m_in_maxlevels + \
|
||||
XFS_ALLOCFREE_LOG_COUNT(mp, 1))))))
|
||||
|
||||
#define XFS_ITRUNCATE_LOG_RES(mp) ((mp)->m_reservations.tr_itruncate)
|
||||
|
||||
/*
|
||||
* In renaming a files we can modify:
|
||||
* the four inodes involved: 4 * inode size
|
||||
* the two directory btrees: 2 * (max depth + v2) * dir block size
|
||||
* the two directory bmap btrees: 2 * max depth * block size
|
||||
* And the bmap_finish transaction can free dir and bmap blocks (two sets
|
||||
* of bmap blocks) giving:
|
||||
* the agf for the ags in which the blocks live: 3 * sector size
|
||||
* the agfl for the ags in which the blocks live: 3 * sector size
|
||||
* the superblock for the free block count: sector size
|
||||
* the allocation btrees: 3 exts * 2 trees * (2 * max depth - 1) * block size
|
||||
*/
|
||||
#define XFS_CALC_RENAME_LOG_RES(mp) \
|
||||
(MAX( \
|
||||
((4 * (mp)->m_sb.sb_inodesize) + \
|
||||
(2 * XFS_DIROP_LOG_RES(mp)) + \
|
||||
(128 * (4 + 2 * XFS_DIROP_LOG_COUNT(mp)))), \
|
||||
((3 * (mp)->m_sb.sb_sectsize) + \
|
||||
(3 * (mp)->m_sb.sb_sectsize) + \
|
||||
(mp)->m_sb.sb_sectsize + \
|
||||
XFS_ALLOCFREE_LOG_RES(mp, 3) + \
|
||||
(128 * (7 + XFS_ALLOCFREE_LOG_COUNT(mp, 3))))))
|
||||
|
||||
#define XFS_RENAME_LOG_RES(mp) ((mp)->m_reservations.tr_rename)
|
||||
|
||||
/*
|
||||
* For creating a link to an inode:
|
||||
* the parent directory inode: inode size
|
||||
* the linked inode: inode size
|
||||
* the directory btree could split: (max depth + v2) * dir block size
|
||||
* the directory bmap btree could join or split: (max depth + v2) * blocksize
|
||||
* And the bmap_finish transaction can free some bmap blocks giving:
|
||||
* the agf for the ag in which the blocks live: sector size
|
||||
* the agfl for the ag in which the blocks live: sector size
|
||||
* the superblock for the free block count: sector size
|
||||
* the allocation btrees: 2 trees * (2 * max depth - 1) * block size
|
||||
*/
|
||||
#define XFS_CALC_LINK_LOG_RES(mp) \
|
||||
(MAX( \
|
||||
((mp)->m_sb.sb_inodesize + \
|
||||
(mp)->m_sb.sb_inodesize + \
|
||||
XFS_DIROP_LOG_RES(mp) + \
|
||||
(128 * (2 + XFS_DIROP_LOG_COUNT(mp)))), \
|
||||
((mp)->m_sb.sb_sectsize + \
|
||||
(mp)->m_sb.sb_sectsize + \
|
||||
(mp)->m_sb.sb_sectsize + \
|
||||
XFS_ALLOCFREE_LOG_RES(mp, 1) + \
|
||||
(128 * (3 + XFS_ALLOCFREE_LOG_COUNT(mp, 1))))))
|
||||
|
||||
#define XFS_LINK_LOG_RES(mp) ((mp)->m_reservations.tr_link)
|
||||
|
||||
/*
|
||||
* For removing a directory entry we can modify:
|
||||
* the parent directory inode: inode size
|
||||
* the removed inode: inode size
|
||||
* the directory btree could join: (max depth + v2) * dir block size
|
||||
* the directory bmap btree could join or split: (max depth + v2) * blocksize
|
||||
* And the bmap_finish transaction can free the dir and bmap blocks giving:
|
||||
* the agf for the ag in which the blocks live: 2 * sector size
|
||||
* the agfl for the ag in which the blocks live: 2 * sector size
|
||||
* the superblock for the free block count: sector size
|
||||
* the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
|
||||
*/
|
||||
#define XFS_CALC_REMOVE_LOG_RES(mp) \
|
||||
(MAX( \
|
||||
((mp)->m_sb.sb_inodesize + \
|
||||
(mp)->m_sb.sb_inodesize + \
|
||||
XFS_DIROP_LOG_RES(mp) + \
|
||||
(128 * (2 + XFS_DIROP_LOG_COUNT(mp)))), \
|
||||
((2 * (mp)->m_sb.sb_sectsize) + \
|
||||
(2 * (mp)->m_sb.sb_sectsize) + \
|
||||
(mp)->m_sb.sb_sectsize + \
|
||||
XFS_ALLOCFREE_LOG_RES(mp, 2) + \
|
||||
(128 * (5 + XFS_ALLOCFREE_LOG_COUNT(mp, 2))))))
|
||||
|
||||
#define XFS_REMOVE_LOG_RES(mp) ((mp)->m_reservations.tr_remove)
|
||||
|
||||
/*
|
||||
* For symlink we can modify:
|
||||
* the parent directory inode: inode size
|
||||
* the new inode: inode size
|
||||
* the inode btree entry: 1 block
|
||||
* the directory btree: (max depth + v2) * dir block size
|
||||
* the directory inode's bmap btree: (max depth + v2) * block size
|
||||
* the blocks for the symlink: 1 kB
|
||||
* Or in the first xact we allocate some inodes giving:
|
||||
* the agi and agf of the ag getting the new inodes: 2 * sectorsize
|
||||
* the inode blocks allocated: XFS_IALLOC_BLOCKS * blocksize
|
||||
* the inode btree: max depth * blocksize
|
||||
* the allocation btrees: 2 trees * (2 * max depth - 1) * block size
|
||||
*/
|
||||
#define XFS_CALC_SYMLINK_LOG_RES(mp) \
|
||||
(MAX( \
|
||||
((mp)->m_sb.sb_inodesize + \
|
||||
(mp)->m_sb.sb_inodesize + \
|
||||
XFS_FSB_TO_B(mp, 1) + \
|
||||
XFS_DIROP_LOG_RES(mp) + \
|
||||
1024 + \
|
||||
(128 * (4 + XFS_DIROP_LOG_COUNT(mp)))), \
|
||||
(2 * (mp)->m_sb.sb_sectsize + \
|
||||
XFS_FSB_TO_B((mp), XFS_IALLOC_BLOCKS((mp))) + \
|
||||
XFS_FSB_TO_B((mp), (mp)->m_in_maxlevels) + \
|
||||
XFS_ALLOCFREE_LOG_RES(mp, 1) + \
|
||||
(128 * (2 + XFS_IALLOC_BLOCKS(mp) + (mp)->m_in_maxlevels + \
|
||||
XFS_ALLOCFREE_LOG_COUNT(mp, 1))))))
|
||||
|
||||
#define XFS_SYMLINK_LOG_RES(mp) ((mp)->m_reservations.tr_symlink)
|
||||
|
||||
/*
|
||||
* For create we can modify:
|
||||
* the parent directory inode: inode size
|
||||
* the new inode: inode size
|
||||
* the inode btree entry: block size
|
||||
* the superblock for the nlink flag: sector size
|
||||
* the directory btree: (max depth + v2) * dir block size
|
||||
* the directory inode's bmap btree: (max depth + v2) * block size
|
||||
* Or in the first xact we allocate some inodes giving:
|
||||
* the agi and agf of the ag getting the new inodes: 2 * sectorsize
|
||||
* the superblock for the nlink flag: sector size
|
||||
* the inode blocks allocated: XFS_IALLOC_BLOCKS * blocksize
|
||||
* the inode btree: max depth * blocksize
|
||||
* the allocation btrees: 2 trees * (max depth - 1) * block size
|
||||
*/
|
||||
#define XFS_CALC_CREATE_LOG_RES(mp) \
|
||||
(MAX( \
|
||||
((mp)->m_sb.sb_inodesize + \
|
||||
(mp)->m_sb.sb_inodesize + \
|
||||
(mp)->m_sb.sb_sectsize + \
|
||||
XFS_FSB_TO_B(mp, 1) + \
|
||||
XFS_DIROP_LOG_RES(mp) + \
|
||||
(128 * (3 + XFS_DIROP_LOG_COUNT(mp)))), \
|
||||
(3 * (mp)->m_sb.sb_sectsize + \
|
||||
XFS_FSB_TO_B((mp), XFS_IALLOC_BLOCKS((mp))) + \
|
||||
XFS_FSB_TO_B((mp), (mp)->m_in_maxlevels) + \
|
||||
XFS_ALLOCFREE_LOG_RES(mp, 1) + \
|
||||
(128 * (2 + XFS_IALLOC_BLOCKS(mp) + (mp)->m_in_maxlevels + \
|
||||
XFS_ALLOCFREE_LOG_COUNT(mp, 1))))))
|
||||
|
||||
#define XFS_CREATE_LOG_RES(mp) ((mp)->m_reservations.tr_create)
|
||||
|
||||
/*
|
||||
* Making a new directory is the same as creating a new file.
|
||||
*/
|
||||
#define XFS_CALC_MKDIR_LOG_RES(mp) XFS_CALC_CREATE_LOG_RES(mp)
|
||||
|
||||
#define XFS_MKDIR_LOG_RES(mp) ((mp)->m_reservations.tr_mkdir)
|
||||
|
||||
/*
|
||||
* In freeing an inode we can modify:
|
||||
* the inode being freed: inode size
|
||||
* the super block free inode counter: sector size
|
||||
* the agi hash list and counters: sector size
|
||||
* the inode btree entry: block size
|
||||
* the on disk inode before ours in the agi hash list: inode cluster size
|
||||
* the inode btree: max depth * blocksize
|
||||
* the allocation btrees: 2 trees * (max depth - 1) * block size
|
||||
*/
|
||||
#define XFS_CALC_IFREE_LOG_RES(mp) \
|
||||
((mp)->m_sb.sb_inodesize + \
|
||||
(mp)->m_sb.sb_sectsize + \
|
||||
(mp)->m_sb.sb_sectsize + \
|
||||
XFS_FSB_TO_B((mp), 1) + \
|
||||
MAX((__uint16_t)XFS_FSB_TO_B((mp), 1), XFS_INODE_CLUSTER_SIZE(mp)) + \
|
||||
(128 * 5) + \
|
||||
XFS_ALLOCFREE_LOG_RES(mp, 1) + \
|
||||
(128 * (2 + XFS_IALLOC_BLOCKS(mp) + (mp)->m_in_maxlevels + \
|
||||
XFS_ALLOCFREE_LOG_COUNT(mp, 1))))
|
||||
|
||||
|
||||
#define XFS_IFREE_LOG_RES(mp) ((mp)->m_reservations.tr_ifree)
|
||||
|
||||
/*
|
||||
* When only changing the inode we log the inode and possibly the superblock
|
||||
* We also add a bit of slop for the transaction stuff.
|
||||
*/
|
||||
#define XFS_CALC_ICHANGE_LOG_RES(mp) ((mp)->m_sb.sb_inodesize + \
|
||||
(mp)->m_sb.sb_sectsize + 512)
|
||||
|
||||
#define XFS_ICHANGE_LOG_RES(mp) ((mp)->m_reservations.tr_ichange)
|
||||
|
||||
/*
|
||||
* Growing the data section of the filesystem.
|
||||
* superblock
|
||||
* agi and agf
|
||||
* allocation btrees
|
||||
*/
|
||||
#define XFS_CALC_GROWDATA_LOG_RES(mp) \
|
||||
((mp)->m_sb.sb_sectsize * 3 + \
|
||||
XFS_ALLOCFREE_LOG_RES(mp, 1) + \
|
||||
(128 * (3 + XFS_ALLOCFREE_LOG_COUNT(mp, 1))))
|
||||
|
||||
#define XFS_GROWDATA_LOG_RES(mp) ((mp)->m_reservations.tr_growdata)
|
||||
|
||||
/*
|
||||
* Growing the rt section of the filesystem.
|
||||
* In the first set of transactions (ALLOC) we allocate space to the
|
||||
* bitmap or summary files.
|
||||
* superblock: sector size
|
||||
* agf of the ag from which the extent is allocated: sector size
|
||||
* bmap btree for bitmap/summary inode: max depth * blocksize
|
||||
* bitmap/summary inode: inode size
|
||||
* allocation btrees for 1 block alloc: 2 * (2 * maxdepth - 1) * blocksize
|
||||
*/
|
||||
#define XFS_CALC_GROWRTALLOC_LOG_RES(mp) \
|
||||
(2 * (mp)->m_sb.sb_sectsize + \
|
||||
XFS_FSB_TO_B((mp), XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK)) + \
|
||||
(mp)->m_sb.sb_inodesize + \
|
||||
XFS_ALLOCFREE_LOG_RES(mp, 1) + \
|
||||
(128 * \
|
||||
(3 + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + \
|
||||
XFS_ALLOCFREE_LOG_COUNT(mp, 1))))
|
||||
|
||||
#define XFS_GROWRTALLOC_LOG_RES(mp) ((mp)->m_reservations.tr_growrtalloc)
|
||||
|
||||
/*
|
||||
* Growing the rt section of the filesystem.
|
||||
* In the second set of transactions (ZERO) we zero the new metadata blocks.
|
||||
* one bitmap/summary block: blocksize
|
||||
*/
|
||||
#define XFS_CALC_GROWRTZERO_LOG_RES(mp) \
|
||||
((mp)->m_sb.sb_blocksize + 128)
|
||||
|
||||
#define XFS_GROWRTZERO_LOG_RES(mp) ((mp)->m_reservations.tr_growrtzero)
|
||||
|
||||
/*
|
||||
* Growing the rt section of the filesystem.
|
||||
* In the third set of transactions (FREE) we update metadata without
|
||||
* allocating any new blocks.
|
||||
* superblock: sector size
|
||||
* bitmap inode: inode size
|
||||
* summary inode: inode size
|
||||
* one bitmap block: blocksize
|
||||
* summary blocks: new summary size
|
||||
*/
|
||||
#define XFS_CALC_GROWRTFREE_LOG_RES(mp) \
|
||||
((mp)->m_sb.sb_sectsize + \
|
||||
2 * (mp)->m_sb.sb_inodesize + \
|
||||
(mp)->m_sb.sb_blocksize + \
|
||||
(mp)->m_rsumsize + \
|
||||
(128 * 5))
|
||||
|
||||
#define XFS_GROWRTFREE_LOG_RES(mp) ((mp)->m_reservations.tr_growrtfree)
|
||||
|
||||
/*
|
||||
* Logging the inode modification timestamp on a synchronous write.
|
||||
* inode
|
||||
*/
|
||||
#define XFS_CALC_SWRITE_LOG_RES(mp) \
|
||||
((mp)->m_sb.sb_inodesize + 128)
|
||||
|
||||
#define XFS_SWRITE_LOG_RES(mp) ((mp)->m_reservations.tr_swrite)
|
||||
|
||||
/*
|
||||
* Logging the inode timestamps on an fsync -- same as SWRITE
|
||||
* as long as SWRITE logs the entire inode core
|
||||
*/
|
||||
#define XFS_FSYNC_TS_LOG_RES(mp) ((mp)->m_reservations.tr_swrite)
|
||||
|
||||
/*
|
||||
* Logging the inode mode bits when writing a setuid/setgid file
|
||||
* inode
|
||||
*/
|
||||
#define XFS_CALC_WRITEID_LOG_RES(mp) \
|
||||
((mp)->m_sb.sb_inodesize + 128)
|
||||
|
||||
#define XFS_WRITEID_LOG_RES(mp) ((mp)->m_reservations.tr_swrite)
|
||||
|
||||
/*
|
||||
* Converting the inode from non-attributed to attributed.
|
||||
* the inode being converted: inode size
|
||||
* agf block and superblock (for block allocation)
|
||||
* the new block (directory sized)
|
||||
* bmap blocks for the new directory block
|
||||
* allocation btrees
|
||||
*/
|
||||
#define XFS_CALC_ADDAFORK_LOG_RES(mp) \
|
||||
((mp)->m_sb.sb_inodesize + \
|
||||
(mp)->m_sb.sb_sectsize * 2 + \
|
||||
(mp)->m_dirblksize + \
|
||||
XFS_FSB_TO_B(mp, (XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1)) + \
|
||||
XFS_ALLOCFREE_LOG_RES(mp, 1) + \
|
||||
(128 * (4 + (XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1) + \
|
||||
XFS_ALLOCFREE_LOG_COUNT(mp, 1))))
|
||||
|
||||
#define XFS_ADDAFORK_LOG_RES(mp) ((mp)->m_reservations.tr_addafork)
|
||||
|
||||
/*
|
||||
* Removing the attribute fork of a file
|
||||
* the inode being truncated: inode size
|
||||
* the inode's bmap btree: max depth * block size
|
||||
* And the bmap_finish transaction can free the blocks and bmap blocks:
|
||||
* the agf for each of the ags: 4 * sector size
|
||||
* the agfl for each of the ags: 4 * sector size
|
||||
* the super block to reflect the freed blocks: sector size
|
||||
* worst case split in allocation btrees per extent assuming 4 extents:
|
||||
* 4 exts * 2 trees * (2 * max depth - 1) * block size
|
||||
*/
|
||||
#define XFS_CALC_ATTRINVAL_LOG_RES(mp) \
|
||||
(MAX( \
|
||||
((mp)->m_sb.sb_inodesize + \
|
||||
XFS_FSB_TO_B((mp), XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)) + \
|
||||
(128 * (1 + XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)))), \
|
||||
((4 * (mp)->m_sb.sb_sectsize) + \
|
||||
(4 * (mp)->m_sb.sb_sectsize) + \
|
||||
(mp)->m_sb.sb_sectsize + \
|
||||
XFS_ALLOCFREE_LOG_RES(mp, 4) + \
|
||||
(128 * (9 + XFS_ALLOCFREE_LOG_COUNT(mp, 4))))))
|
||||
|
||||
#define XFS_ATTRINVAL_LOG_RES(mp) ((mp)->m_reservations.tr_attrinval)
|
||||
|
||||
/*
|
||||
* Setting an attribute.
|
||||
* the inode getting the attribute
|
||||
* the superblock for allocations
|
||||
* the agfs extents are allocated from
|
||||
* the attribute btree * max depth
|
||||
* the inode allocation btree
|
||||
* Since attribute transaction space is dependent on the size of the attribute,
|
||||
* the calculation is done partially at mount time and partially at runtime.
|
||||
*/
|
||||
#define XFS_CALC_ATTRSET_LOG_RES(mp) \
|
||||
((mp)->m_sb.sb_inodesize + \
|
||||
(mp)->m_sb.sb_sectsize + \
|
||||
XFS_FSB_TO_B((mp), XFS_DA_NODE_MAXDEPTH) + \
|
||||
(128 * (2 + XFS_DA_NODE_MAXDEPTH)))
|
||||
|
||||
#define XFS_ATTRSET_LOG_RES(mp, ext) \
|
||||
((mp)->m_reservations.tr_attrset + \
|
||||
(ext * (mp)->m_sb.sb_sectsize) + \
|
||||
(ext * XFS_FSB_TO_B((mp), XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK))) + \
|
||||
(128 * (ext + (ext * XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)))))
|
||||
|
||||
/*
|
||||
* Removing an attribute.
|
||||
* the inode: inode size
|
||||
* the attribute btree could join: max depth * block size
|
||||
* the inode bmap btree could join or split: max depth * block size
|
||||
* And the bmap_finish transaction can free the attr blocks freed giving:
|
||||
* the agf for the ag in which the blocks live: 2 * sector size
|
||||
* the agfl for the ag in which the blocks live: 2 * sector size
|
||||
* the superblock for the free block count: sector size
|
||||
* the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
|
||||
*/
|
||||
#define XFS_CALC_ATTRRM_LOG_RES(mp) \
|
||||
(MAX( \
|
||||
((mp)->m_sb.sb_inodesize + \
|
||||
XFS_FSB_TO_B((mp), XFS_DA_NODE_MAXDEPTH) + \
|
||||
XFS_FSB_TO_B((mp), XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)) + \
|
||||
(128 * (1 + XFS_DA_NODE_MAXDEPTH + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK)))), \
|
||||
((2 * (mp)->m_sb.sb_sectsize) + \
|
||||
(2 * (mp)->m_sb.sb_sectsize) + \
|
||||
(mp)->m_sb.sb_sectsize + \
|
||||
XFS_ALLOCFREE_LOG_RES(mp, 2) + \
|
||||
(128 * (5 + XFS_ALLOCFREE_LOG_COUNT(mp, 2))))))
|
||||
|
||||
#define XFS_ATTRRM_LOG_RES(mp) ((mp)->m_reservations.tr_attrrm)
|
||||
|
||||
/*
|
||||
* Clearing a bad agino number in an agi hash bucket.
|
||||
*/
|
||||
#define XFS_CALC_CLEAR_AGI_BUCKET_LOG_RES(mp) \
|
||||
((mp)->m_sb.sb_sectsize + 128)
|
||||
|
||||
#define XFS_CLEAR_AGI_BUCKET_LOG_RES(mp) ((mp)->m_reservations.tr_clearagi)
|
||||
|
||||
|
||||
|
|
|
@ -267,7 +267,7 @@ xfs_setattr(
|
|||
if (code) {
|
||||
ASSERT(tp == NULL);
|
||||
lock_flags &= ~XFS_ILOCK_EXCL;
|
||||
ASSERT(lock_flags == XFS_IOLOCK_EXCL);
|
||||
ASSERT(lock_flags == XFS_IOLOCK_EXCL || !need_iolock);
|
||||
goto error_return;
|
||||
}
|
||||
tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_SIZE);
|
||||
|
|
Загрузка…
Ссылка в новой задаче